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