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