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