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