1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2007-2009 Google Inc. and Amit Singh 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following disclaimer 15 * in the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Google Inc. nor the names of its 18 * contributors may be used to endorse or promote products derived from 19 * this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * Copyright (C) 2005 Csaba Henk. 34 * All rights reserved. 35 * 36 * Copyright (c) 2019 The FreeBSD Foundation 37 * 38 * Portions of this software were developed by BFF Storage Systems, LLC under 39 * sponsorship from the FreeBSD Foundation. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 50 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60 * SUCH DAMAGE. 61 */ 62 63 #include <sys/cdefs.h> 64 __FBSDID("$FreeBSD$"); 65 66 #include <sys/param.h> 67 #include <sys/module.h> 68 #include <sys/systm.h> 69 #include <sys/errno.h> 70 #include <sys/kernel.h> 71 #include <sys/conf.h> 72 #include <sys/filio.h> 73 #include <sys/uio.h> 74 #include <sys/malloc.h> 75 #include <sys/queue.h> 76 #include <sys/limits.h> 77 #include <sys/lock.h> 78 #include <sys/rwlock.h> 79 #include <sys/sx.h> 80 #include <sys/proc.h> 81 #include <sys/mount.h> 82 #include <sys/vnode.h> 83 #include <sys/namei.h> 84 #include <sys/extattr.h> 85 #include <sys/stat.h> 86 #include <sys/unistd.h> 87 #include <sys/filedesc.h> 88 #include <sys/file.h> 89 #include <sys/fcntl.h> 90 #include <sys/dirent.h> 91 #include <sys/bio.h> 92 #include <sys/buf.h> 93 #include <sys/sysctl.h> 94 #include <sys/vmmeter.h> 95 96 #include <vm/vm.h> 97 #include <vm/vm_extern.h> 98 #include <vm/pmap.h> 99 #include <vm/vm_map.h> 100 #include <vm/vm_page.h> 101 #include <vm/vm_param.h> 102 #include <vm/vm_object.h> 103 #include <vm/vm_pager.h> 104 #include <vm/vnode_pager.h> 105 #include <vm/vm_object.h> 106 107 #include "fuse.h" 108 #include "fuse_file.h" 109 #include "fuse_internal.h" 110 #include "fuse_ipc.h" 111 #include "fuse_node.h" 112 #include "fuse_io.h" 113 114 #include <sys/priv.h> 115 116 /* Maximum number of hardlinks to a single FUSE file */ 117 #define FUSE_LINK_MAX UINT32_MAX 118 119 SDT_PROVIDER_DECLARE(fusefs); 120 /* 121 * Fuse trace probe: 122 * arg0: verbosity. Higher numbers give more verbose messages 123 * arg1: Textual message 124 */ 125 SDT_PROBE_DEFINE2(fusefs, , vnops, trace, "int", "char*"); 126 127 /* vnode ops */ 128 static vop_access_t fuse_vnop_access; 129 static vop_advlock_t fuse_vnop_advlock; 130 static vop_allocate_t fuse_vnop_allocate; 131 static vop_bmap_t fuse_vnop_bmap; 132 static vop_close_t fuse_fifo_close; 133 static vop_close_t fuse_vnop_close; 134 static vop_copy_file_range_t fuse_vnop_copy_file_range; 135 static vop_create_t fuse_vnop_create; 136 static vop_deleteextattr_t fuse_vnop_deleteextattr; 137 static vop_fdatasync_t fuse_vnop_fdatasync; 138 static vop_fsync_t fuse_vnop_fsync; 139 static vop_getattr_t fuse_vnop_getattr; 140 static vop_getextattr_t fuse_vnop_getextattr; 141 static vop_inactive_t fuse_vnop_inactive; 142 static vop_ioctl_t fuse_vnop_ioctl; 143 static vop_link_t fuse_vnop_link; 144 static vop_listextattr_t fuse_vnop_listextattr; 145 static vop_lookup_t fuse_vnop_lookup; 146 static vop_mkdir_t fuse_vnop_mkdir; 147 static vop_mknod_t fuse_vnop_mknod; 148 static vop_open_t fuse_vnop_open; 149 static vop_pathconf_t fuse_vnop_pathconf; 150 static vop_read_t fuse_vnop_read; 151 static vop_readdir_t fuse_vnop_readdir; 152 static vop_readlink_t fuse_vnop_readlink; 153 static vop_reclaim_t fuse_vnop_reclaim; 154 static vop_remove_t fuse_vnop_remove; 155 static vop_rename_t fuse_vnop_rename; 156 static vop_rmdir_t fuse_vnop_rmdir; 157 static vop_setattr_t fuse_vnop_setattr; 158 static vop_setextattr_t fuse_vnop_setextattr; 159 static vop_strategy_t fuse_vnop_strategy; 160 static vop_symlink_t fuse_vnop_symlink; 161 static vop_write_t fuse_vnop_write; 162 static vop_getpages_t fuse_vnop_getpages; 163 static vop_print_t fuse_vnop_print; 164 static vop_vptofh_t fuse_vnop_vptofh; 165 166 struct vop_vector fuse_fifoops = { 167 .vop_default = &fifo_specops, 168 .vop_access = fuse_vnop_access, 169 .vop_close = fuse_fifo_close, 170 .vop_fsync = fuse_vnop_fsync, 171 .vop_getattr = fuse_vnop_getattr, 172 .vop_inactive = fuse_vnop_inactive, 173 .vop_pathconf = fuse_vnop_pathconf, 174 .vop_print = fuse_vnop_print, 175 .vop_read = VOP_PANIC, 176 .vop_reclaim = fuse_vnop_reclaim, 177 .vop_setattr = fuse_vnop_setattr, 178 .vop_write = VOP_PANIC, 179 .vop_vptofh = fuse_vnop_vptofh, 180 }; 181 VFS_VOP_VECTOR_REGISTER(fuse_fifoops); 182 183 struct vop_vector fuse_vnops = { 184 .vop_allocate = fuse_vnop_allocate, 185 .vop_default = &default_vnodeops, 186 .vop_access = fuse_vnop_access, 187 .vop_advlock = fuse_vnop_advlock, 188 .vop_bmap = fuse_vnop_bmap, 189 .vop_close = fuse_vnop_close, 190 .vop_copy_file_range = fuse_vnop_copy_file_range, 191 .vop_create = fuse_vnop_create, 192 .vop_deleteextattr = fuse_vnop_deleteextattr, 193 .vop_fsync = fuse_vnop_fsync, 194 .vop_fdatasync = fuse_vnop_fdatasync, 195 .vop_getattr = fuse_vnop_getattr, 196 .vop_getextattr = fuse_vnop_getextattr, 197 .vop_inactive = fuse_vnop_inactive, 198 .vop_ioctl = fuse_vnop_ioctl, 199 .vop_link = fuse_vnop_link, 200 .vop_listextattr = fuse_vnop_listextattr, 201 .vop_lookup = fuse_vnop_lookup, 202 .vop_mkdir = fuse_vnop_mkdir, 203 .vop_mknod = fuse_vnop_mknod, 204 .vop_open = fuse_vnop_open, 205 .vop_pathconf = fuse_vnop_pathconf, 206 /* 207 * TODO: implement vop_poll after upgrading to protocol 7.21. 208 * FUSE_POLL was added in protocol 7.11, but it's kind of broken until 209 * 7.21, which adds the ability for the client to choose which poll 210 * events it wants, and for a client to deregister a file handle 211 */ 212 .vop_read = fuse_vnop_read, 213 .vop_readdir = fuse_vnop_readdir, 214 .vop_readlink = fuse_vnop_readlink, 215 .vop_reclaim = fuse_vnop_reclaim, 216 .vop_remove = fuse_vnop_remove, 217 .vop_rename = fuse_vnop_rename, 218 .vop_rmdir = fuse_vnop_rmdir, 219 .vop_setattr = fuse_vnop_setattr, 220 .vop_setextattr = fuse_vnop_setextattr, 221 .vop_strategy = fuse_vnop_strategy, 222 .vop_symlink = fuse_vnop_symlink, 223 .vop_write = fuse_vnop_write, 224 .vop_getpages = fuse_vnop_getpages, 225 .vop_print = fuse_vnop_print, 226 .vop_vptofh = fuse_vnop_vptofh, 227 }; 228 VFS_VOP_VECTOR_REGISTER(fuse_vnops); 229 230 uma_zone_t fuse_pbuf_zone; 231 232 /* Check permission for extattr operations, much like extattr_check_cred */ 233 static int 234 fuse_extattr_check_cred(struct vnode *vp, int ns, struct ucred *cred, 235 struct thread *td, accmode_t accmode) 236 { 237 struct mount *mp = vnode_mount(vp); 238 struct fuse_data *data = fuse_get_mpdata(mp); 239 int default_permissions = data->dataflags & FSESS_DEFAULT_PERMISSIONS; 240 241 /* 242 * Kernel-invoked always succeeds. 243 */ 244 if (cred == NOCRED) 245 return (0); 246 247 /* 248 * Do not allow privileged processes in jail to directly manipulate 249 * system attributes. 250 */ 251 switch (ns) { 252 case EXTATTR_NAMESPACE_SYSTEM: 253 if (default_permissions) { 254 return (priv_check_cred(cred, PRIV_VFS_EXTATTR_SYSTEM)); 255 } 256 return (0); 257 case EXTATTR_NAMESPACE_USER: 258 if (default_permissions) { 259 return (fuse_internal_access(vp, accmode, td, cred)); 260 } 261 return (0); 262 default: 263 return (EPERM); 264 } 265 } 266 267 /* Get a filehandle for a directory */ 268 static int 269 fuse_filehandle_get_dir(struct vnode *vp, struct fuse_filehandle **fufhp, 270 struct ucred *cred, pid_t pid) 271 { 272 if (fuse_filehandle_get(vp, FREAD, fufhp, cred, pid) == 0) 273 return 0; 274 return fuse_filehandle_get(vp, FEXEC, fufhp, cred, pid); 275 } 276 277 /* Send FUSE_FLUSH for this vnode */ 278 static int 279 fuse_flush(struct vnode *vp, struct ucred *cred, pid_t pid, int fflag) 280 { 281 struct fuse_flush_in *ffi; 282 struct fuse_filehandle *fufh; 283 struct fuse_dispatcher fdi; 284 struct thread *td = curthread; 285 struct mount *mp = vnode_mount(vp); 286 int err; 287 288 if (fsess_not_impl(vnode_mount(vp), FUSE_FLUSH)) 289 return 0; 290 291 err = fuse_filehandle_getrw(vp, fflag, &fufh, cred, pid); 292 if (err) 293 return err; 294 295 fdisp_init(&fdi, sizeof(*ffi)); 296 fdisp_make_vp(&fdi, FUSE_FLUSH, vp, td, cred); 297 ffi = fdi.indata; 298 ffi->fh = fufh->fh_id; 299 /* 300 * If the file has a POSIX lock then we're supposed to set lock_owner. 301 * If not, then lock_owner is undefined. So we may as well always set 302 * it. 303 */ 304 ffi->lock_owner = td->td_proc->p_pid; 305 306 err = fdisp_wait_answ(&fdi); 307 if (err == ENOSYS) { 308 fsess_set_notimpl(mp, FUSE_FLUSH); 309 err = 0; 310 } 311 fdisp_destroy(&fdi); 312 return err; 313 } 314 315 /* Close wrapper for fifos. */ 316 static int 317 fuse_fifo_close(struct vop_close_args *ap) 318 { 319 return (fifo_specops.vop_close(ap)); 320 } 321 322 /* Invalidate a range of cached data, whether dirty of not */ 323 static int 324 fuse_inval_buf_range(struct vnode *vp, off_t filesize, off_t start, off_t end) 325 { 326 struct buf *bp; 327 daddr_t left_lbn, end_lbn, right_lbn; 328 off_t new_filesize; 329 int iosize, left_on, right_on, right_blksize; 330 331 iosize = fuse_iosize(vp); 332 left_lbn = start / iosize; 333 end_lbn = howmany(end, iosize); 334 left_on = start & (iosize - 1); 335 if (left_on != 0) { 336 bp = getblk(vp, left_lbn, iosize, PCATCH, 0, 0); 337 if ((bp->b_flags & B_CACHE) != 0 && bp->b_dirtyend >= left_on) { 338 /* 339 * Flush the dirty buffer, because we don't have a 340 * byte-granular way to record which parts of the 341 * buffer are valid. 342 */ 343 bwrite(bp); 344 if (bp->b_error) 345 return (bp->b_error); 346 } else { 347 brelse(bp); 348 } 349 } 350 right_on = end & (iosize - 1); 351 if (right_on != 0) { 352 right_lbn = end / iosize; 353 new_filesize = MAX(filesize, end); 354 right_blksize = MIN(iosize, new_filesize - iosize * right_lbn); 355 bp = getblk(vp, right_lbn, right_blksize, PCATCH, 0, 0); 356 if ((bp->b_flags & B_CACHE) != 0 && bp->b_dirtyoff < right_on) { 357 /* 358 * Flush the dirty buffer, because we don't have a 359 * byte-granular way to record which parts of the 360 * buffer are valid. 361 */ 362 bwrite(bp); 363 if (bp->b_error) 364 return (bp->b_error); 365 } else { 366 brelse(bp); 367 } 368 } 369 370 v_inval_buf_range(vp, left_lbn, end_lbn, iosize); 371 return (0); 372 } 373 374 375 /* Send FUSE_LSEEK for this node */ 376 static int 377 fuse_vnop_do_lseek(struct vnode *vp, struct thread *td, struct ucred *cred, 378 pid_t pid, off_t *offp, int whence) 379 { 380 struct fuse_dispatcher fdi; 381 struct fuse_filehandle *fufh; 382 struct fuse_lseek_in *flsi; 383 struct fuse_lseek_out *flso; 384 struct mount *mp = vnode_mount(vp); 385 int err; 386 387 ASSERT_VOP_LOCKED(vp, __func__); 388 389 err = fuse_filehandle_getrw(vp, FREAD, &fufh, cred, pid); 390 if (err) 391 return (err); 392 fdisp_init(&fdi, sizeof(*flsi)); 393 fdisp_make_vp(&fdi, FUSE_LSEEK, vp, td, cred); 394 flsi = fdi.indata; 395 flsi->fh = fufh->fh_id; 396 flsi->offset = *offp; 397 flsi->whence = whence; 398 err = fdisp_wait_answ(&fdi); 399 if (err == ENOSYS) { 400 fsess_set_notimpl(mp, FUSE_LSEEK); 401 } else if (err == 0) { 402 fsess_set_impl(mp, FUSE_LSEEK); 403 flso = fdi.answ; 404 *offp = flso->offset; 405 } 406 fdisp_destroy(&fdi); 407 408 return (err); 409 } 410 411 /* 412 struct vnop_access_args { 413 struct vnode *a_vp; 414 #if VOP_ACCESS_TAKES_ACCMODE_T 415 accmode_t a_accmode; 416 #else 417 int a_mode; 418 #endif 419 struct ucred *a_cred; 420 struct thread *a_td; 421 }; 422 */ 423 static int 424 fuse_vnop_access(struct vop_access_args *ap) 425 { 426 struct vnode *vp = ap->a_vp; 427 int accmode = ap->a_accmode; 428 struct ucred *cred = ap->a_cred; 429 430 struct fuse_data *data = fuse_get_mpdata(vnode_mount(vp)); 431 432 int err; 433 434 if (fuse_isdeadfs(vp)) { 435 if (vnode_isvroot(vp)) { 436 return 0; 437 } 438 return ENXIO; 439 } 440 if (!(data->dataflags & FSESS_INITED)) { 441 if (vnode_isvroot(vp)) { 442 if (priv_check_cred(cred, PRIV_VFS_ADMIN) || 443 (fuse_match_cred(data->daemoncred, cred) == 0)) { 444 return 0; 445 } 446 } 447 return EBADF; 448 } 449 if (vnode_islnk(vp)) { 450 return 0; 451 } 452 453 err = fuse_internal_access(vp, accmode, ap->a_td, ap->a_cred); 454 return err; 455 } 456 457 /* 458 * struct vop_advlock_args { 459 * struct vop_generic_args a_gen; 460 * struct vnode *a_vp; 461 * void *a_id; 462 * int a_op; 463 * struct flock *a_fl; 464 * int a_flags; 465 * } 466 */ 467 static int 468 fuse_vnop_advlock(struct vop_advlock_args *ap) 469 { 470 struct vnode *vp = ap->a_vp; 471 struct flock *fl = ap->a_fl; 472 struct thread *td = curthread; 473 struct ucred *cred = td->td_ucred; 474 pid_t pid = td->td_proc->p_pid; 475 struct fuse_filehandle *fufh; 476 struct fuse_dispatcher fdi; 477 struct fuse_lk_in *fli; 478 struct fuse_lk_out *flo; 479 enum fuse_opcode op; 480 int dataflags, err; 481 int flags = ap->a_flags; 482 483 dataflags = fuse_get_mpdata(vnode_mount(vp))->dataflags; 484 485 if (fuse_isdeadfs(vp)) { 486 return ENXIO; 487 } 488 489 switch(ap->a_op) { 490 case F_GETLK: 491 op = FUSE_GETLK; 492 break; 493 case F_SETLK: 494 if (flags & F_WAIT) 495 op = FUSE_SETLKW; 496 else 497 op = FUSE_SETLK; 498 break; 499 case F_UNLCK: 500 op = FUSE_SETLK; 501 break; 502 default: 503 return EINVAL; 504 } 505 506 if (!(dataflags & FSESS_POSIX_LOCKS)) 507 return vop_stdadvlock(ap); 508 /* FUSE doesn't properly support flock until protocol 7.17 */ 509 if (flags & F_FLOCK) 510 return vop_stdadvlock(ap); 511 512 vn_lock(vp, LK_SHARED | LK_RETRY); 513 514 err = fuse_filehandle_get_anyflags(vp, &fufh, cred, pid); 515 if (err) 516 goto out; 517 518 fdisp_init(&fdi, sizeof(*fli)); 519 520 fdisp_make_vp(&fdi, op, vp, td, cred); 521 fli = fdi.indata; 522 fli->fh = fufh->fh_id; 523 fli->owner = td->td_proc->p_pid; 524 fli->lk.start = fl->l_start; 525 if (fl->l_len != 0) 526 fli->lk.end = fl->l_start + fl->l_len - 1; 527 else 528 fli->lk.end = INT64_MAX; 529 fli->lk.type = fl->l_type; 530 fli->lk.pid = td->td_proc->p_pid; 531 532 err = fdisp_wait_answ(&fdi); 533 fdisp_destroy(&fdi); 534 535 if (err == 0 && op == FUSE_GETLK) { 536 flo = fdi.answ; 537 fl->l_type = flo->lk.type; 538 fl->l_pid = flo->lk.pid; 539 if (flo->lk.type != F_UNLCK) { 540 fl->l_start = flo->lk.start; 541 if (flo->lk.end == INT64_MAX) 542 fl->l_len = 0; 543 else 544 fl->l_len = flo->lk.end - flo->lk.start + 1; 545 fl->l_start = flo->lk.start; 546 } 547 } 548 549 out: 550 VOP_UNLOCK(vp); 551 return err; 552 } 553 554 static int 555 fuse_vnop_allocate(struct vop_allocate_args *ap) 556 { 557 struct vnode *vp = ap->a_vp; 558 off_t *len = ap->a_len; 559 off_t *offset = ap->a_offset; 560 struct ucred *cred = ap->a_cred; 561 struct fuse_filehandle *fufh; 562 struct mount *mp = vnode_mount(vp); 563 struct fuse_dispatcher fdi; 564 struct fuse_fallocate_in *ffi; 565 struct uio io; 566 pid_t pid = curthread->td_proc->p_pid; 567 struct fuse_vnode_data *fvdat = VTOFUD(vp); 568 off_t filesize; 569 int err; 570 571 if (fuse_isdeadfs(vp)) 572 return (ENXIO); 573 574 switch (vp->v_type) { 575 case VFIFO: 576 return (ESPIPE); 577 case VLNK: 578 case VREG: 579 if (vfs_isrdonly(mp)) 580 return (EROFS); 581 break; 582 default: 583 return (ENODEV); 584 } 585 586 if (vfs_isrdonly(mp)) 587 return (EROFS); 588 589 if (fsess_not_impl(mp, FUSE_FALLOCATE)) 590 return (EINVAL); 591 592 io.uio_offset = *offset; 593 io.uio_resid = *len; 594 err = vn_rlimit_fsize(vp, &io, curthread); 595 if (err) 596 return (err); 597 598 err = fuse_filehandle_getrw(vp, FWRITE, &fufh, cred, pid); 599 if (err) 600 return (err); 601 602 fuse_vnode_update(vp, FN_MTIMECHANGE | FN_CTIMECHANGE); 603 604 err = fuse_vnode_size(vp, &filesize, cred, curthread); 605 if (err) 606 return (err); 607 fuse_inval_buf_range(vp, filesize, *offset, *offset + *len); 608 609 fdisp_init(&fdi, sizeof(*ffi)); 610 fdisp_make_vp(&fdi, FUSE_FALLOCATE, vp, curthread, cred); 611 ffi = fdi.indata; 612 ffi->fh = fufh->fh_id; 613 ffi->offset = *offset; 614 ffi->length = *len; 615 ffi->mode = 0; 616 err = fdisp_wait_answ(&fdi); 617 618 if (err == ENOSYS) { 619 fsess_set_notimpl(mp, FUSE_FALLOCATE); 620 err = EINVAL; 621 } else if (err == EOPNOTSUPP) { 622 /* 623 * The file system server does not support FUSE_FALLOCATE with 624 * the supplied mode. That's effectively the same thing as 625 * ENOSYS since we only ever issue mode=0. 626 * TODO: revise this section once we support fspacectl. 627 */ 628 fsess_set_notimpl(mp, FUSE_FALLOCATE); 629 err = EINVAL; 630 } else if (!err) { 631 *offset += *len; 632 *len = 0; 633 fuse_vnode_undirty_cached_timestamps(vp, false); 634 fuse_internal_clear_suid_on_write(vp, cred, curthread); 635 if (*offset > fvdat->cached_attrs.va_size) { 636 fuse_vnode_setsize(vp, *offset, false); 637 getnanouptime(&fvdat->last_local_modify); 638 } 639 } 640 641 return (err); 642 } 643 644 /* { 645 struct vnode *a_vp; 646 daddr_t a_bn; 647 struct bufobj **a_bop; 648 daddr_t *a_bnp; 649 int *a_runp; 650 int *a_runb; 651 } */ 652 static int 653 fuse_vnop_bmap(struct vop_bmap_args *ap) 654 { 655 struct vnode *vp = ap->a_vp; 656 struct bufobj **bo = ap->a_bop; 657 struct thread *td = curthread; 658 struct mount *mp; 659 struct fuse_dispatcher fdi; 660 struct fuse_bmap_in *fbi; 661 struct fuse_bmap_out *fbo; 662 struct fuse_data *data; 663 struct fuse_vnode_data *fvdat = VTOFUD(vp); 664 uint64_t biosize; 665 off_t fsize; 666 daddr_t lbn = ap->a_bn; 667 daddr_t *pbn = ap->a_bnp; 668 int *runp = ap->a_runp; 669 int *runb = ap->a_runb; 670 int error = 0; 671 int maxrun; 672 673 if (fuse_isdeadfs(vp)) { 674 return ENXIO; 675 } 676 677 mp = vnode_mount(vp); 678 data = fuse_get_mpdata(mp); 679 biosize = fuse_iosize(vp); 680 maxrun = MIN(vp->v_mount->mnt_iosize_max / biosize - 1, 681 data->max_readahead_blocks); 682 683 if (bo != NULL) 684 *bo = &vp->v_bufobj; 685 686 /* 687 * The FUSE_BMAP operation does not include the runp and runb 688 * variables, so we must guess. Report nonzero contiguous runs so 689 * cluster_read will combine adjacent reads. It's worthwhile to reduce 690 * upcalls even if we don't know the true physical layout of the file. 691 * 692 * FUSE file systems may opt out of read clustering in two ways: 693 * * mounting with -onoclusterr 694 * * Setting max_readahead <= maxbcachebuf during FUSE_INIT 695 */ 696 if (runb != NULL) 697 *runb = MIN(lbn, maxrun); 698 if (runp != NULL && maxrun == 0) 699 *runp = 0; 700 else if (runp != NULL) { 701 /* 702 * If the file's size is cached, use that value to calculate 703 * runp, even if the cache is expired. runp is only advisory, 704 * and the risk of getting it wrong is not worth the cost of 705 * another upcall. 706 */ 707 if (fvdat->cached_attrs.va_size != VNOVAL) 708 fsize = fvdat->cached_attrs.va_size; 709 else 710 error = fuse_vnode_size(vp, &fsize, td->td_ucred, td); 711 if (error == 0) 712 *runp = MIN(MAX(0, fsize / (off_t)biosize - lbn - 1), 713 maxrun); 714 else 715 *runp = 0; 716 } 717 718 if (fsess_maybe_impl(mp, FUSE_BMAP)) { 719 fdisp_init(&fdi, sizeof(*fbi)); 720 fdisp_make_vp(&fdi, FUSE_BMAP, vp, td, td->td_ucred); 721 fbi = fdi.indata; 722 fbi->block = lbn; 723 fbi->blocksize = biosize; 724 error = fdisp_wait_answ(&fdi); 725 if (error == ENOSYS) { 726 fdisp_destroy(&fdi); 727 fsess_set_notimpl(mp, FUSE_BMAP); 728 error = 0; 729 } else { 730 fbo = fdi.answ; 731 if (error == 0 && pbn != NULL) 732 *pbn = fbo->block; 733 fdisp_destroy(&fdi); 734 return error; 735 } 736 } 737 738 /* If the daemon doesn't support BMAP, make up a sensible default */ 739 if (pbn != NULL) 740 *pbn = lbn * btodb(biosize); 741 return (error); 742 } 743 744 /* 745 struct vop_close_args { 746 struct vnode *a_vp; 747 int a_fflag; 748 struct ucred *a_cred; 749 struct thread *a_td; 750 }; 751 */ 752 static int 753 fuse_vnop_close(struct vop_close_args *ap) 754 { 755 struct vnode *vp = ap->a_vp; 756 struct ucred *cred = ap->a_cred; 757 int fflag = ap->a_fflag; 758 struct thread *td = ap->a_td; 759 pid_t pid = td->td_proc->p_pid; 760 struct fuse_vnode_data *fvdat = VTOFUD(vp); 761 int err = 0; 762 763 if (fuse_isdeadfs(vp)) 764 return 0; 765 if (vnode_isdir(vp)) 766 return 0; 767 if (fflag & IO_NDELAY) 768 return 0; 769 770 err = fuse_flush(vp, cred, pid, fflag); 771 if (err == 0 && (fvdat->flag & FN_ATIMECHANGE)) { 772 struct vattr vap; 773 774 VATTR_NULL(&vap); 775 vap.va_atime = fvdat->cached_attrs.va_atime; 776 err = fuse_internal_setattr(vp, &vap, td, NULL); 777 } 778 /* TODO: close the file handle, if we're sure it's no longer used */ 779 if ((fvdat->flag & FN_SIZECHANGE) != 0) { 780 fuse_vnode_savesize(vp, cred, td->td_proc->p_pid); 781 } 782 return err; 783 } 784 785 /* 786 struct vop_copy_file_range_args { 787 struct vop_generic_args a_gen; 788 struct vnode *a_invp; 789 off_t *a_inoffp; 790 struct vnode *a_outvp; 791 off_t *a_outoffp; 792 size_t *a_lenp; 793 unsigned int a_flags; 794 struct ucred *a_incred; 795 struct ucred *a_outcred; 796 struct thread *a_fsizetd; 797 } 798 */ 799 static int 800 fuse_vnop_copy_file_range(struct vop_copy_file_range_args *ap) 801 { 802 struct vnode *invp = ap->a_invp; 803 struct vnode *outvp = ap->a_outvp; 804 struct mount *mp = vnode_mount(invp); 805 struct fuse_vnode_data *outfvdat = VTOFUD(outvp); 806 struct fuse_dispatcher fdi; 807 struct fuse_filehandle *infufh, *outfufh; 808 struct fuse_copy_file_range_in *fcfri; 809 struct ucred *incred = ap->a_incred; 810 struct ucred *outcred = ap->a_outcred; 811 struct fuse_write_out *fwo; 812 struct thread *td; 813 struct uio io; 814 off_t outfilesize; 815 pid_t pid; 816 int err; 817 818 if (mp != vnode_mount(outvp)) 819 goto fallback; 820 821 if (incred->cr_uid != outcred->cr_uid) 822 goto fallback; 823 824 if (incred->cr_groups[0] != outcred->cr_groups[0]) 825 goto fallback; 826 827 if (fsess_not_impl(mp, FUSE_COPY_FILE_RANGE)) 828 goto fallback; 829 830 if (ap->a_fsizetd == NULL) 831 td = curthread; 832 else 833 td = ap->a_fsizetd; 834 pid = td->td_proc->p_pid; 835 836 /* Lock both vnodes, avoiding risk of deadlock. */ 837 do { 838 err = vn_lock(outvp, LK_EXCLUSIVE); 839 if (invp == outvp) 840 break; 841 if (err == 0) { 842 err = vn_lock(invp, LK_SHARED | LK_NOWAIT); 843 if (err == 0) 844 break; 845 VOP_UNLOCK(outvp); 846 err = vn_lock(invp, LK_SHARED); 847 if (err == 0) 848 VOP_UNLOCK(invp); 849 } 850 } while (err == 0); 851 if (err != 0) 852 return (err); 853 854 err = fuse_filehandle_getrw(invp, FREAD, &infufh, incred, pid); 855 if (err) 856 goto unlock; 857 858 err = fuse_filehandle_getrw(outvp, FWRITE, &outfufh, outcred, pid); 859 if (err) 860 goto unlock; 861 862 if (ap->a_fsizetd) { 863 io.uio_offset = *ap->a_outoffp; 864 io.uio_resid = *ap->a_lenp; 865 err = vn_rlimit_fsize(outvp, &io, ap->a_fsizetd); 866 if (err) 867 goto unlock; 868 } 869 870 err = fuse_vnode_size(outvp, &outfilesize, outcred, curthread); 871 if (err) 872 goto unlock; 873 874 err = fuse_inval_buf_range(outvp, outfilesize, *ap->a_outoffp, 875 *ap->a_outoffp + *ap->a_lenp); 876 if (err) 877 goto unlock; 878 879 fdisp_init(&fdi, sizeof(*fcfri)); 880 fdisp_make_vp(&fdi, FUSE_COPY_FILE_RANGE, invp, td, incred); 881 fcfri = fdi.indata; 882 fcfri->fh_in = infufh->fh_id; 883 fcfri->off_in = *ap->a_inoffp; 884 fcfri->nodeid_out = VTOI(outvp); 885 fcfri->fh_out = outfufh->fh_id; 886 fcfri->off_out = *ap->a_outoffp; 887 fcfri->len = *ap->a_lenp; 888 fcfri->flags = 0; 889 890 err = fdisp_wait_answ(&fdi); 891 if (err == 0) { 892 fwo = fdi.answ; 893 *ap->a_lenp = fwo->size; 894 *ap->a_inoffp += fwo->size; 895 *ap->a_outoffp += fwo->size; 896 fuse_internal_clear_suid_on_write(outvp, outcred, td); 897 if (*ap->a_outoffp > outfvdat->cached_attrs.va_size) { 898 fuse_vnode_setsize(outvp, *ap->a_outoffp, false); 899 getnanouptime(&outfvdat->last_local_modify); 900 } 901 fuse_vnode_update(invp, FN_ATIMECHANGE); 902 fuse_vnode_update(outvp, FN_MTIMECHANGE | FN_CTIMECHANGE); 903 } 904 fdisp_destroy(&fdi); 905 906 unlock: 907 if (invp != outvp) 908 VOP_UNLOCK(invp); 909 VOP_UNLOCK(outvp); 910 911 if (err == ENOSYS) { 912 fsess_set_notimpl(mp, FUSE_COPY_FILE_RANGE); 913 fallback: 914 err = vn_generic_copy_file_range(ap->a_invp, ap->a_inoffp, 915 ap->a_outvp, ap->a_outoffp, ap->a_lenp, ap->a_flags, 916 ap->a_incred, ap->a_outcred, ap->a_fsizetd); 917 } 918 919 return (err); 920 } 921 922 static void 923 fdisp_make_mknod_for_fallback( 924 struct fuse_dispatcher *fdip, 925 struct componentname *cnp, 926 struct vnode *dvp, 927 uint64_t parentnid, 928 struct thread *td, 929 struct ucred *cred, 930 mode_t mode, 931 enum fuse_opcode *op) 932 { 933 struct fuse_mknod_in *fmni; 934 935 fdisp_init(fdip, sizeof(*fmni) + cnp->cn_namelen + 1); 936 *op = FUSE_MKNOD; 937 fdisp_make(fdip, *op, vnode_mount(dvp), parentnid, td, cred); 938 fmni = fdip->indata; 939 fmni->mode = mode; 940 fmni->rdev = 0; 941 memcpy((char *)fdip->indata + sizeof(*fmni), cnp->cn_nameptr, 942 cnp->cn_namelen); 943 ((char *)fdip->indata)[sizeof(*fmni) + cnp->cn_namelen] = '\0'; 944 } 945 /* 946 struct vnop_create_args { 947 struct vnode *a_dvp; 948 struct vnode **a_vpp; 949 struct componentname *a_cnp; 950 struct vattr *a_vap; 951 }; 952 */ 953 static int 954 fuse_vnop_create(struct vop_create_args *ap) 955 { 956 struct vnode *dvp = ap->a_dvp; 957 struct vnode **vpp = ap->a_vpp; 958 struct componentname *cnp = ap->a_cnp; 959 struct vattr *vap = ap->a_vap; 960 struct thread *td = curthread; 961 struct ucred *cred = cnp->cn_cred; 962 963 struct fuse_data *data; 964 struct fuse_create_in *fci; 965 struct fuse_entry_out *feo; 966 struct fuse_open_out *foo; 967 struct fuse_dispatcher fdi, fdi2; 968 struct fuse_dispatcher *fdip = &fdi; 969 struct fuse_dispatcher *fdip2 = NULL; 970 971 int err; 972 973 struct mount *mp = vnode_mount(dvp); 974 data = fuse_get_mpdata(mp); 975 uint64_t parentnid = VTOFUD(dvp)->nid; 976 mode_t mode = MAKEIMODE(vap->va_type, vap->va_mode); 977 enum fuse_opcode op; 978 int flags; 979 980 if (fuse_isdeadfs(dvp)) 981 return ENXIO; 982 983 /* FUSE expects sockets to be created with FUSE_MKNOD */ 984 if (vap->va_type == VSOCK) 985 return fuse_internal_mknod(dvp, vpp, cnp, vap); 986 987 /* 988 * VOP_CREATE doesn't tell us the open(2) flags, so we guess. Only a 989 * writable mode makes sense, and we might as well include readability 990 * too. 991 */ 992 flags = O_RDWR; 993 994 bzero(&fdi, sizeof(fdi)); 995 996 if (vap->va_type != VREG) 997 return (EINVAL); 998 999 if (fsess_not_impl(mp, FUSE_CREATE) || vap->va_type == VSOCK) { 1000 /* Fallback to FUSE_MKNOD/FUSE_OPEN */ 1001 fdisp_make_mknod_for_fallback(fdip, cnp, dvp, parentnid, td, 1002 cred, mode, &op); 1003 } else { 1004 /* Use FUSE_CREATE */ 1005 size_t insize; 1006 1007 op = FUSE_CREATE; 1008 fdisp_init(fdip, sizeof(*fci) + cnp->cn_namelen + 1); 1009 fdisp_make(fdip, op, vnode_mount(dvp), parentnid, td, cred); 1010 fci = fdip->indata; 1011 fci->mode = mode; 1012 fci->flags = O_CREAT | flags; 1013 if (fuse_libabi_geq(data, 7, 12)) { 1014 insize = sizeof(*fci); 1015 fci->umask = td->td_proc->p_pd->pd_cmask; 1016 } else { 1017 insize = sizeof(struct fuse_open_in); 1018 } 1019 1020 memcpy((char *)fdip->indata + insize, cnp->cn_nameptr, 1021 cnp->cn_namelen); 1022 ((char *)fdip->indata)[insize + cnp->cn_namelen] = '\0'; 1023 } 1024 1025 err = fdisp_wait_answ(fdip); 1026 1027 if (err) { 1028 if (err == ENOSYS && op == FUSE_CREATE) { 1029 fsess_set_notimpl(mp, FUSE_CREATE); 1030 fdisp_destroy(fdip); 1031 fdisp_make_mknod_for_fallback(fdip, cnp, dvp, 1032 parentnid, td, cred, mode, &op); 1033 err = fdisp_wait_answ(fdip); 1034 } 1035 if (err) 1036 goto out; 1037 } 1038 1039 feo = fdip->answ; 1040 1041 if ((err = fuse_internal_checkentry(feo, vap->va_type))) { 1042 goto out; 1043 } 1044 1045 if (op == FUSE_CREATE) { 1046 foo = (struct fuse_open_out*)(feo + 1); 1047 } else { 1048 /* Issue a separate FUSE_OPEN */ 1049 struct fuse_open_in *foi; 1050 1051 fdip2 = &fdi2; 1052 fdisp_init(fdip2, sizeof(*foi)); 1053 fdisp_make(fdip2, FUSE_OPEN, vnode_mount(dvp), feo->nodeid, td, 1054 cred); 1055 foi = fdip2->indata; 1056 foi->flags = flags; 1057 err = fdisp_wait_answ(fdip2); 1058 if (err) 1059 goto out; 1060 foo = fdip2->answ; 1061 } 1062 err = fuse_vnode_get(mp, feo, feo->nodeid, dvp, vpp, cnp, vap->va_type); 1063 if (err) { 1064 struct fuse_release_in *fri; 1065 uint64_t nodeid = feo->nodeid; 1066 uint64_t fh_id = foo->fh; 1067 1068 fdisp_init(fdip, sizeof(*fri)); 1069 fdisp_make(fdip, FUSE_RELEASE, mp, nodeid, td, cred); 1070 fri = fdip->indata; 1071 fri->fh = fh_id; 1072 fri->flags = flags; 1073 fuse_insert_callback(fdip->tick, fuse_internal_forget_callback); 1074 fuse_insert_message(fdip->tick, false); 1075 goto out; 1076 } 1077 ASSERT_VOP_ELOCKED(*vpp, "fuse_vnop_create"); 1078 fuse_internal_cache_attrs(*vpp, &feo->attr, feo->attr_valid, 1079 feo->attr_valid_nsec, NULL, true); 1080 1081 fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, td, cred, foo); 1082 fuse_vnode_open(*vpp, foo->open_flags, td); 1083 /* 1084 * Purge the parent's attribute cache because the daemon should've 1085 * updated its mtime and ctime 1086 */ 1087 fuse_vnode_clear_attr_cache(dvp); 1088 cache_purge_negative(dvp); 1089 1090 out: 1091 if (fdip2) 1092 fdisp_destroy(fdip2); 1093 fdisp_destroy(fdip); 1094 return err; 1095 } 1096 1097 /* 1098 struct vnop_fdatasync_args { 1099 struct vop_generic_args a_gen; 1100 struct vnode * a_vp; 1101 struct thread * a_td; 1102 }; 1103 */ 1104 static int 1105 fuse_vnop_fdatasync(struct vop_fdatasync_args *ap) 1106 { 1107 struct vnode *vp = ap->a_vp; 1108 struct thread *td = ap->a_td; 1109 int waitfor = MNT_WAIT; 1110 1111 int err = 0; 1112 1113 if (fuse_isdeadfs(vp)) { 1114 return 0; 1115 } 1116 if ((err = vop_stdfdatasync_buf(ap))) 1117 return err; 1118 1119 return fuse_internal_fsync(vp, td, waitfor, true); 1120 } 1121 1122 /* 1123 struct vnop_fsync_args { 1124 struct vop_generic_args a_gen; 1125 struct vnode * a_vp; 1126 int a_waitfor; 1127 struct thread * a_td; 1128 }; 1129 */ 1130 static int 1131 fuse_vnop_fsync(struct vop_fsync_args *ap) 1132 { 1133 struct vnode *vp = ap->a_vp; 1134 struct thread *td = ap->a_td; 1135 int waitfor = ap->a_waitfor; 1136 int err = 0; 1137 1138 if (fuse_isdeadfs(vp)) { 1139 return 0; 1140 } 1141 if ((err = vop_stdfsync(ap))) 1142 return err; 1143 1144 return fuse_internal_fsync(vp, td, waitfor, false); 1145 } 1146 1147 /* 1148 struct vnop_getattr_args { 1149 struct vnode *a_vp; 1150 struct vattr *a_vap; 1151 struct ucred *a_cred; 1152 struct thread *a_td; 1153 }; 1154 */ 1155 static int 1156 fuse_vnop_getattr(struct vop_getattr_args *ap) 1157 { 1158 struct vnode *vp = ap->a_vp; 1159 struct vattr *vap = ap->a_vap; 1160 struct ucred *cred = ap->a_cred; 1161 struct thread *td = curthread; 1162 1163 int err = 0; 1164 int dataflags; 1165 1166 dataflags = fuse_get_mpdata(vnode_mount(vp))->dataflags; 1167 1168 /* Note that we are not bailing out on a dead file system just yet. */ 1169 1170 if (!(dataflags & FSESS_INITED)) { 1171 if (!vnode_isvroot(vp)) { 1172 fdata_set_dead(fuse_get_mpdata(vnode_mount(vp))); 1173 err = ENOTCONN; 1174 return err; 1175 } else { 1176 goto fake; 1177 } 1178 } 1179 err = fuse_internal_getattr(vp, vap, cred, td); 1180 if (err == ENOTCONN && vnode_isvroot(vp)) { 1181 /* see comment in fuse_vfsop_statfs() */ 1182 goto fake; 1183 } else { 1184 return err; 1185 } 1186 1187 fake: 1188 bzero(vap, sizeof(*vap)); 1189 vap->va_type = vnode_vtype(vp); 1190 1191 return 0; 1192 } 1193 1194 /* 1195 struct vnop_inactive_args { 1196 struct vnode *a_vp; 1197 }; 1198 */ 1199 static int 1200 fuse_vnop_inactive(struct vop_inactive_args *ap) 1201 { 1202 struct vnode *vp = ap->a_vp; 1203 struct thread *td = curthread; 1204 1205 struct fuse_vnode_data *fvdat = VTOFUD(vp); 1206 struct fuse_filehandle *fufh, *fufh_tmp; 1207 1208 int need_flush = 1; 1209 1210 LIST_FOREACH_SAFE(fufh, &fvdat->handles, next, fufh_tmp) { 1211 if (need_flush && vp->v_type == VREG) { 1212 if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) { 1213 fuse_vnode_savesize(vp, NULL, 0); 1214 } 1215 if ((fvdat->flag & FN_REVOKED) != 0) 1216 fuse_io_invalbuf(vp, td); 1217 else 1218 fuse_io_flushbuf(vp, MNT_WAIT, td); 1219 need_flush = 0; 1220 } 1221 fuse_filehandle_close(vp, fufh, td, NULL); 1222 } 1223 1224 if ((fvdat->flag & FN_REVOKED) != 0) 1225 vrecycle(vp); 1226 1227 return 0; 1228 } 1229 1230 /* 1231 struct vnop_ioctl_args { 1232 struct vnode *a_vp; 1233 u_long a_command; 1234 caddr_t a_data; 1235 int a_fflag; 1236 struct ucred *a_cred; 1237 struct thread *a_td; 1238 }; 1239 */ 1240 static int 1241 fuse_vnop_ioctl(struct vop_ioctl_args *ap) 1242 { 1243 struct vnode *vp = ap->a_vp; 1244 struct mount *mp = vnode_mount(vp); 1245 struct ucred *cred = ap->a_cred; 1246 off_t *offp; 1247 pid_t pid = ap->a_td->td_proc->p_pid; 1248 int err; 1249 1250 switch (ap->a_command) { 1251 case FIOSEEKDATA: 1252 case FIOSEEKHOLE: 1253 /* Call FUSE_LSEEK, if we can, or fall back to vop_stdioctl */ 1254 if (fsess_maybe_impl(mp, FUSE_LSEEK)) { 1255 int whence; 1256 1257 offp = ap->a_data; 1258 if (ap->a_command == FIOSEEKDATA) 1259 whence = SEEK_DATA; 1260 else 1261 whence = SEEK_HOLE; 1262 1263 vn_lock(vp, LK_SHARED | LK_RETRY); 1264 err = fuse_vnop_do_lseek(vp, ap->a_td, cred, pid, offp, 1265 whence); 1266 VOP_UNLOCK(vp); 1267 } 1268 if (fsess_not_impl(mp, FUSE_LSEEK)) 1269 err = vop_stdioctl(ap); 1270 break; 1271 default: 1272 /* TODO: implement FUSE_IOCTL */ 1273 err = ENOTTY; 1274 break; 1275 } 1276 return (err); 1277 } 1278 1279 1280 /* 1281 struct vnop_link_args { 1282 struct vnode *a_tdvp; 1283 struct vnode *a_vp; 1284 struct componentname *a_cnp; 1285 }; 1286 */ 1287 static int 1288 fuse_vnop_link(struct vop_link_args *ap) 1289 { 1290 struct vnode *vp = ap->a_vp; 1291 struct vnode *tdvp = ap->a_tdvp; 1292 struct componentname *cnp = ap->a_cnp; 1293 1294 struct vattr *vap = VTOVA(vp); 1295 1296 struct fuse_dispatcher fdi; 1297 struct fuse_entry_out *feo; 1298 struct fuse_link_in fli; 1299 1300 int err; 1301 1302 if (fuse_isdeadfs(vp)) { 1303 return ENXIO; 1304 } 1305 if (vnode_mount(tdvp) != vnode_mount(vp)) { 1306 return EXDEV; 1307 } 1308 1309 /* 1310 * This is a seatbelt check to protect naive userspace filesystems from 1311 * themselves and the limitations of the FUSE IPC protocol. If a 1312 * filesystem does not allow attribute caching, assume it is capable of 1313 * validating that nlink does not overflow. 1314 */ 1315 if (vap != NULL && vap->va_nlink >= FUSE_LINK_MAX) 1316 return EMLINK; 1317 fli.oldnodeid = VTOI(vp); 1318 1319 fdisp_init(&fdi, 0); 1320 fuse_internal_newentry_makerequest(vnode_mount(tdvp), VTOI(tdvp), cnp, 1321 FUSE_LINK, &fli, sizeof(fli), &fdi); 1322 if ((err = fdisp_wait_answ(&fdi))) { 1323 goto out; 1324 } 1325 feo = fdi.answ; 1326 1327 err = fuse_internal_checkentry(feo, vnode_vtype(vp)); 1328 if (!err) { 1329 /* 1330 * Purge the parent's attribute cache because the daemon 1331 * should've updated its mtime and ctime 1332 */ 1333 fuse_vnode_clear_attr_cache(tdvp); 1334 fuse_internal_cache_attrs(vp, &feo->attr, feo->attr_valid, 1335 feo->attr_valid_nsec, NULL, true); 1336 } 1337 out: 1338 fdisp_destroy(&fdi); 1339 return err; 1340 } 1341 1342 struct fuse_lookup_alloc_arg { 1343 struct fuse_entry_out *feo; 1344 struct componentname *cnp; 1345 uint64_t nid; 1346 enum vtype vtyp; 1347 }; 1348 1349 /* Callback for vn_get_ino */ 1350 static int 1351 fuse_lookup_alloc(struct mount *mp, void *arg, int lkflags, struct vnode **vpp) 1352 { 1353 struct fuse_lookup_alloc_arg *flaa = arg; 1354 1355 return fuse_vnode_get(mp, flaa->feo, flaa->nid, NULL, vpp, flaa->cnp, 1356 flaa->vtyp); 1357 } 1358 1359 SDT_PROBE_DEFINE3(fusefs, , vnops, cache_lookup, 1360 "int", "struct timespec*", "struct timespec*"); 1361 /* 1362 struct vnop_lookup_args { 1363 struct vnodeop_desc *a_desc; 1364 struct vnode *a_dvp; 1365 struct vnode **a_vpp; 1366 struct componentname *a_cnp; 1367 }; 1368 */ 1369 int 1370 fuse_vnop_lookup(struct vop_lookup_args *ap) 1371 { 1372 struct vnode *dvp = ap->a_dvp; 1373 struct vnode **vpp = ap->a_vpp; 1374 struct componentname *cnp = ap->a_cnp; 1375 struct thread *td = curthread; 1376 struct ucred *cred = cnp->cn_cred; 1377 struct timespec now; 1378 1379 int nameiop = cnp->cn_nameiop; 1380 int flags = cnp->cn_flags; 1381 int wantparent = flags & (LOCKPARENT | WANTPARENT); 1382 int islastcn = flags & ISLASTCN; 1383 struct mount *mp = vnode_mount(dvp); 1384 struct fuse_data *data = fuse_get_mpdata(mp); 1385 int default_permissions = data->dataflags & FSESS_DEFAULT_PERMISSIONS; 1386 1387 int err = 0; 1388 int lookup_err = 0; 1389 struct vnode *vp = NULL; 1390 1391 struct fuse_dispatcher fdi; 1392 bool did_lookup = false; 1393 struct fuse_entry_out *feo = NULL; 1394 enum vtype vtyp; /* vnode type of target */ 1395 off_t filesize; /* filesize of target */ 1396 1397 uint64_t nid; 1398 1399 if (fuse_isdeadfs(dvp)) { 1400 *vpp = NULL; 1401 return ENXIO; 1402 } 1403 if (!vnode_isdir(dvp)) 1404 return ENOTDIR; 1405 1406 if (islastcn && vfs_isrdonly(mp) && (nameiop != LOOKUP)) 1407 return EROFS; 1408 1409 if ((cnp->cn_flags & NOEXECCHECK) != 0) 1410 cnp->cn_flags &= ~NOEXECCHECK; 1411 else if ((err = fuse_internal_access(dvp, VEXEC, td, cred))) 1412 return err; 1413 1414 if ((flags & ISDOTDOT) && !(data->dataflags & FSESS_EXPORT_SUPPORT)) 1415 { 1416 if (!(VTOFUD(dvp)->flag & FN_PARENT_NID)) { 1417 /* 1418 * Since the file system doesn't support ".." lookups, 1419 * we have no way to find this entry. 1420 */ 1421 return ESTALE; 1422 } 1423 nid = VTOFUD(dvp)->parent_nid; 1424 if (nid == 0) 1425 return ENOENT; 1426 /* .. is obviously a directory */ 1427 vtyp = VDIR; 1428 filesize = 0; 1429 } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') { 1430 nid = VTOI(dvp); 1431 /* . is obviously a directory */ 1432 vtyp = VDIR; 1433 filesize = 0; 1434 } else { 1435 struct timespec timeout; 1436 int ncpticks; /* here to accomodate for API contract */ 1437 1438 err = cache_lookup(dvp, vpp, cnp, &timeout, &ncpticks); 1439 getnanouptime(&now); 1440 SDT_PROBE3(fusefs, , vnops, cache_lookup, err, &timeout, &now); 1441 switch (err) { 1442 case -1: /* positive match */ 1443 if (timespeccmp(&timeout, &now, >)) { 1444 counter_u64_add(fuse_lookup_cache_hits, 1); 1445 } else { 1446 /* Cache timeout */ 1447 counter_u64_add(fuse_lookup_cache_misses, 1); 1448 bintime_clear( 1449 &VTOFUD(*vpp)->entry_cache_timeout); 1450 cache_purge(*vpp); 1451 if (dvp != *vpp) 1452 vput(*vpp); 1453 else 1454 vrele(*vpp); 1455 *vpp = NULL; 1456 break; 1457 } 1458 return 0; 1459 1460 case 0: /* no match in cache */ 1461 counter_u64_add(fuse_lookup_cache_misses, 1); 1462 break; 1463 1464 case ENOENT: /* negative match */ 1465 if (timespeccmp(&timeout, &now, <=)) { 1466 /* Cache timeout */ 1467 cache_purge_negative(dvp); 1468 break; 1469 } 1470 /* fall through */ 1471 default: 1472 return err; 1473 } 1474 1475 fdisp_init(&fdi, cnp->cn_namelen + 1); 1476 fdisp_make(&fdi, FUSE_LOOKUP, mp, VTOI(dvp), td, cred); 1477 1478 memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen); 1479 ((char *)fdi.indata)[cnp->cn_namelen] = '\0'; 1480 lookup_err = fdisp_wait_answ(&fdi); 1481 did_lookup = true; 1482 1483 if (!lookup_err) { 1484 /* lookup call succeeded */ 1485 feo = (struct fuse_entry_out *)fdi.answ; 1486 nid = feo->nodeid; 1487 if (nid == 0) { 1488 /* zero nodeid means ENOENT and cache it */ 1489 struct timespec timeout; 1490 1491 fdi.answ_stat = ENOENT; 1492 lookup_err = ENOENT; 1493 if (cnp->cn_flags & MAKEENTRY) { 1494 fuse_validity_2_timespec(feo, &timeout); 1495 /* Use the same entry_time for .. as for 1496 * the file itself. That doesn't honor 1497 * exactly what the fuse server tells 1498 * us, but to do otherwise would require 1499 * another cache lookup at this point. 1500 */ 1501 struct timespec *dtsp = NULL; 1502 cache_enter_time(dvp, *vpp, cnp, 1503 &timeout, dtsp); 1504 } 1505 } 1506 vtyp = IFTOVT(feo->attr.mode); 1507 filesize = feo->attr.size; 1508 } 1509 if (lookup_err && (!fdi.answ_stat || lookup_err != ENOENT)) { 1510 fdisp_destroy(&fdi); 1511 return lookup_err; 1512 } 1513 } 1514 /* lookup_err, if non-zero, must be ENOENT at this point */ 1515 1516 if (lookup_err) { 1517 /* Entry not found */ 1518 if ((nameiop == CREATE || nameiop == RENAME) && islastcn) { 1519 if (default_permissions) 1520 err = fuse_internal_access(dvp, VWRITE, td, 1521 cred); 1522 else 1523 err = 0; 1524 if (!err) { 1525 /* 1526 * Set the SAVENAME flag to hold onto the 1527 * pathname for use later in VOP_CREATE or 1528 * VOP_RENAME. 1529 */ 1530 cnp->cn_flags |= SAVENAME; 1531 1532 err = EJUSTRETURN; 1533 } 1534 } else { 1535 err = ENOENT; 1536 } 1537 } else { 1538 /* Entry was found */ 1539 if (flags & ISDOTDOT) { 1540 struct fuse_lookup_alloc_arg flaa; 1541 1542 flaa.nid = nid; 1543 flaa.feo = feo; 1544 flaa.cnp = cnp; 1545 flaa.vtyp = vtyp; 1546 err = vn_vget_ino_gen(dvp, fuse_lookup_alloc, &flaa, 0, 1547 &vp); 1548 *vpp = vp; 1549 } else if (nid == VTOI(dvp)) { 1550 vref(dvp); 1551 *vpp = dvp; 1552 } else { 1553 struct fuse_vnode_data *fvdat; 1554 1555 err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp, 1556 &vp, cnp, vtyp); 1557 if (err) 1558 goto out; 1559 *vpp = vp; 1560 fvdat = VTOFUD(vp); 1561 1562 MPASS(feo != NULL); 1563 if (timespeccmp(&now, &fvdat->last_local_modify, >)) { 1564 /* 1565 * Attributes from the server are definitely 1566 * newer than the last attributes we sent to 1567 * the server, so cache them. 1568 */ 1569 fuse_internal_cache_attrs(*vpp, &feo->attr, 1570 feo->attr_valid, feo->attr_valid_nsec, 1571 NULL, true); 1572 } 1573 fuse_validity_2_bintime(feo->entry_valid, 1574 feo->entry_valid_nsec, 1575 &fvdat->entry_cache_timeout); 1576 1577 if ((nameiop == DELETE || nameiop == RENAME) && 1578 islastcn && default_permissions) 1579 { 1580 struct vattr dvattr; 1581 1582 err = fuse_internal_access(dvp, VWRITE, td, 1583 cred); 1584 if (err != 0) 1585 goto out; 1586 /* 1587 * if the parent's sticky bit is set, check 1588 * whether we're allowed to remove the file. 1589 * Need to figure out the vnode locking to make 1590 * this work. 1591 */ 1592 fuse_internal_getattr(dvp, &dvattr, cred, td); 1593 if ((dvattr.va_mode & S_ISTXT) && 1594 fuse_internal_access(dvp, VADMIN, td, 1595 cred) && 1596 fuse_internal_access(*vpp, VADMIN, td, 1597 cred)) { 1598 err = EPERM; 1599 goto out; 1600 } 1601 } 1602 1603 if (islastcn && ( 1604 (nameiop == DELETE) || 1605 (nameiop == RENAME && wantparent))) { 1606 cnp->cn_flags |= SAVENAME; 1607 } 1608 } 1609 } 1610 out: 1611 if (err) { 1612 if (vp != NULL && dvp != vp) 1613 vput(vp); 1614 else if (vp != NULL) 1615 vrele(vp); 1616 *vpp = NULL; 1617 } 1618 if (did_lookup) 1619 fdisp_destroy(&fdi); 1620 1621 return err; 1622 } 1623 1624 /* 1625 struct vnop_mkdir_args { 1626 struct vnode *a_dvp; 1627 struct vnode **a_vpp; 1628 struct componentname *a_cnp; 1629 struct vattr *a_vap; 1630 }; 1631 */ 1632 static int 1633 fuse_vnop_mkdir(struct vop_mkdir_args *ap) 1634 { 1635 struct vnode *dvp = ap->a_dvp; 1636 struct vnode **vpp = ap->a_vpp; 1637 struct componentname *cnp = ap->a_cnp; 1638 struct vattr *vap = ap->a_vap; 1639 1640 struct fuse_mkdir_in fmdi; 1641 1642 if (fuse_isdeadfs(dvp)) { 1643 return ENXIO; 1644 } 1645 fmdi.mode = MAKEIMODE(vap->va_type, vap->va_mode); 1646 fmdi.umask = curthread->td_proc->p_pd->pd_cmask; 1647 1648 return (fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKDIR, &fmdi, 1649 sizeof(fmdi), VDIR)); 1650 } 1651 1652 /* 1653 struct vnop_mknod_args { 1654 struct vnode *a_dvp; 1655 struct vnode **a_vpp; 1656 struct componentname *a_cnp; 1657 struct vattr *a_vap; 1658 }; 1659 */ 1660 static int 1661 fuse_vnop_mknod(struct vop_mknod_args *ap) 1662 { 1663 1664 struct vnode *dvp = ap->a_dvp; 1665 struct vnode **vpp = ap->a_vpp; 1666 struct componentname *cnp = ap->a_cnp; 1667 struct vattr *vap = ap->a_vap; 1668 1669 if (fuse_isdeadfs(dvp)) 1670 return ENXIO; 1671 1672 return fuse_internal_mknod(dvp, vpp, cnp, vap); 1673 } 1674 1675 /* 1676 struct vop_open_args { 1677 struct vnode *a_vp; 1678 int a_mode; 1679 struct ucred *a_cred; 1680 struct thread *a_td; 1681 int a_fdidx; / struct file *a_fp; 1682 }; 1683 */ 1684 static int 1685 fuse_vnop_open(struct vop_open_args *ap) 1686 { 1687 struct vnode *vp = ap->a_vp; 1688 int a_mode = ap->a_mode; 1689 struct thread *td = ap->a_td; 1690 struct ucred *cred = ap->a_cred; 1691 pid_t pid = td->td_proc->p_pid; 1692 struct fuse_vnode_data *fvdat; 1693 1694 if (fuse_isdeadfs(vp)) 1695 return ENXIO; 1696 if (vp->v_type == VCHR || vp->v_type == VBLK || vp->v_type == VFIFO) 1697 return (EOPNOTSUPP); 1698 if ((a_mode & (FREAD | FWRITE | FEXEC)) == 0) 1699 return EINVAL; 1700 1701 fvdat = VTOFUD(vp); 1702 1703 if (fuse_filehandle_validrw(vp, a_mode, cred, pid)) { 1704 fuse_vnode_open(vp, 0, td); 1705 return 0; 1706 } 1707 1708 return fuse_filehandle_open(vp, a_mode, NULL, td, cred); 1709 } 1710 1711 static int 1712 fuse_vnop_pathconf(struct vop_pathconf_args *ap) 1713 { 1714 struct vnode *vp = ap->a_vp; 1715 struct mount *mp; 1716 1717 switch (ap->a_name) { 1718 case _PC_FILESIZEBITS: 1719 *ap->a_retval = 64; 1720 return (0); 1721 case _PC_NAME_MAX: 1722 *ap->a_retval = NAME_MAX; 1723 return (0); 1724 case _PC_LINK_MAX: 1725 *ap->a_retval = MIN(LONG_MAX, FUSE_LINK_MAX); 1726 return (0); 1727 case _PC_SYMLINK_MAX: 1728 *ap->a_retval = MAXPATHLEN; 1729 return (0); 1730 case _PC_NO_TRUNC: 1731 *ap->a_retval = 1; 1732 return (0); 1733 case _PC_MIN_HOLE_SIZE: 1734 /* 1735 * The FUSE protocol provides no mechanism for a server to 1736 * report _PC_MIN_HOLE_SIZE. It's a protocol bug. Instead, 1737 * return EINVAL if the server does not support FUSE_LSEEK, or 1738 * 1 if it does. 1739 */ 1740 mp = vnode_mount(vp); 1741 if (!fsess_is_impl(mp, FUSE_LSEEK) && 1742 !fsess_not_impl(mp, FUSE_LSEEK)) { 1743 off_t offset = 0; 1744 1745 /* Issue a FUSE_LSEEK to find out if it's implemented */ 1746 fuse_vnop_do_lseek(vp, curthread, curthread->td_ucred, 1747 curthread->td_proc->p_pid, &offset, SEEK_DATA); 1748 } 1749 1750 if (fsess_is_impl(mp, FUSE_LSEEK)) { 1751 *ap->a_retval = 1; 1752 return (0); 1753 } else { 1754 /* 1755 * Probably FUSE_LSEEK is not implemented. It might 1756 * be, if the FUSE_LSEEK above returned an error like 1757 * EACCES, but in that case we can't tell, so it's 1758 * safest to report EINVAL anyway. 1759 */ 1760 return (EINVAL); 1761 } 1762 default: 1763 return (vop_stdpathconf(ap)); 1764 } 1765 } 1766 1767 SDT_PROBE_DEFINE3(fusefs, , vnops, filehandles_closed, "struct vnode*", 1768 "struct uio*", "struct ucred*"); 1769 /* 1770 struct vnop_read_args { 1771 struct vnode *a_vp; 1772 struct uio *a_uio; 1773 int a_ioflag; 1774 struct ucred *a_cred; 1775 }; 1776 */ 1777 static int 1778 fuse_vnop_read(struct vop_read_args *ap) 1779 { 1780 struct vnode *vp = ap->a_vp; 1781 struct uio *uio = ap->a_uio; 1782 int ioflag = ap->a_ioflag; 1783 struct ucred *cred = ap->a_cred; 1784 pid_t pid = curthread->td_proc->p_pid; 1785 struct fuse_filehandle *fufh; 1786 int err; 1787 bool closefufh = false, directio; 1788 1789 MPASS(vp->v_type == VREG || vp->v_type == VDIR); 1790 1791 if (fuse_isdeadfs(vp)) { 1792 return ENXIO; 1793 } 1794 1795 if (VTOFUD(vp)->flag & FN_DIRECTIO) { 1796 ioflag |= IO_DIRECT; 1797 } 1798 1799 err = fuse_filehandle_getrw(vp, FREAD, &fufh, cred, pid); 1800 if (err == EBADF && vnode_mount(vp)->mnt_flag & MNT_EXPORTED) { 1801 /* 1802 * nfsd will do I/O without first doing VOP_OPEN. We 1803 * must implicitly open the file here 1804 */ 1805 err = fuse_filehandle_open(vp, FREAD, &fufh, curthread, cred); 1806 closefufh = true; 1807 } 1808 if (err) { 1809 SDT_PROBE3(fusefs, , vnops, filehandles_closed, vp, uio, cred); 1810 return err; 1811 } 1812 1813 /* 1814 * Ideally, when the daemon asks for direct io at open time, the 1815 * standard file flag should be set according to this, so that would 1816 * just change the default mode, which later on could be changed via 1817 * fcntl(2). 1818 * But this doesn't work, the O_DIRECT flag gets cleared at some point 1819 * (don't know where). So to make any use of the Fuse direct_io option, 1820 * we hardwire it into the file's private data (similarly to Linux, 1821 * btw.). 1822 */ 1823 directio = (ioflag & IO_DIRECT) || !fsess_opt_datacache(vnode_mount(vp)); 1824 1825 fuse_vnode_update(vp, FN_ATIMECHANGE); 1826 if (directio) { 1827 SDT_PROBE2(fusefs, , vnops, trace, 1, "direct read of vnode"); 1828 err = fuse_read_directbackend(vp, uio, cred, fufh); 1829 } else { 1830 SDT_PROBE2(fusefs, , vnops, trace, 1, "buffered read of vnode"); 1831 err = fuse_read_biobackend(vp, uio, ioflag, cred, fufh, pid); 1832 } 1833 1834 if (closefufh) 1835 fuse_filehandle_close(vp, fufh, curthread, cred); 1836 1837 return (err); 1838 } 1839 1840 /* 1841 struct vnop_readdir_args { 1842 struct vnode *a_vp; 1843 struct uio *a_uio; 1844 struct ucred *a_cred; 1845 int *a_eofflag; 1846 int *a_ncookies; 1847 uint64_t **a_cookies; 1848 }; 1849 */ 1850 static int 1851 fuse_vnop_readdir(struct vop_readdir_args *ap) 1852 { 1853 struct vnode *vp = ap->a_vp; 1854 struct uio *uio = ap->a_uio; 1855 struct ucred *cred = ap->a_cred; 1856 struct fuse_filehandle *fufh = NULL; 1857 struct fuse_iov cookediov; 1858 int err = 0; 1859 uint64_t *cookies; 1860 off_t startoff; 1861 ssize_t tresid; 1862 int ncookies; 1863 bool closefufh = false; 1864 pid_t pid = curthread->td_proc->p_pid; 1865 1866 if (ap->a_eofflag) 1867 *ap->a_eofflag = 0; 1868 if (fuse_isdeadfs(vp)) { 1869 return ENXIO; 1870 } 1871 if ( /* XXXIP ((uio_iovcnt(uio) > 1)) || */ 1872 (uio_resid(uio) < sizeof(struct dirent))) { 1873 return EINVAL; 1874 } 1875 1876 tresid = uio->uio_resid; 1877 startoff = uio->uio_offset; 1878 err = fuse_filehandle_get_dir(vp, &fufh, cred, pid); 1879 if (err == EBADF && vnode_mount(vp)->mnt_flag & MNT_EXPORTED) { 1880 /* 1881 * nfsd will do VOP_READDIR without first doing VOP_OPEN. We 1882 * must implicitly open the directory here 1883 */ 1884 err = fuse_filehandle_open(vp, FREAD, &fufh, curthread, cred); 1885 if (err == 0) { 1886 /* 1887 * When a directory is opened, it must be read from 1888 * the beginning. Hopefully, the "startoff" still 1889 * exists as an offset cookie for the directory. 1890 * If not, it will read the entire directory without 1891 * returning any entries and just return eof. 1892 */ 1893 uio->uio_offset = 0; 1894 } 1895 closefufh = true; 1896 } 1897 if (err) 1898 return (err); 1899 if (ap->a_ncookies != NULL) { 1900 ncookies = uio->uio_resid / 1901 (offsetof(struct dirent, d_name) + 4) + 1; 1902 cookies = malloc(ncookies * sizeof(*cookies), M_TEMP, M_WAITOK); 1903 *ap->a_ncookies = ncookies; 1904 *ap->a_cookies = cookies; 1905 } else { 1906 ncookies = 0; 1907 cookies = NULL; 1908 } 1909 #define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1) 1910 fiov_init(&cookediov, DIRCOOKEDSIZE); 1911 1912 err = fuse_internal_readdir(vp, uio, startoff, fufh, &cookediov, 1913 &ncookies, cookies); 1914 1915 fiov_teardown(&cookediov); 1916 if (closefufh) 1917 fuse_filehandle_close(vp, fufh, curthread, cred); 1918 1919 if (ap->a_ncookies != NULL) { 1920 if (err == 0) { 1921 *ap->a_ncookies -= ncookies; 1922 } else { 1923 free(*ap->a_cookies, M_TEMP); 1924 *ap->a_ncookies = 0; 1925 *ap->a_cookies = NULL; 1926 } 1927 } 1928 if (err == 0 && tresid == uio->uio_resid) 1929 *ap->a_eofflag = 1; 1930 1931 return err; 1932 } 1933 1934 /* 1935 struct vnop_readlink_args { 1936 struct vnode *a_vp; 1937 struct uio *a_uio; 1938 struct ucred *a_cred; 1939 }; 1940 */ 1941 static int 1942 fuse_vnop_readlink(struct vop_readlink_args *ap) 1943 { 1944 struct vnode *vp = ap->a_vp; 1945 struct uio *uio = ap->a_uio; 1946 struct ucred *cred = ap->a_cred; 1947 1948 struct fuse_dispatcher fdi; 1949 int err; 1950 1951 if (fuse_isdeadfs(vp)) { 1952 return ENXIO; 1953 } 1954 if (!vnode_islnk(vp)) { 1955 return EINVAL; 1956 } 1957 fdisp_init(&fdi, 0); 1958 err = fdisp_simple_putget_vp(&fdi, FUSE_READLINK, vp, curthread, cred); 1959 if (err) { 1960 goto out; 1961 } 1962 if (((char *)fdi.answ)[0] == '/' && 1963 fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_PUSH_SYMLINKS_IN) { 1964 char *mpth = vnode_mount(vp)->mnt_stat.f_mntonname; 1965 1966 err = uiomove(mpth, strlen(mpth), uio); 1967 } 1968 if (!err) { 1969 err = uiomove(fdi.answ, fdi.iosize, uio); 1970 } 1971 out: 1972 fdisp_destroy(&fdi); 1973 return err; 1974 } 1975 1976 /* 1977 struct vnop_reclaim_args { 1978 struct vnode *a_vp; 1979 }; 1980 */ 1981 static int 1982 fuse_vnop_reclaim(struct vop_reclaim_args *ap) 1983 { 1984 struct vnode *vp = ap->a_vp; 1985 struct thread *td = curthread; 1986 struct fuse_vnode_data *fvdat = VTOFUD(vp); 1987 struct fuse_filehandle *fufh, *fufh_tmp; 1988 1989 if (!fvdat) { 1990 panic("FUSE: no vnode data during recycling"); 1991 } 1992 LIST_FOREACH_SAFE(fufh, &fvdat->handles, next, fufh_tmp) { 1993 printf("FUSE: vnode being reclaimed with open fufh " 1994 "(type=%#x)", fufh->fufh_type); 1995 fuse_filehandle_close(vp, fufh, td, NULL); 1996 } 1997 1998 if (!fuse_isdeadfs(vp) && fvdat->nlookup > 0) { 1999 fuse_internal_forget_send(vnode_mount(vp), td, NULL, VTOI(vp), 2000 fvdat->nlookup); 2001 } 2002 cache_purge(vp); 2003 vfs_hash_remove(vp); 2004 fuse_vnode_destroy(vp); 2005 2006 return 0; 2007 } 2008 2009 /* 2010 struct vnop_remove_args { 2011 struct vnode *a_dvp; 2012 struct vnode *a_vp; 2013 struct componentname *a_cnp; 2014 }; 2015 */ 2016 static int 2017 fuse_vnop_remove(struct vop_remove_args *ap) 2018 { 2019 struct vnode *dvp = ap->a_dvp; 2020 struct vnode *vp = ap->a_vp; 2021 struct componentname *cnp = ap->a_cnp; 2022 2023 int err; 2024 2025 if (fuse_isdeadfs(vp)) { 2026 return ENXIO; 2027 } 2028 if (vnode_isdir(vp)) { 2029 return EPERM; 2030 } 2031 2032 err = fuse_internal_remove(dvp, vp, cnp, FUSE_UNLINK); 2033 2034 return err; 2035 } 2036 2037 /* 2038 struct vnop_rename_args { 2039 struct vnode *a_fdvp; 2040 struct vnode *a_fvp; 2041 struct componentname *a_fcnp; 2042 struct vnode *a_tdvp; 2043 struct vnode *a_tvp; 2044 struct componentname *a_tcnp; 2045 }; 2046 */ 2047 static int 2048 fuse_vnop_rename(struct vop_rename_args *ap) 2049 { 2050 struct vnode *fdvp = ap->a_fdvp; 2051 struct vnode *fvp = ap->a_fvp; 2052 struct componentname *fcnp = ap->a_fcnp; 2053 struct vnode *tdvp = ap->a_tdvp; 2054 struct vnode *tvp = ap->a_tvp; 2055 struct componentname *tcnp = ap->a_tcnp; 2056 struct fuse_data *data; 2057 bool newparent = fdvp != tdvp; 2058 bool isdir = fvp->v_type == VDIR; 2059 int err = 0; 2060 2061 if (fuse_isdeadfs(fdvp)) { 2062 return ENXIO; 2063 } 2064 if (fvp->v_mount != tdvp->v_mount || 2065 (tvp && fvp->v_mount != tvp->v_mount)) { 2066 SDT_PROBE2(fusefs, , vnops, trace, 1, "cross-device rename"); 2067 err = EXDEV; 2068 goto out; 2069 } 2070 cache_purge(fvp); 2071 2072 /* 2073 * FUSE library is expected to check if target directory is not 2074 * under the source directory in the file system tree. 2075 * Linux performs this check at VFS level. 2076 */ 2077 /* 2078 * If source is a directory, and it will get a new parent, user must 2079 * have write permission to it, so ".." can be modified. 2080 */ 2081 data = fuse_get_mpdata(vnode_mount(tdvp)); 2082 if (data->dataflags & FSESS_DEFAULT_PERMISSIONS && isdir && newparent) { 2083 err = fuse_internal_access(fvp, VWRITE, 2084 curthread, tcnp->cn_cred); 2085 if (err) 2086 goto out; 2087 } 2088 sx_xlock(&data->rename_lock); 2089 err = fuse_internal_rename(fdvp, fcnp, tdvp, tcnp); 2090 if (err == 0) { 2091 if (tdvp != fdvp) 2092 fuse_vnode_setparent(fvp, tdvp); 2093 if (tvp != NULL) 2094 fuse_vnode_setparent(tvp, NULL); 2095 } 2096 sx_unlock(&data->rename_lock); 2097 2098 if (tvp != NULL && tvp != fvp) { 2099 cache_purge(tvp); 2100 } 2101 if (vnode_isdir(fvp)) { 2102 if ((tvp != NULL) && vnode_isdir(tvp)) { 2103 cache_purge(tdvp); 2104 } 2105 cache_purge(fdvp); 2106 } 2107 out: 2108 if (tdvp == tvp) { 2109 vrele(tdvp); 2110 } else { 2111 vput(tdvp); 2112 } 2113 if (tvp != NULL) { 2114 vput(tvp); 2115 } 2116 vrele(fdvp); 2117 vrele(fvp); 2118 2119 return err; 2120 } 2121 2122 /* 2123 struct vnop_rmdir_args { 2124 struct vnode *a_dvp; 2125 struct vnode *a_vp; 2126 struct componentname *a_cnp; 2127 } *ap; 2128 */ 2129 static int 2130 fuse_vnop_rmdir(struct vop_rmdir_args *ap) 2131 { 2132 struct vnode *dvp = ap->a_dvp; 2133 struct vnode *vp = ap->a_vp; 2134 2135 int err; 2136 2137 if (fuse_isdeadfs(vp)) { 2138 return ENXIO; 2139 } 2140 if (VTOFUD(vp) == VTOFUD(dvp)) { 2141 return EINVAL; 2142 } 2143 err = fuse_internal_remove(dvp, vp, ap->a_cnp, FUSE_RMDIR); 2144 2145 return err; 2146 } 2147 2148 /* 2149 struct vnop_setattr_args { 2150 struct vnode *a_vp; 2151 struct vattr *a_vap; 2152 struct ucred *a_cred; 2153 struct thread *a_td; 2154 }; 2155 */ 2156 static int 2157 fuse_vnop_setattr(struct vop_setattr_args *ap) 2158 { 2159 struct vnode *vp = ap->a_vp; 2160 struct vattr *vap = ap->a_vap; 2161 struct ucred *cred = ap->a_cred; 2162 struct thread *td = curthread; 2163 struct mount *mp; 2164 struct fuse_data *data; 2165 struct vattr old_va; 2166 int dataflags; 2167 int err = 0, err2; 2168 accmode_t accmode = 0; 2169 bool checkperm; 2170 bool drop_suid = false; 2171 gid_t cr_gid; 2172 2173 mp = vnode_mount(vp); 2174 data = fuse_get_mpdata(mp); 2175 dataflags = data->dataflags; 2176 checkperm = dataflags & FSESS_DEFAULT_PERMISSIONS; 2177 if (cred->cr_ngroups > 0) 2178 cr_gid = cred->cr_groups[0]; 2179 else 2180 cr_gid = 0; 2181 2182 if (fuse_isdeadfs(vp)) { 2183 return ENXIO; 2184 } 2185 2186 if (vap->va_uid != (uid_t)VNOVAL) { 2187 if (checkperm) { 2188 /* Only root may change a file's owner */ 2189 err = priv_check_cred(cred, PRIV_VFS_CHOWN); 2190 if (err) { 2191 /* As a special case, allow the null chown */ 2192 err2 = fuse_internal_getattr(vp, &old_va, cred, 2193 td); 2194 if (err2) 2195 return (err2); 2196 if (vap->va_uid != old_va.va_uid) 2197 return err; 2198 else 2199 accmode |= VADMIN; 2200 drop_suid = true; 2201 } else 2202 accmode |= VADMIN; 2203 } else 2204 accmode |= VADMIN; 2205 } 2206 if (vap->va_gid != (gid_t)VNOVAL) { 2207 if (checkperm && priv_check_cred(cred, PRIV_VFS_CHOWN)) 2208 drop_suid = true; 2209 if (checkperm && !groupmember(vap->va_gid, cred)) 2210 { 2211 /* 2212 * Non-root users may only chgrp to one of their own 2213 * groups 2214 */ 2215 err = priv_check_cred(cred, PRIV_VFS_CHOWN); 2216 if (err) { 2217 /* As a special case, allow the null chgrp */ 2218 err2 = fuse_internal_getattr(vp, &old_va, cred, 2219 td); 2220 if (err2) 2221 return (err2); 2222 if (vap->va_gid != old_va.va_gid) 2223 return err; 2224 accmode |= VADMIN; 2225 } else 2226 accmode |= VADMIN; 2227 } else 2228 accmode |= VADMIN; 2229 } 2230 if (vap->va_size != VNOVAL) { 2231 switch (vp->v_type) { 2232 case VDIR: 2233 return (EISDIR); 2234 case VLNK: 2235 case VREG: 2236 if (vfs_isrdonly(mp)) 2237 return (EROFS); 2238 break; 2239 default: 2240 /* 2241 * According to POSIX, the result is unspecified 2242 * for file types other than regular files, 2243 * directories and shared memory objects. We 2244 * don't support shared memory objects in the file 2245 * system, and have dubious support for truncating 2246 * symlinks. Just ignore the request in other cases. 2247 */ 2248 return (0); 2249 } 2250 /* Don't set accmode. Permission to trunc is checked upstack */ 2251 } 2252 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { 2253 if (vap->va_vaflags & VA_UTIMES_NULL) 2254 accmode |= VWRITE; 2255 else 2256 accmode |= VADMIN; 2257 } 2258 if (drop_suid) { 2259 if (vap->va_mode != (mode_t)VNOVAL) 2260 vap->va_mode &= ~(S_ISUID | S_ISGID); 2261 else { 2262 err = fuse_internal_getattr(vp, &old_va, cred, td); 2263 if (err) 2264 return (err); 2265 vap->va_mode = old_va.va_mode & ~(S_ISUID | S_ISGID); 2266 } 2267 } 2268 if (vap->va_mode != (mode_t)VNOVAL) { 2269 /* Only root may set the sticky bit on non-directories */ 2270 if (checkperm && vp->v_type != VDIR && (vap->va_mode & S_ISTXT) 2271 && priv_check_cred(cred, PRIV_VFS_STICKYFILE)) 2272 return EFTYPE; 2273 if (checkperm && (vap->va_mode & S_ISGID)) { 2274 err = fuse_internal_getattr(vp, &old_va, cred, td); 2275 if (err) 2276 return (err); 2277 if (!groupmember(old_va.va_gid, cred)) { 2278 err = priv_check_cred(cred, PRIV_VFS_SETGID); 2279 if (err) 2280 return (err); 2281 } 2282 } 2283 accmode |= VADMIN; 2284 } 2285 2286 if (vfs_isrdonly(mp)) 2287 return EROFS; 2288 2289 if (checkperm) { 2290 err = fuse_internal_access(vp, accmode, td, cred); 2291 } else { 2292 err = 0; 2293 } 2294 if (err) 2295 return err; 2296 else 2297 return fuse_internal_setattr(vp, vap, td, cred); 2298 } 2299 2300 /* 2301 struct vnop_strategy_args { 2302 struct vnode *a_vp; 2303 struct buf *a_bp; 2304 }; 2305 */ 2306 static int 2307 fuse_vnop_strategy(struct vop_strategy_args *ap) 2308 { 2309 struct vnode *vp = ap->a_vp; 2310 struct buf *bp = ap->a_bp; 2311 2312 if (!vp || fuse_isdeadfs(vp)) { 2313 bp->b_ioflags |= BIO_ERROR; 2314 bp->b_error = ENXIO; 2315 bufdone(bp); 2316 return 0; 2317 } 2318 2319 /* 2320 * VOP_STRATEGY always returns zero and signals error via bp->b_ioflags. 2321 * fuse_io_strategy sets bp's error fields 2322 */ 2323 (void)fuse_io_strategy(vp, bp); 2324 2325 return 0; 2326 } 2327 2328 /* 2329 struct vnop_symlink_args { 2330 struct vnode *a_dvp; 2331 struct vnode **a_vpp; 2332 struct componentname *a_cnp; 2333 struct vattr *a_vap; 2334 char *a_target; 2335 }; 2336 */ 2337 static int 2338 fuse_vnop_symlink(struct vop_symlink_args *ap) 2339 { 2340 struct vnode *dvp = ap->a_dvp; 2341 struct vnode **vpp = ap->a_vpp; 2342 struct componentname *cnp = ap->a_cnp; 2343 const char *target = ap->a_target; 2344 2345 struct fuse_dispatcher fdi; 2346 2347 int err; 2348 size_t len; 2349 2350 if (fuse_isdeadfs(dvp)) { 2351 return ENXIO; 2352 } 2353 /* 2354 * Unlike the other creator type calls, here we have to create a message 2355 * where the name of the new entry comes first, and the data describing 2356 * the entry comes second. 2357 * Hence we can't rely on our handy fuse_internal_newentry() routine, 2358 * but put together the message manually and just call the core part. 2359 */ 2360 2361 len = strlen(target) + 1; 2362 fdisp_init(&fdi, len + cnp->cn_namelen + 1); 2363 fdisp_make_vp(&fdi, FUSE_SYMLINK, dvp, curthread, NULL); 2364 2365 memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen); 2366 ((char *)fdi.indata)[cnp->cn_namelen] = '\0'; 2367 memcpy((char *)fdi.indata + cnp->cn_namelen + 1, target, len); 2368 2369 err = fuse_internal_newentry_core(dvp, vpp, cnp, VLNK, &fdi); 2370 fdisp_destroy(&fdi); 2371 return err; 2372 } 2373 2374 /* 2375 struct vnop_write_args { 2376 struct vnode *a_vp; 2377 struct uio *a_uio; 2378 int a_ioflag; 2379 struct ucred *a_cred; 2380 }; 2381 */ 2382 static int 2383 fuse_vnop_write(struct vop_write_args *ap) 2384 { 2385 struct vnode *vp = ap->a_vp; 2386 struct uio *uio = ap->a_uio; 2387 int ioflag = ap->a_ioflag; 2388 struct ucred *cred = ap->a_cred; 2389 pid_t pid = curthread->td_proc->p_pid; 2390 struct fuse_filehandle *fufh; 2391 int err; 2392 bool closefufh = false, directio; 2393 2394 MPASS(vp->v_type == VREG || vp->v_type == VDIR); 2395 2396 if (fuse_isdeadfs(vp)) { 2397 return ENXIO; 2398 } 2399 2400 if (VTOFUD(vp)->flag & FN_DIRECTIO) { 2401 ioflag |= IO_DIRECT; 2402 } 2403 2404 err = fuse_filehandle_getrw(vp, FWRITE, &fufh, cred, pid); 2405 if (err == EBADF && vnode_mount(vp)->mnt_flag & MNT_EXPORTED) { 2406 /* 2407 * nfsd will do I/O without first doing VOP_OPEN. We 2408 * must implicitly open the file here 2409 */ 2410 err = fuse_filehandle_open(vp, FWRITE, &fufh, curthread, cred); 2411 closefufh = true; 2412 } 2413 if (err) { 2414 SDT_PROBE3(fusefs, , vnops, filehandles_closed, vp, uio, cred); 2415 return err; 2416 } 2417 2418 /* 2419 * Ideally, when the daemon asks for direct io at open time, the 2420 * standard file flag should be set according to this, so that would 2421 * just change the default mode, which later on could be changed via 2422 * fcntl(2). 2423 * But this doesn't work, the O_DIRECT flag gets cleared at some point 2424 * (don't know where). So to make any use of the Fuse direct_io option, 2425 * we hardwire it into the file's private data (similarly to Linux, 2426 * btw.). 2427 */ 2428 directio = (ioflag & IO_DIRECT) || !fsess_opt_datacache(vnode_mount(vp)); 2429 2430 fuse_vnode_update(vp, FN_MTIMECHANGE | FN_CTIMECHANGE); 2431 if (directio) { 2432 off_t start, end, filesize; 2433 bool pages = (ioflag & IO_VMIO) != 0; 2434 2435 SDT_PROBE2(fusefs, , vnops, trace, 1, "direct write of vnode"); 2436 2437 err = fuse_vnode_size(vp, &filesize, cred, curthread); 2438 if (err) 2439 goto out; 2440 2441 start = uio->uio_offset; 2442 end = start + uio->uio_resid; 2443 if (!pages) { 2444 err = fuse_inval_buf_range(vp, filesize, start, 2445 end); 2446 if (err) 2447 goto out; 2448 } 2449 err = fuse_write_directbackend(vp, uio, cred, fufh, 2450 filesize, ioflag, pages); 2451 } else { 2452 SDT_PROBE2(fusefs, , vnops, trace, 1, 2453 "buffered write of vnode"); 2454 if (!fsess_opt_writeback(vnode_mount(vp))) 2455 ioflag |= IO_SYNC; 2456 err = fuse_write_biobackend(vp, uio, cred, fufh, ioflag, pid); 2457 } 2458 fuse_internal_clear_suid_on_write(vp, cred, uio->uio_td); 2459 2460 out: 2461 if (closefufh) 2462 fuse_filehandle_close(vp, fufh, curthread, cred); 2463 2464 return (err); 2465 } 2466 2467 static daddr_t 2468 fuse_gbp_getblkno(struct vnode *vp, vm_ooffset_t off) 2469 { 2470 const int biosize = fuse_iosize(vp); 2471 2472 return (off / biosize); 2473 } 2474 2475 static int 2476 fuse_gbp_getblksz(struct vnode *vp, daddr_t lbn, long *blksz) 2477 { 2478 off_t filesize; 2479 int err; 2480 const int biosize = fuse_iosize(vp); 2481 2482 err = fuse_vnode_size(vp, &filesize, NULL, NULL); 2483 if (err) { 2484 /* This will turn into a SIGBUS */ 2485 return (EIO); 2486 } else if ((off_t)lbn * biosize >= filesize) { 2487 *blksz = 0; 2488 } else if ((off_t)(lbn + 1) * biosize > filesize) { 2489 *blksz = filesize - (off_t)lbn *biosize; 2490 } else { 2491 *blksz = biosize; 2492 } 2493 return (0); 2494 } 2495 2496 /* 2497 struct vnop_getpages_args { 2498 struct vnode *a_vp; 2499 vm_page_t *a_m; 2500 int a_count; 2501 int a_reqpage; 2502 }; 2503 */ 2504 static int 2505 fuse_vnop_getpages(struct vop_getpages_args *ap) 2506 { 2507 struct vnode *vp = ap->a_vp; 2508 2509 if (!fsess_opt_mmap(vnode_mount(vp))) { 2510 SDT_PROBE2(fusefs, , vnops, trace, 1, 2511 "called on non-cacheable vnode??\n"); 2512 return (VM_PAGER_ERROR); 2513 } 2514 2515 return (vfs_bio_getpages(vp, ap->a_m, ap->a_count, ap->a_rbehind, 2516 ap->a_rahead, fuse_gbp_getblkno, fuse_gbp_getblksz)); 2517 } 2518 2519 static const char extattr_namespace_separator = '.'; 2520 2521 /* 2522 struct vop_getextattr_args { 2523 struct vop_generic_args a_gen; 2524 struct vnode *a_vp; 2525 int a_attrnamespace; 2526 const char *a_name; 2527 struct uio *a_uio; 2528 size_t *a_size; 2529 struct ucred *a_cred; 2530 struct thread *a_td; 2531 }; 2532 */ 2533 static int 2534 fuse_vnop_getextattr(struct vop_getextattr_args *ap) 2535 { 2536 struct vnode *vp = ap->a_vp; 2537 struct uio *uio = ap->a_uio; 2538 struct fuse_dispatcher fdi; 2539 struct fuse_getxattr_in *get_xattr_in; 2540 struct fuse_getxattr_out *get_xattr_out; 2541 struct mount *mp = vnode_mount(vp); 2542 struct thread *td = ap->a_td; 2543 struct ucred *cred = ap->a_cred; 2544 char *prefix; 2545 char *attr_str; 2546 size_t len; 2547 int err; 2548 2549 if (fuse_isdeadfs(vp)) 2550 return (ENXIO); 2551 2552 if (fsess_not_impl(mp, FUSE_GETXATTR)) 2553 return EOPNOTSUPP; 2554 2555 err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, VREAD); 2556 if (err) 2557 return err; 2558 2559 /* Default to looking for user attributes. */ 2560 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2561 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2562 else 2563 prefix = EXTATTR_NAMESPACE_USER_STRING; 2564 2565 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2566 strlen(ap->a_name) + 1; 2567 2568 fdisp_init(&fdi, len + sizeof(*get_xattr_in)); 2569 fdisp_make_vp(&fdi, FUSE_GETXATTR, vp, td, cred); 2570 2571 get_xattr_in = fdi.indata; 2572 /* 2573 * Check to see whether we're querying the available size or 2574 * issuing the actual request. If we pass in 0, we get back struct 2575 * fuse_getxattr_out. If we pass in a non-zero size, we get back 2576 * that much data, without the struct fuse_getxattr_out header. 2577 */ 2578 if (uio == NULL) 2579 get_xattr_in->size = 0; 2580 else 2581 get_xattr_in->size = uio->uio_resid; 2582 2583 attr_str = (char *)fdi.indata + sizeof(*get_xattr_in); 2584 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2585 ap->a_name); 2586 2587 err = fdisp_wait_answ(&fdi); 2588 if (err != 0) { 2589 if (err == ENOSYS) { 2590 fsess_set_notimpl(mp, FUSE_GETXATTR); 2591 err = EOPNOTSUPP; 2592 } 2593 goto out; 2594 } 2595 2596 get_xattr_out = fdi.answ; 2597 2598 if (ap->a_size != NULL) 2599 *ap->a_size = get_xattr_out->size; 2600 2601 if (uio != NULL) 2602 err = uiomove(fdi.answ, fdi.iosize, uio); 2603 2604 out: 2605 fdisp_destroy(&fdi); 2606 return (err); 2607 } 2608 2609 /* 2610 struct vop_setextattr_args { 2611 struct vop_generic_args a_gen; 2612 struct vnode *a_vp; 2613 int a_attrnamespace; 2614 const char *a_name; 2615 struct uio *a_uio; 2616 struct ucred *a_cred; 2617 struct thread *a_td; 2618 }; 2619 */ 2620 static int 2621 fuse_vnop_setextattr(struct vop_setextattr_args *ap) 2622 { 2623 struct vnode *vp = ap->a_vp; 2624 struct uio *uio = ap->a_uio; 2625 struct fuse_dispatcher fdi; 2626 struct fuse_setxattr_in *set_xattr_in; 2627 struct mount *mp = vnode_mount(vp); 2628 struct thread *td = ap->a_td; 2629 struct ucred *cred = ap->a_cred; 2630 char *prefix; 2631 size_t len; 2632 char *attr_str; 2633 int err; 2634 2635 if (fuse_isdeadfs(vp)) 2636 return (ENXIO); 2637 2638 if (fsess_not_impl(mp, FUSE_SETXATTR)) 2639 return EOPNOTSUPP; 2640 2641 if (vfs_isrdonly(mp)) 2642 return EROFS; 2643 2644 /* Deleting xattrs must use VOP_DELETEEXTATTR instead */ 2645 if (ap->a_uio == NULL) { 2646 /* 2647 * If we got here as fallback from VOP_DELETEEXTATTR, then 2648 * return EOPNOTSUPP. 2649 */ 2650 if (fsess_not_impl(mp, FUSE_REMOVEXATTR)) 2651 return (EOPNOTSUPP); 2652 else 2653 return (EINVAL); 2654 } 2655 2656 err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, 2657 VWRITE); 2658 if (err) 2659 return err; 2660 2661 /* Default to looking for user attributes. */ 2662 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2663 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2664 else 2665 prefix = EXTATTR_NAMESPACE_USER_STRING; 2666 2667 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2668 strlen(ap->a_name) + 1; 2669 2670 fdisp_init(&fdi, len + sizeof(*set_xattr_in) + uio->uio_resid); 2671 fdisp_make_vp(&fdi, FUSE_SETXATTR, vp, td, cred); 2672 2673 set_xattr_in = fdi.indata; 2674 set_xattr_in->size = uio->uio_resid; 2675 2676 attr_str = (char *)fdi.indata + sizeof(*set_xattr_in); 2677 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2678 ap->a_name); 2679 2680 err = uiomove((char *)fdi.indata + sizeof(*set_xattr_in) + len, 2681 uio->uio_resid, uio); 2682 if (err != 0) { 2683 goto out; 2684 } 2685 2686 err = fdisp_wait_answ(&fdi); 2687 2688 if (err == ENOSYS) { 2689 fsess_set_notimpl(mp, FUSE_SETXATTR); 2690 err = EOPNOTSUPP; 2691 } 2692 if (err == ERESTART) { 2693 /* Can't restart after calling uiomove */ 2694 err = EINTR; 2695 } 2696 2697 out: 2698 fdisp_destroy(&fdi); 2699 return (err); 2700 } 2701 2702 /* 2703 * The Linux / FUSE extended attribute list is simply a collection of 2704 * NUL-terminated strings. The FreeBSD extended attribute list is a single 2705 * byte length followed by a non-NUL terminated string. So, this allows 2706 * conversion of the Linux / FUSE format to the FreeBSD format in place. 2707 * Linux attribute names are reported with the namespace as a prefix (e.g. 2708 * "user.attribute_name"), but in FreeBSD they are reported without the 2709 * namespace prefix (e.g. "attribute_name"). So, we're going from: 2710 * 2711 * user.attr_name1\0user.attr_name2\0 2712 * 2713 * to: 2714 * 2715 * <num>attr_name1<num>attr_name2 2716 * 2717 * Where "<num>" is a single byte number of characters in the attribute name. 2718 * 2719 * Args: 2720 * prefix - exattr namespace prefix string 2721 * list, list_len - input list with namespace prefixes 2722 * bsd_list, bsd_list_len - output list compatible with bsd vfs 2723 */ 2724 static int 2725 fuse_xattrlist_convert(char *prefix, const char *list, int list_len, 2726 char *bsd_list, int *bsd_list_len) 2727 { 2728 int len, pos, dist_to_next, prefix_len; 2729 2730 pos = 0; 2731 *bsd_list_len = 0; 2732 prefix_len = strlen(prefix); 2733 2734 while (pos < list_len && list[pos] != '\0') { 2735 dist_to_next = strlen(&list[pos]) + 1; 2736 if (bcmp(&list[pos], prefix, prefix_len) == 0 && 2737 list[pos + prefix_len] == extattr_namespace_separator) { 2738 len = dist_to_next - 2739 (prefix_len + sizeof(extattr_namespace_separator)) - 1; 2740 if (len >= EXTATTR_MAXNAMELEN) 2741 return (ENAMETOOLONG); 2742 2743 bsd_list[*bsd_list_len] = len; 2744 memcpy(&bsd_list[*bsd_list_len + 1], 2745 &list[pos + prefix_len + 2746 sizeof(extattr_namespace_separator)], len); 2747 2748 *bsd_list_len += len + 1; 2749 } 2750 2751 pos += dist_to_next; 2752 } 2753 2754 return (0); 2755 } 2756 2757 /* 2758 * List extended attributes 2759 * 2760 * The FUSE_LISTXATTR operation is based on Linux's listxattr(2) syscall, which 2761 * has a number of differences compared to its FreeBSD equivalent, 2762 * extattr_list_file: 2763 * 2764 * - FUSE_LISTXATTR returns all extended attributes across all namespaces, 2765 * whereas listxattr(2) only returns attributes for a single namespace 2766 * - FUSE_LISTXATTR prepends each attribute name with "namespace." 2767 * - If the provided buffer is not large enough to hold the result, 2768 * FUSE_LISTXATTR should return ERANGE, whereas listxattr is expected to 2769 * return as many results as will fit. 2770 */ 2771 /* 2772 struct vop_listextattr_args { 2773 struct vop_generic_args a_gen; 2774 struct vnode *a_vp; 2775 int a_attrnamespace; 2776 struct uio *a_uio; 2777 size_t *a_size; 2778 struct ucred *a_cred; 2779 struct thread *a_td; 2780 }; 2781 */ 2782 static int 2783 fuse_vnop_listextattr(struct vop_listextattr_args *ap) 2784 { 2785 struct vnode *vp = ap->a_vp; 2786 struct uio *uio = ap->a_uio; 2787 struct fuse_dispatcher fdi; 2788 struct fuse_listxattr_in *list_xattr_in; 2789 struct fuse_listxattr_out *list_xattr_out; 2790 struct mount *mp = vnode_mount(vp); 2791 struct thread *td = ap->a_td; 2792 struct ucred *cred = ap->a_cred; 2793 char *prefix; 2794 char *bsd_list = NULL; 2795 char *linux_list; 2796 int bsd_list_len; 2797 int linux_list_len; 2798 int err; 2799 2800 if (fuse_isdeadfs(vp)) 2801 return (ENXIO); 2802 2803 if (fsess_not_impl(mp, FUSE_LISTXATTR)) 2804 return EOPNOTSUPP; 2805 2806 err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, VREAD); 2807 if (err) 2808 return err; 2809 2810 /* 2811 * Add space for a NUL and the period separator if enabled. 2812 * Default to looking for user attributes. 2813 */ 2814 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2815 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2816 else 2817 prefix = EXTATTR_NAMESPACE_USER_STRING; 2818 2819 fdisp_init(&fdi, sizeof(*list_xattr_in)); 2820 fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred); 2821 2822 /* 2823 * Retrieve Linux / FUSE compatible list size. 2824 */ 2825 list_xattr_in = fdi.indata; 2826 list_xattr_in->size = 0; 2827 2828 err = fdisp_wait_answ(&fdi); 2829 if (err != 0) { 2830 if (err == ENOSYS) { 2831 fsess_set_notimpl(mp, FUSE_LISTXATTR); 2832 err = EOPNOTSUPP; 2833 } 2834 goto out; 2835 } 2836 2837 list_xattr_out = fdi.answ; 2838 linux_list_len = list_xattr_out->size; 2839 if (linux_list_len == 0) { 2840 if (ap->a_size != NULL) 2841 *ap->a_size = linux_list_len; 2842 goto out; 2843 } 2844 2845 /* 2846 * Retrieve Linux / FUSE compatible list values. 2847 */ 2848 fdisp_refresh_vp(&fdi, FUSE_LISTXATTR, vp, td, cred); 2849 list_xattr_in = fdi.indata; 2850 list_xattr_in->size = linux_list_len; 2851 2852 err = fdisp_wait_answ(&fdi); 2853 if (err == ERANGE) { 2854 /* 2855 * Race detected. The attribute list must've grown since the 2856 * first FUSE_LISTXATTR call. Start over. Go all the way back 2857 * to userland so we can process signals, if necessary, before 2858 * restarting. 2859 */ 2860 err = ERESTART; 2861 goto out; 2862 } else if (err != 0) 2863 goto out; 2864 2865 linux_list = fdi.answ; 2866 /* FUSE doesn't allow the server to return more data than requested */ 2867 if (fdi.iosize > linux_list_len) { 2868 struct fuse_data *data = fuse_get_mpdata(mp); 2869 2870 fuse_warn(data, FSESS_WARN_LSEXTATTR_LONG, 2871 "server returned " 2872 "more extended attribute data than requested; " 2873 "should've returned ERANGE instead."); 2874 } else { 2875 /* But returning less data is fine */ 2876 linux_list_len = fdi.iosize; 2877 } 2878 2879 /* 2880 * Retrieve the BSD compatible list values. 2881 * The Linux / FUSE attribute list format isn't the same 2882 * as FreeBSD's format. So we need to transform it into 2883 * FreeBSD's format before giving it to the user. 2884 */ 2885 bsd_list = malloc(linux_list_len, M_TEMP, M_WAITOK); 2886 err = fuse_xattrlist_convert(prefix, linux_list, linux_list_len, 2887 bsd_list, &bsd_list_len); 2888 if (err != 0) 2889 goto out; 2890 2891 if (ap->a_size != NULL) 2892 *ap->a_size = bsd_list_len; 2893 2894 if (uio != NULL) 2895 err = uiomove(bsd_list, bsd_list_len, uio); 2896 2897 out: 2898 free(bsd_list, M_TEMP); 2899 fdisp_destroy(&fdi); 2900 return (err); 2901 } 2902 2903 /* 2904 struct vop_deleteextattr_args { 2905 struct vop_generic_args a_gen; 2906 struct vnode *a_vp; 2907 int a_attrnamespace; 2908 const char *a_name; 2909 struct ucred *a_cred; 2910 struct thread *a_td; 2911 }; 2912 */ 2913 static int 2914 fuse_vnop_deleteextattr(struct vop_deleteextattr_args *ap) 2915 { 2916 struct vnode *vp = ap->a_vp; 2917 struct fuse_dispatcher fdi; 2918 struct mount *mp = vnode_mount(vp); 2919 struct thread *td = ap->a_td; 2920 struct ucred *cred = ap->a_cred; 2921 char *prefix; 2922 size_t len; 2923 char *attr_str; 2924 int err; 2925 2926 if (fuse_isdeadfs(vp)) 2927 return (ENXIO); 2928 2929 if (fsess_not_impl(mp, FUSE_REMOVEXATTR)) 2930 return EOPNOTSUPP; 2931 2932 if (vfs_isrdonly(mp)) 2933 return EROFS; 2934 2935 err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, 2936 VWRITE); 2937 if (err) 2938 return err; 2939 2940 /* Default to looking for user attributes. */ 2941 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2942 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2943 else 2944 prefix = EXTATTR_NAMESPACE_USER_STRING; 2945 2946 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2947 strlen(ap->a_name) + 1; 2948 2949 fdisp_init(&fdi, len); 2950 fdisp_make_vp(&fdi, FUSE_REMOVEXATTR, vp, td, cred); 2951 2952 attr_str = fdi.indata; 2953 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2954 ap->a_name); 2955 2956 err = fdisp_wait_answ(&fdi); 2957 if (err == ENOSYS) { 2958 fsess_set_notimpl(mp, FUSE_REMOVEXATTR); 2959 err = EOPNOTSUPP; 2960 } 2961 2962 fdisp_destroy(&fdi); 2963 return (err); 2964 } 2965 2966 /* 2967 struct vnop_print_args { 2968 struct vnode *a_vp; 2969 }; 2970 */ 2971 static int 2972 fuse_vnop_print(struct vop_print_args *ap) 2973 { 2974 struct fuse_vnode_data *fvdat = VTOFUD(ap->a_vp); 2975 2976 printf("nodeid: %ju, parent nodeid: %ju, nlookup: %ju, flag: %#x\n", 2977 (uintmax_t)VTOILLU(ap->a_vp), (uintmax_t)fvdat->parent_nid, 2978 (uintmax_t)fvdat->nlookup, 2979 fvdat->flag); 2980 2981 return 0; 2982 } 2983 2984 /* 2985 * Get an NFS filehandle for a FUSE file. 2986 * 2987 * This will only work for FUSE file systems that guarantee the uniqueness of 2988 * nodeid:generation, which most don't. 2989 */ 2990 /* 2991 vop_vptofh { 2992 IN struct vnode *a_vp; 2993 IN struct fid *a_fhp; 2994 }; 2995 */ 2996 static int 2997 fuse_vnop_vptofh(struct vop_vptofh_args *ap) 2998 { 2999 struct vnode *vp = ap->a_vp; 3000 struct fuse_vnode_data *fvdat = VTOFUD(vp); 3001 struct fuse_fid *fhp = (struct fuse_fid *)(ap->a_fhp); 3002 _Static_assert(sizeof(struct fuse_fid) <= sizeof(struct fid), 3003 "FUSE fid type is too big"); 3004 struct mount *mp = vnode_mount(vp); 3005 struct fuse_data *data = fuse_get_mpdata(mp); 3006 struct vattr va; 3007 int err; 3008 3009 if (!(data->dataflags & FSESS_EXPORT_SUPPORT)) 3010 return EOPNOTSUPP; 3011 3012 err = fuse_internal_getattr(vp, &va, curthread->td_ucred, curthread); 3013 if (err) 3014 return err; 3015 3016 /*ip = VTOI(ap->a_vp);*/ 3017 /*ufhp = (struct ufid *)ap->a_fhp;*/ 3018 fhp->len = sizeof(struct fuse_fid); 3019 fhp->nid = fvdat->nid; 3020 if (fvdat->generation <= UINT32_MAX) 3021 fhp->gen = fvdat->generation; 3022 else 3023 return EOVERFLOW; 3024 return (0); 3025 } 3026