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 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 45 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 */ 57 58 #include <sys/cdefs.h> 59 __FBSDID("$FreeBSD$"); 60 61 #include <sys/param.h> 62 #include <sys/module.h> 63 #include <sys/systm.h> 64 #include <sys/errno.h> 65 #include <sys/kernel.h> 66 #include <sys/conf.h> 67 #include <sys/uio.h> 68 #include <sys/malloc.h> 69 #include <sys/queue.h> 70 #include <sys/limits.h> 71 #include <sys/lock.h> 72 #include <sys/rwlock.h> 73 #include <sys/sx.h> 74 #include <sys/proc.h> 75 #include <sys/mount.h> 76 #include <sys/vnode.h> 77 #include <sys/namei.h> 78 #include <sys/extattr.h> 79 #include <sys/stat.h> 80 #include <sys/unistd.h> 81 #include <sys/filedesc.h> 82 #include <sys/file.h> 83 #include <sys/fcntl.h> 84 #include <sys/dirent.h> 85 #include <sys/bio.h> 86 #include <sys/buf.h> 87 #include <sys/sysctl.h> 88 #include <sys/vmmeter.h> 89 90 #include <vm/vm.h> 91 #include <vm/vm_extern.h> 92 #include <vm/pmap.h> 93 #include <vm/vm_map.h> 94 #include <vm/vm_page.h> 95 #include <vm/vm_param.h> 96 #include <vm/vm_object.h> 97 #include <vm/vm_pager.h> 98 #include <vm/vnode_pager.h> 99 #include <vm/vm_object.h> 100 101 #include "fuse.h" 102 #include "fuse_file.h" 103 #include "fuse_internal.h" 104 #include "fuse_ipc.h" 105 #include "fuse_node.h" 106 #include "fuse_param.h" 107 #include "fuse_io.h" 108 109 #include <sys/priv.h> 110 111 SDT_PROVIDER_DECLARE(fuse); 112 /* 113 * Fuse trace probe: 114 * arg0: verbosity. Higher numbers give more verbose messages 115 * arg1: Textual message 116 */ 117 SDT_PROBE_DEFINE2(fuse, , vnops, trace, "int", "char*"); 118 119 /* vnode ops */ 120 static vop_access_t fuse_vnop_access; 121 static vop_close_t fuse_vnop_close; 122 static vop_create_t fuse_vnop_create; 123 static vop_deleteextattr_t fuse_vnop_deleteextattr; 124 static vop_fsync_t fuse_vnop_fsync; 125 static vop_getattr_t fuse_vnop_getattr; 126 static vop_getextattr_t fuse_vnop_getextattr; 127 static vop_inactive_t fuse_vnop_inactive; 128 static vop_link_t fuse_vnop_link; 129 static vop_listextattr_t fuse_vnop_listextattr; 130 static vop_lookup_t fuse_vnop_lookup; 131 static vop_mkdir_t fuse_vnop_mkdir; 132 static vop_mknod_t fuse_vnop_mknod; 133 static vop_open_t fuse_vnop_open; 134 static vop_pathconf_t fuse_vnop_pathconf; 135 static vop_read_t fuse_vnop_read; 136 static vop_readdir_t fuse_vnop_readdir; 137 static vop_readlink_t fuse_vnop_readlink; 138 static vop_reclaim_t fuse_vnop_reclaim; 139 static vop_remove_t fuse_vnop_remove; 140 static vop_rename_t fuse_vnop_rename; 141 static vop_rmdir_t fuse_vnop_rmdir; 142 static vop_setattr_t fuse_vnop_setattr; 143 static vop_setextattr_t fuse_vnop_setextattr; 144 static vop_strategy_t fuse_vnop_strategy; 145 static vop_symlink_t fuse_vnop_symlink; 146 static vop_write_t fuse_vnop_write; 147 static vop_getpages_t fuse_vnop_getpages; 148 static vop_putpages_t fuse_vnop_putpages; 149 static vop_print_t fuse_vnop_print; 150 151 struct vop_vector fuse_vnops = { 152 .vop_default = &default_vnodeops, 153 .vop_access = fuse_vnop_access, 154 .vop_close = fuse_vnop_close, 155 .vop_create = fuse_vnop_create, 156 .vop_deleteextattr = fuse_vnop_deleteextattr, 157 .vop_fsync = fuse_vnop_fsync, 158 .vop_getattr = fuse_vnop_getattr, 159 .vop_getextattr = fuse_vnop_getextattr, 160 .vop_inactive = fuse_vnop_inactive, 161 .vop_link = fuse_vnop_link, 162 .vop_listextattr = fuse_vnop_listextattr, 163 .vop_lookup = fuse_vnop_lookup, 164 .vop_mkdir = fuse_vnop_mkdir, 165 .vop_mknod = fuse_vnop_mknod, 166 .vop_open = fuse_vnop_open, 167 .vop_pathconf = fuse_vnop_pathconf, 168 .vop_read = fuse_vnop_read, 169 .vop_readdir = fuse_vnop_readdir, 170 .vop_readlink = fuse_vnop_readlink, 171 .vop_reclaim = fuse_vnop_reclaim, 172 .vop_remove = fuse_vnop_remove, 173 .vop_rename = fuse_vnop_rename, 174 .vop_rmdir = fuse_vnop_rmdir, 175 .vop_setattr = fuse_vnop_setattr, 176 .vop_setextattr = fuse_vnop_setextattr, 177 .vop_strategy = fuse_vnop_strategy, 178 .vop_symlink = fuse_vnop_symlink, 179 .vop_write = fuse_vnop_write, 180 .vop_getpages = fuse_vnop_getpages, 181 .vop_putpages = fuse_vnop_putpages, 182 .vop_print = fuse_vnop_print, 183 }; 184 185 static u_long fuse_lookup_cache_hits = 0; 186 187 SYSCTL_ULONG(_vfs_fusefs, OID_AUTO, lookup_cache_hits, CTLFLAG_RD, 188 &fuse_lookup_cache_hits, 0, "number of positive cache hits in lookup"); 189 190 static u_long fuse_lookup_cache_misses = 0; 191 192 SYSCTL_ULONG(_vfs_fusefs, OID_AUTO, lookup_cache_misses, CTLFLAG_RD, 193 &fuse_lookup_cache_misses, 0, "number of cache misses in lookup"); 194 195 int fuse_lookup_cache_enable = 1; 196 197 SYSCTL_INT(_vfs_fusefs, OID_AUTO, lookup_cache_enable, CTLFLAG_RW, 198 &fuse_lookup_cache_enable, 0, "if non-zero, enable lookup cache"); 199 200 /* 201 * XXX: This feature is highly experimental and can bring to instabilities, 202 * needs revisiting before to be enabled by default. 203 */ 204 static int fuse_reclaim_revoked = 0; 205 206 SYSCTL_INT(_vfs_fusefs, OID_AUTO, reclaim_revoked, CTLFLAG_RW, 207 &fuse_reclaim_revoked, 0, ""); 208 209 uma_zone_t fuse_pbuf_zone; 210 211 #define fuse_vm_page_lock(m) vm_page_lock((m)); 212 #define fuse_vm_page_unlock(m) vm_page_unlock((m)); 213 #define fuse_vm_page_lock_queues() ((void)0) 214 #define fuse_vm_page_unlock_queues() ((void)0) 215 216 /* 217 struct vnop_access_args { 218 struct vnode *a_vp; 219 #if VOP_ACCESS_TAKES_ACCMODE_T 220 accmode_t a_accmode; 221 #else 222 int a_mode; 223 #endif 224 struct ucred *a_cred; 225 struct thread *a_td; 226 }; 227 */ 228 static int 229 fuse_vnop_access(struct vop_access_args *ap) 230 { 231 struct vnode *vp = ap->a_vp; 232 int accmode = ap->a_accmode; 233 struct ucred *cred = ap->a_cred; 234 235 struct fuse_access_param facp; 236 struct fuse_data *data = fuse_get_mpdata(vnode_mount(vp)); 237 238 int err; 239 240 if (fuse_isdeadfs(vp)) { 241 if (vnode_isvroot(vp)) { 242 return 0; 243 } 244 return ENXIO; 245 } 246 if (!(data->dataflags & FSESS_INITED)) { 247 if (vnode_isvroot(vp)) { 248 if (priv_check_cred(cred, PRIV_VFS_ADMIN) || 249 (fuse_match_cred(data->daemoncred, cred) == 0)) { 250 return 0; 251 } 252 } 253 return EBADF; 254 } 255 if (vnode_islnk(vp)) { 256 return 0; 257 } 258 bzero(&facp, sizeof(facp)); 259 260 err = fuse_internal_access(vp, accmode, &facp, ap->a_td, ap->a_cred); 261 return err; 262 } 263 264 /* 265 struct vnop_close_args { 266 struct vnode *a_vp; 267 int a_fflag; 268 struct ucred *a_cred; 269 struct thread *a_td; 270 }; 271 */ 272 static int 273 fuse_vnop_close(struct vop_close_args *ap) 274 { 275 struct vnode *vp = ap->a_vp; 276 struct ucred *cred = ap->a_cred; 277 int fflag = ap->a_fflag; 278 fufh_type_t fufh_type; 279 280 if (fuse_isdeadfs(vp)) { 281 return 0; 282 } 283 if (vnode_isdir(vp)) { 284 if (fuse_filehandle_valid(vp, FUFH_RDONLY)) { 285 fuse_filehandle_close(vp, FUFH_RDONLY, NULL, cred); 286 } 287 return 0; 288 } 289 if (fflag & IO_NDELAY) { 290 return 0; 291 } 292 fufh_type = fuse_filehandle_xlate_from_fflags(fflag); 293 294 if (!fuse_filehandle_valid(vp, fufh_type)) { 295 int i; 296 297 for (i = 0; i < FUFH_MAXTYPE; i++) 298 if (fuse_filehandle_valid(vp, i)) 299 break; 300 if (i == FUFH_MAXTYPE) 301 panic("FUSE: fufh type %d found to be invalid in close" 302 " (fflag=0x%x)\n", 303 fufh_type, fflag); 304 } 305 if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) { 306 fuse_vnode_savesize(vp, cred); 307 } 308 return 0; 309 } 310 311 /* 312 struct vnop_create_args { 313 struct vnode *a_dvp; 314 struct vnode **a_vpp; 315 struct componentname *a_cnp; 316 struct vattr *a_vap; 317 }; 318 */ 319 static int 320 fuse_vnop_create(struct vop_create_args *ap) 321 { 322 struct vnode *dvp = ap->a_dvp; 323 struct vnode **vpp = ap->a_vpp; 324 struct componentname *cnp = ap->a_cnp; 325 struct vattr *vap = ap->a_vap; 326 struct thread *td = cnp->cn_thread; 327 struct ucred *cred = cnp->cn_cred; 328 329 struct fuse_open_in *foi; 330 struct fuse_entry_out *feo; 331 struct fuse_dispatcher fdi; 332 struct fuse_dispatcher *fdip = &fdi; 333 334 int err; 335 336 struct mount *mp = vnode_mount(dvp); 337 uint64_t parentnid = VTOFUD(dvp)->nid; 338 mode_t mode = MAKEIMODE(vap->va_type, vap->va_mode); 339 uint64_t x_fh_id; 340 uint32_t x_open_flags; 341 342 if (fuse_isdeadfs(dvp)) { 343 return ENXIO; 344 } 345 bzero(&fdi, sizeof(fdi)); 346 347 /* XXX: Will we ever want devices ? */ 348 if ((vap->va_type != VREG)) { 349 printf("fuse_vnop_create: unsupported va_type %d\n", 350 vap->va_type); 351 return (EINVAL); 352 } 353 354 fdisp_init(fdip, sizeof(*foi) + cnp->cn_namelen + 1); 355 if (!fsess_isimpl(mp, FUSE_CREATE)) { 356 SDT_PROBE2(fuse, , vnops, trace, 1, 357 "eh, daemon doesn't implement create?"); 358 return (EINVAL); 359 } 360 fdisp_make(fdip, FUSE_CREATE, vnode_mount(dvp), parentnid, td, cred); 361 362 foi = fdip->indata; 363 foi->mode = mode; 364 foi->flags = O_CREAT | O_RDWR; 365 366 memcpy((char *)fdip->indata + sizeof(*foi), cnp->cn_nameptr, 367 cnp->cn_namelen); 368 ((char *)fdip->indata)[sizeof(*foi) + cnp->cn_namelen] = '\0'; 369 370 err = fdisp_wait_answ(fdip); 371 372 if (err) { 373 if (err == ENOSYS) 374 fsess_set_notimpl(mp, FUSE_CREATE); 375 goto out; 376 } 377 378 feo = fdip->answ; 379 380 if ((err = fuse_internal_checkentry(feo, VREG))) { 381 goto out; 382 } 383 err = fuse_vnode_get(mp, feo, feo->nodeid, dvp, vpp, cnp, VREG); 384 if (err) { 385 struct fuse_release_in *fri; 386 uint64_t nodeid = feo->nodeid; 387 uint64_t fh_id = ((struct fuse_open_out *)(feo + 1))->fh; 388 389 fdisp_init(fdip, sizeof(*fri)); 390 fdisp_make(fdip, FUSE_RELEASE, mp, nodeid, td, cred); 391 fri = fdip->indata; 392 fri->fh = fh_id; 393 fri->flags = OFLAGS(mode); 394 fuse_insert_callback(fdip->tick, fuse_internal_forget_callback); 395 fuse_insert_message(fdip->tick); 396 return err; 397 } 398 ASSERT_VOP_ELOCKED(*vpp, "fuse_vnop_create"); 399 400 fdip->answ = feo + 1; 401 402 x_fh_id = ((struct fuse_open_out *)(feo + 1))->fh; 403 x_open_flags = ((struct fuse_open_out *)(feo + 1))->open_flags; 404 fuse_filehandle_init(*vpp, FUFH_RDWR, NULL, x_fh_id); 405 fuse_vnode_open(*vpp, x_open_flags, td); 406 cache_purge_negative(dvp); 407 408 out: 409 fdisp_destroy(fdip); 410 return err; 411 } 412 413 /* 414 * Our vnop_fsync roughly corresponds to the FUSE_FSYNC method. The Linux 415 * version of FUSE also has a FUSE_FLUSH method. 416 * 417 * On Linux, fsync() synchronizes a file's complete in-core state with that 418 * on disk. The call is not supposed to return until the system has completed 419 * that action or until an error is detected. 420 * 421 * Linux also has an fdatasync() call that is similar to fsync() but is not 422 * required to update the metadata such as access time and modification time. 423 */ 424 425 /* 426 struct vnop_fsync_args { 427 struct vnodeop_desc *a_desc; 428 struct vnode * a_vp; 429 struct ucred * a_cred; 430 int a_waitfor; 431 struct thread * a_td; 432 }; 433 */ 434 static int 435 fuse_vnop_fsync(struct vop_fsync_args *ap) 436 { 437 struct vnode *vp = ap->a_vp; 438 struct thread *td = ap->a_td; 439 440 struct fuse_filehandle *fufh; 441 struct fuse_vnode_data *fvdat = VTOFUD(vp); 442 443 int type, err = 0; 444 445 if (fuse_isdeadfs(vp)) { 446 return 0; 447 } 448 if ((err = vop_stdfsync(ap))) 449 return err; 450 451 if (!fsess_isimpl(vnode_mount(vp), 452 (vnode_vtype(vp) == VDIR ? FUSE_FSYNCDIR : FUSE_FSYNC))) { 453 goto out; 454 } 455 for (type = 0; type < FUFH_MAXTYPE; type++) { 456 fufh = &(fvdat->fufh[type]); 457 if (FUFH_IS_VALID(fufh)) { 458 fuse_internal_fsync(vp, td, NULL, fufh); 459 } 460 } 461 462 out: 463 return 0; 464 } 465 466 /* 467 struct vnop_getattr_args { 468 struct vnode *a_vp; 469 struct vattr *a_vap; 470 struct ucred *a_cred; 471 struct thread *a_td; 472 }; 473 */ 474 static int 475 fuse_vnop_getattr(struct vop_getattr_args *ap) 476 { 477 struct vnode *vp = ap->a_vp; 478 struct vattr *vap = ap->a_vap; 479 struct ucred *cred = ap->a_cred; 480 struct thread *td = curthread; 481 struct fuse_vnode_data *fvdat = VTOFUD(vp); 482 struct fuse_attr_out *fao; 483 484 int err = 0; 485 int dataflags; 486 struct fuse_dispatcher fdi; 487 488 dataflags = fuse_get_mpdata(vnode_mount(vp))->dataflags; 489 490 /* Note that we are not bailing out on a dead file system just yet. */ 491 492 if (!(dataflags & FSESS_INITED)) { 493 if (!vnode_isvroot(vp)) { 494 fdata_set_dead(fuse_get_mpdata(vnode_mount(vp))); 495 err = ENOTCONN; 496 return err; 497 } else { 498 goto fake; 499 } 500 } 501 fdisp_init(&fdi, 0); 502 if ((err = fdisp_simple_putget_vp(&fdi, FUSE_GETATTR, vp, td, cred))) { 503 if ((err == ENOTCONN) && vnode_isvroot(vp)) { 504 /* see comment in fuse_vfsop_statfs() */ 505 fdisp_destroy(&fdi); 506 goto fake; 507 } 508 if (err == ENOENT) { 509 fuse_internal_vnode_disappear(vp); 510 } 511 goto out; 512 } 513 514 fao = (struct fuse_attr_out *)fdi.answ; 515 fuse_internal_cache_attrs(vp, &fao->attr, fao->attr_valid, 516 fao->attr_valid_nsec, vap); 517 if (vap->va_type != vnode_vtype(vp)) { 518 fuse_internal_vnode_disappear(vp); 519 err = ENOENT; 520 goto out; 521 } 522 if ((fvdat->flag & FN_SIZECHANGE) != 0) 523 vap->va_size = fvdat->filesize; 524 525 if (vnode_isreg(vp) && (fvdat->flag & FN_SIZECHANGE) == 0) { 526 /* 527 * This is for those cases when the file size changed without us 528 * knowing, and we want to catch up. 529 */ 530 off_t new_filesize = ((struct fuse_attr_out *) 531 fdi.answ)->attr.size; 532 533 if (fvdat->filesize != new_filesize) { 534 fuse_vnode_setsize(vp, new_filesize); 535 fvdat->flag &= ~FN_SIZECHANGE; 536 } 537 } 538 539 out: 540 fdisp_destroy(&fdi); 541 return err; 542 543 fake: 544 bzero(vap, sizeof(*vap)); 545 vap->va_type = vnode_vtype(vp); 546 547 return 0; 548 } 549 550 /* 551 struct vnop_inactive_args { 552 struct vnode *a_vp; 553 struct thread *a_td; 554 }; 555 */ 556 static int 557 fuse_vnop_inactive(struct vop_inactive_args *ap) 558 { 559 struct vnode *vp = ap->a_vp; 560 struct thread *td = ap->a_td; 561 562 struct fuse_vnode_data *fvdat = VTOFUD(vp); 563 struct fuse_filehandle *fufh = NULL; 564 565 int type, need_flush = 1; 566 567 for (type = 0; type < FUFH_MAXTYPE; type++) { 568 fufh = &(fvdat->fufh[type]); 569 if (FUFH_IS_VALID(fufh)) { 570 if (need_flush && vp->v_type == VREG) { 571 if ((VTOFUD(vp)->flag & FN_SIZECHANGE) != 0) { 572 fuse_vnode_savesize(vp, NULL); 573 } 574 if (fuse_data_cache_invalidate || 575 (fvdat->flag & FN_REVOKED) != 0) 576 fuse_io_invalbuf(vp, td); 577 else 578 fuse_io_flushbuf(vp, MNT_WAIT, td); 579 need_flush = 0; 580 } 581 fuse_filehandle_close(vp, type, td, NULL); 582 } 583 } 584 585 if ((fvdat->flag & FN_REVOKED) != 0 && fuse_reclaim_revoked) { 586 vrecycle(vp); 587 } 588 return 0; 589 } 590 591 /* 592 struct vnop_link_args { 593 struct vnode *a_tdvp; 594 struct vnode *a_vp; 595 struct componentname *a_cnp; 596 }; 597 */ 598 static int 599 fuse_vnop_link(struct vop_link_args *ap) 600 { 601 struct vnode *vp = ap->a_vp; 602 struct vnode *tdvp = ap->a_tdvp; 603 struct componentname *cnp = ap->a_cnp; 604 605 struct vattr *vap = VTOVA(vp); 606 607 struct fuse_dispatcher fdi; 608 struct fuse_entry_out *feo; 609 struct fuse_link_in fli; 610 611 int err; 612 613 if (fuse_isdeadfs(vp)) { 614 return ENXIO; 615 } 616 if (vnode_mount(tdvp) != vnode_mount(vp)) { 617 return EXDEV; 618 } 619 620 /* 621 * This is a seatbelt check to protect naive userspace filesystems from 622 * themselves and the limitations of the FUSE IPC protocol. If a 623 * filesystem does not allow attribute caching, assume it is capable of 624 * validating that nlink does not overflow. 625 */ 626 if (vap != NULL && vap->va_nlink >= FUSE_LINK_MAX) 627 return EMLINK; 628 fli.oldnodeid = VTOI(vp); 629 630 fdisp_init(&fdi, 0); 631 fuse_internal_newentry_makerequest(vnode_mount(tdvp), VTOI(tdvp), cnp, 632 FUSE_LINK, &fli, sizeof(fli), &fdi); 633 if ((err = fdisp_wait_answ(&fdi))) { 634 goto out; 635 } 636 feo = fdi.answ; 637 638 err = fuse_internal_checkentry(feo, vnode_vtype(vp)); 639 out: 640 fdisp_destroy(&fdi); 641 return err; 642 } 643 644 /* 645 struct vnop_lookup_args { 646 struct vnodeop_desc *a_desc; 647 struct vnode *a_dvp; 648 struct vnode **a_vpp; 649 struct componentname *a_cnp; 650 }; 651 */ 652 int 653 fuse_vnop_lookup(struct vop_lookup_args *ap) 654 { 655 struct vnode *dvp = ap->a_dvp; 656 struct vnode **vpp = ap->a_vpp; 657 struct componentname *cnp = ap->a_cnp; 658 struct thread *td = cnp->cn_thread; 659 struct ucred *cred = cnp->cn_cred; 660 661 int nameiop = cnp->cn_nameiop; 662 int flags = cnp->cn_flags; 663 int wantparent = flags & (LOCKPARENT | WANTPARENT); 664 int islastcn = flags & ISLASTCN; 665 struct mount *mp = vnode_mount(dvp); 666 667 int err = 0; 668 int lookup_err = 0; 669 struct vnode *vp = NULL; 670 671 struct fuse_dispatcher fdi; 672 enum fuse_opcode op; 673 674 uint64_t nid; 675 struct fuse_access_param facp; 676 677 if (fuse_isdeadfs(dvp)) { 678 *vpp = NULL; 679 return ENXIO; 680 } 681 if (!vnode_isdir(dvp)) { 682 return ENOTDIR; 683 } 684 if (islastcn && vfs_isrdonly(mp) && (nameiop != LOOKUP)) { 685 return EROFS; 686 } 687 /* 688 * We do access check prior to doing anything else only in the case 689 * when we are at fs root (we'd like to say, "we are at the first 690 * component", but that's not exactly the same... nevermind). 691 * See further comments at further access checks. 692 */ 693 694 bzero(&facp, sizeof(facp)); 695 if (vnode_isvroot(dvp)) { /* early permission check hack */ 696 if ((err = fuse_internal_access(dvp, VEXEC, &facp, td, cred))) { 697 return err; 698 } 699 } 700 if (flags & ISDOTDOT) { 701 nid = VTOFUD(dvp)->parent_nid; 702 if (nid == 0) { 703 return ENOENT; 704 } 705 fdisp_init(&fdi, 0); 706 op = FUSE_GETATTR; 707 goto calldaemon; 708 } else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') { 709 nid = VTOI(dvp); 710 fdisp_init(&fdi, 0); 711 op = FUSE_GETATTR; 712 goto calldaemon; 713 } else if (fuse_lookup_cache_enable) { 714 err = cache_lookup(dvp, vpp, cnp, NULL, NULL); 715 switch (err) { 716 717 case -1: /* positive match */ 718 atomic_add_acq_long(&fuse_lookup_cache_hits, 1); 719 return 0; 720 721 case 0: /* no match in cache */ 722 atomic_add_acq_long(&fuse_lookup_cache_misses, 1); 723 break; 724 725 case ENOENT: /* negative match */ 726 /* fall through */ 727 default: 728 return err; 729 } 730 } 731 nid = VTOI(dvp); 732 fdisp_init(&fdi, cnp->cn_namelen + 1); 733 op = FUSE_LOOKUP; 734 735 calldaemon: 736 fdisp_make(&fdi, op, mp, nid, td, cred); 737 738 if (op == FUSE_LOOKUP) { 739 memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen); 740 ((char *)fdi.indata)[cnp->cn_namelen] = '\0'; 741 } 742 lookup_err = fdisp_wait_answ(&fdi); 743 744 if ((op == FUSE_LOOKUP) && !lookup_err) { /* lookup call succeeded */ 745 nid = ((struct fuse_entry_out *)fdi.answ)->nodeid; 746 if (!nid) { 747 /* 748 * zero nodeid is the same as "not found", 749 * but it's also cacheable (which we keep 750 * keep on doing not as of writing this) 751 */ 752 lookup_err = ENOENT; 753 } else if (nid == FUSE_ROOT_ID) { 754 lookup_err = EINVAL; 755 } 756 } 757 if (lookup_err && 758 (!fdi.answ_stat || lookup_err != ENOENT || op != FUSE_LOOKUP)) { 759 fdisp_destroy(&fdi); 760 return lookup_err; 761 } 762 /* lookup_err, if non-zero, must be ENOENT at this point */ 763 764 if (lookup_err) { 765 766 if ((nameiop == CREATE || nameiop == RENAME) && islastcn 767 /* && directory dvp has not been removed */ ) { 768 769 if (vfs_isrdonly(mp)) { 770 err = EROFS; 771 goto out; 772 } 773 #if 0 /* THINK_ABOUT_THIS */ 774 if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp))) { 775 goto out; 776 } 777 #endif 778 779 /* 780 * Possibly record the position of a slot in the 781 * directory large enough for the new component name. 782 * This can be recorded in the vnode private data for 783 * dvp. Set the SAVENAME flag to hold onto the 784 * pathname for use later in VOP_CREATE or VOP_RENAME. 785 */ 786 cnp->cn_flags |= SAVENAME; 787 788 err = EJUSTRETURN; 789 goto out; 790 } 791 /* Consider inserting name into cache. */ 792 793 /* 794 * No we can't use negative caching, as the fs 795 * changes are out of our control. 796 * False positives' falseness turns out just as things 797 * go by, but false negatives' falseness doesn't. 798 * (and aiding the caching mechanism with extra control 799 * mechanisms comes quite close to beating the whole purpose 800 * caching...) 801 */ 802 #if 0 803 if ((cnp->cn_flags & MAKEENTRY) != 0) { 804 SDT_PROBE2(fuse, , vnops, trace, 1, 805 "inserting NULL into cache"); 806 cache_enter(dvp, NULL, cnp); 807 } 808 #endif 809 err = ENOENT; 810 goto out; 811 812 } else { 813 814 /* !lookup_err */ 815 816 struct fuse_entry_out *feo = NULL; 817 struct fuse_attr *fattr = NULL; 818 819 if (op == FUSE_GETATTR) { 820 fattr = &((struct fuse_attr_out *)fdi.answ)->attr; 821 } else { 822 feo = (struct fuse_entry_out *)fdi.answ; 823 fattr = &(feo->attr); 824 } 825 826 /* 827 * If deleting, and at end of pathname, return parameters 828 * which can be used to remove file. If the wantparent flag 829 * isn't set, we return only the directory, otherwise we go on 830 * and lock the inode, being careful with ".". 831 */ 832 if (nameiop == DELETE && islastcn) { 833 /* 834 * Check for write access on directory. 835 */ 836 facp.xuid = fattr->uid; 837 facp.facc_flags |= FACCESS_STICKY; 838 err = fuse_internal_access(dvp, VWRITE, &facp, td, cred); 839 facp.facc_flags &= ~FACCESS_XQUERIES; 840 841 if (err) { 842 goto out; 843 } 844 if (nid == VTOI(dvp)) { 845 vref(dvp); 846 *vpp = dvp; 847 } else { 848 err = fuse_vnode_get(dvp->v_mount, feo, nid, 849 dvp, &vp, cnp, IFTOVT(fattr->mode)); 850 if (err) 851 goto out; 852 *vpp = vp; 853 } 854 855 /* 856 * Save the name for use in VOP_RMDIR and VOP_REMOVE 857 * later. 858 */ 859 cnp->cn_flags |= SAVENAME; 860 goto out; 861 862 } 863 /* 864 * If rewriting (RENAME), return the inode and the 865 * information required to rewrite the present directory 866 * Must get inode of directory entry to verify it's a 867 * regular file, or empty directory. 868 */ 869 if (nameiop == RENAME && wantparent && islastcn) { 870 871 #if 0 /* THINK_ABOUT_THIS */ 872 if ((err = fuse_internal_access(dvp, VWRITE, cred, td, &facp))) { 873 goto out; 874 } 875 #endif 876 877 /* 878 * Check for "." 879 */ 880 if (nid == VTOI(dvp)) { 881 err = EISDIR; 882 goto out; 883 } 884 err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp, 885 &vp, cnp, IFTOVT(fattr->mode)); 886 if (err) { 887 goto out; 888 } 889 *vpp = vp; 890 /* 891 * Save the name for use in VOP_RENAME later. 892 */ 893 cnp->cn_flags |= SAVENAME; 894 895 goto out; 896 } 897 if (flags & ISDOTDOT) { 898 struct mount *mp; 899 int ltype; 900 901 /* 902 * Expanded copy of vn_vget_ino() so that 903 * fuse_vnode_get() can be used. 904 */ 905 mp = dvp->v_mount; 906 ltype = VOP_ISLOCKED(dvp); 907 err = vfs_busy(mp, MBF_NOWAIT); 908 if (err != 0) { 909 vfs_ref(mp); 910 VOP_UNLOCK(dvp, 0); 911 err = vfs_busy(mp, 0); 912 vn_lock(dvp, ltype | LK_RETRY); 913 vfs_rel(mp); 914 if (err) 915 goto out; 916 if ((dvp->v_iflag & VI_DOOMED) != 0) { 917 err = ENOENT; 918 vfs_unbusy(mp); 919 goto out; 920 } 921 } 922 VOP_UNLOCK(dvp, 0); 923 err = fuse_vnode_get(vnode_mount(dvp), feo, nid, NULL, 924 &vp, cnp, IFTOVT(fattr->mode)); 925 vfs_unbusy(mp); 926 vn_lock(dvp, ltype | LK_RETRY); 927 if ((dvp->v_iflag & VI_DOOMED) != 0) { 928 if (err == 0) 929 vput(vp); 930 err = ENOENT; 931 } 932 if (err) 933 goto out; 934 *vpp = vp; 935 } else if (nid == VTOI(dvp)) { 936 vref(dvp); 937 *vpp = dvp; 938 } else { 939 struct fuse_vnode_data *fvdat; 940 941 err = fuse_vnode_get(vnode_mount(dvp), feo, nid, dvp, 942 &vp, cnp, IFTOVT(fattr->mode)); 943 if (err) { 944 goto out; 945 } 946 fuse_vnode_setparent(vp, dvp); 947 948 /* 949 * In the case where we are looking up a FUSE node 950 * represented by an existing cached vnode, and the 951 * true size reported by FUSE_LOOKUP doesn't match 952 * the vnode's cached size, fix the vnode cache to 953 * match the real object size. 954 * 955 * This can occur via FUSE distributed filesystems, 956 * irregular files, etc. 957 */ 958 fvdat = VTOFUD(vp); 959 if (vnode_isreg(vp) && 960 fattr->size != fvdat->filesize) { 961 /* 962 * The FN_SIZECHANGE flag reflects a dirty 963 * append. If userspace lets us know our cache 964 * is invalid, that write was lost. (Dirty 965 * writes that do not cause append are also 966 * lost, but we don't detect them here.) 967 * 968 * XXX: Maybe disable WB caching on this mount. 969 */ 970 if (fvdat->flag & FN_SIZECHANGE) 971 printf("%s: WB cache incoherent on " 972 "%s!\n", __func__, 973 vnode_mount(vp)->mnt_stat.f_mntonname); 974 975 (void)fuse_vnode_setsize(vp, fattr->size); 976 fvdat->flag &= ~FN_SIZECHANGE; 977 } 978 *vpp = vp; 979 } 980 981 if (op == FUSE_GETATTR) { 982 struct fuse_attr_out *fao = 983 (struct fuse_attr_out*)fdi.answ; 984 fuse_internal_cache_attrs(*vpp, 985 &fao->attr, fao->attr_valid, 986 fao->attr_valid_nsec, NULL); 987 } else { 988 struct fuse_entry_out *feo = 989 (struct fuse_entry_out*)fdi.answ; 990 fuse_internal_cache_attrs(*vpp, 991 &feo->attr, feo->attr_valid, 992 feo->attr_valid_nsec, NULL); 993 } 994 995 /* Insert name into cache if appropriate. */ 996 997 /* 998 * Nooo, caching is evil. With caching, we can't avoid stale 999 * information taking over the playground (cached info is not 1000 * just positive/negative, it does have qualitative aspects, 1001 * too). And a (VOP/FUSE)_GETATTR is always thrown anyway, when 1002 * walking down along cached path components, and that's not 1003 * any cheaper than FUSE_LOOKUP. This might change with 1004 * implementing kernel side attr caching, but... In Linux, 1005 * lookup results are not cached, and the daemon is bombarded 1006 * with FUSE_LOOKUPS on and on. This shows that by design, the 1007 * daemon is expected to handle frequent lookup queries 1008 * efficiently, do its caching in userspace, and so on. 1009 * 1010 * So just leave the name cache alone. 1011 */ 1012 1013 /* 1014 * Well, now I know, Linux caches lookups, but with a 1015 * timeout... So it's the same thing as attribute caching: 1016 * we can deal with it when implement timeouts. 1017 */ 1018 #if 0 1019 if (cnp->cn_flags & MAKEENTRY) { 1020 cache_enter(dvp, *vpp, cnp); 1021 } 1022 #endif 1023 } 1024 out: 1025 if (!lookup_err) { 1026 1027 /* No lookup error; need to clean up. */ 1028 1029 if (err) { /* Found inode; exit with no vnode. */ 1030 if (op == FUSE_LOOKUP) { 1031 fuse_internal_forget_send(vnode_mount(dvp), td, cred, 1032 nid, 1); 1033 } 1034 fdisp_destroy(&fdi); 1035 return err; 1036 } else { 1037 #ifndef NO_EARLY_PERM_CHECK_HACK 1038 if (!islastcn) { 1039 /* 1040 * We have the attributes of the next item 1041 * *now*, and it's a fact, and we do not 1042 * have to do extra work for it (ie, beg the 1043 * daemon), and it neither depends on such 1044 * accidental things like attr caching. So 1045 * the big idea: check credentials *now*, 1046 * not at the beginning of the next call to 1047 * lookup. 1048 * 1049 * The first item of the lookup chain (fs root) 1050 * won't be checked then here, of course, as 1051 * its never "the next". But go and see that 1052 * the root is taken care about at the very 1053 * beginning of this function. 1054 * 1055 * Now, given we want to do the access check 1056 * this way, one might ask: so then why not 1057 * do the access check just after fetching 1058 * the inode and its attributes from the 1059 * daemon? Why bother with producing the 1060 * corresponding vnode at all if something 1061 * is not OK? We know what's the deal as 1062 * soon as we get those attrs... There is 1063 * one bit of info though not given us by 1064 * the daemon: whether his response is 1065 * authoritative or not... His response should 1066 * be ignored if something is mounted over 1067 * the dir in question. But that can be 1068 * known only by having the vnode... 1069 */ 1070 int tmpvtype = vnode_vtype(*vpp); 1071 1072 bzero(&facp, sizeof(facp)); 1073 /*the early perm check hack */ 1074 facp.facc_flags |= FACCESS_VA_VALID; 1075 1076 if ((tmpvtype != VDIR) && (tmpvtype != VLNK)) { 1077 err = ENOTDIR; 1078 } 1079 if (!err && !vnode_mountedhere(*vpp)) { 1080 err = fuse_internal_access(*vpp, VEXEC, &facp, td, cred); 1081 } 1082 if (err) { 1083 if (tmpvtype == VLNK) 1084 SDT_PROBE2(fuse, , vnops, trace, 1085 1, "weird, permission " 1086 "error with a symlink?"); 1087 vput(*vpp); 1088 *vpp = NULL; 1089 } 1090 } 1091 #endif 1092 } 1093 } 1094 fdisp_destroy(&fdi); 1095 1096 return err; 1097 } 1098 1099 /* 1100 struct vnop_mkdir_args { 1101 struct vnode *a_dvp; 1102 struct vnode **a_vpp; 1103 struct componentname *a_cnp; 1104 struct vattr *a_vap; 1105 }; 1106 */ 1107 static int 1108 fuse_vnop_mkdir(struct vop_mkdir_args *ap) 1109 { 1110 struct vnode *dvp = ap->a_dvp; 1111 struct vnode **vpp = ap->a_vpp; 1112 struct componentname *cnp = ap->a_cnp; 1113 struct vattr *vap = ap->a_vap; 1114 1115 struct fuse_mkdir_in fmdi; 1116 1117 if (fuse_isdeadfs(dvp)) { 1118 return ENXIO; 1119 } 1120 fmdi.mode = MAKEIMODE(vap->va_type, vap->va_mode); 1121 1122 return (fuse_internal_newentry(dvp, vpp, cnp, FUSE_MKDIR, &fmdi, 1123 sizeof(fmdi), VDIR)); 1124 } 1125 1126 /* 1127 struct vnop_mknod_args { 1128 struct vnode *a_dvp; 1129 struct vnode **a_vpp; 1130 struct componentname *a_cnp; 1131 struct vattr *a_vap; 1132 }; 1133 */ 1134 static int 1135 fuse_vnop_mknod(struct vop_mknod_args *ap) 1136 { 1137 1138 return (EINVAL); 1139 } 1140 1141 1142 /* 1143 struct vnop_open_args { 1144 struct vnode *a_vp; 1145 int a_mode; 1146 struct ucred *a_cred; 1147 struct thread *a_td; 1148 int a_fdidx; / struct file *a_fp; 1149 }; 1150 */ 1151 static int 1152 fuse_vnop_open(struct vop_open_args *ap) 1153 { 1154 struct vnode *vp = ap->a_vp; 1155 int mode = ap->a_mode; 1156 struct thread *td = ap->a_td; 1157 struct ucred *cred = ap->a_cred; 1158 1159 fufh_type_t fufh_type; 1160 struct fuse_vnode_data *fvdat; 1161 1162 int error, isdir = 0; 1163 int32_t fuse_open_flags; 1164 1165 if (fuse_isdeadfs(vp)) { 1166 return ENXIO; 1167 } 1168 if ((mode & (FREAD | FWRITE)) == 0) 1169 return EINVAL; 1170 1171 fvdat = VTOFUD(vp); 1172 1173 if (vnode_isdir(vp)) { 1174 isdir = 1; 1175 } 1176 fuse_open_flags = 0; 1177 if (isdir) { 1178 fufh_type = FUFH_RDONLY; 1179 } else { 1180 fufh_type = fuse_filehandle_xlate_from_fflags(mode); 1181 /* 1182 * For WRONLY opens, force DIRECT_IO. This is necessary 1183 * since writing a partial block through the buffer cache 1184 * will result in a read of the block and that read won't 1185 * be allowed by the WRONLY open. 1186 */ 1187 if (fufh_type == FUFH_WRONLY || 1188 (fvdat->flag & FN_DIRECTIO) != 0) 1189 fuse_open_flags = FOPEN_DIRECT_IO; 1190 } 1191 1192 if (fuse_filehandle_validrw(vp, fufh_type) != FUFH_INVALID) { 1193 fuse_vnode_open(vp, fuse_open_flags, td); 1194 return 0; 1195 } 1196 error = fuse_filehandle_open(vp, fufh_type, NULL, td, cred); 1197 1198 return error; 1199 } 1200 1201 static int 1202 fuse_vnop_pathconf(struct vop_pathconf_args *ap) 1203 { 1204 1205 switch (ap->a_name) { 1206 case _PC_FILESIZEBITS: 1207 *ap->a_retval = 64; 1208 return (0); 1209 case _PC_NAME_MAX: 1210 *ap->a_retval = NAME_MAX; 1211 return (0); 1212 case _PC_LINK_MAX: 1213 *ap->a_retval = MIN(LONG_MAX, FUSE_LINK_MAX); 1214 return (0); 1215 case _PC_SYMLINK_MAX: 1216 *ap->a_retval = MAXPATHLEN; 1217 return (0); 1218 case _PC_NO_TRUNC: 1219 *ap->a_retval = 1; 1220 return (0); 1221 default: 1222 return (vop_stdpathconf(ap)); 1223 } 1224 } 1225 1226 /* 1227 struct vnop_read_args { 1228 struct vnode *a_vp; 1229 struct uio *a_uio; 1230 int a_ioflag; 1231 struct ucred *a_cred; 1232 }; 1233 */ 1234 static int 1235 fuse_vnop_read(struct vop_read_args *ap) 1236 { 1237 struct vnode *vp = ap->a_vp; 1238 struct uio *uio = ap->a_uio; 1239 int ioflag = ap->a_ioflag; 1240 struct ucred *cred = ap->a_cred; 1241 1242 if (fuse_isdeadfs(vp)) { 1243 return ENXIO; 1244 } 1245 1246 if (VTOFUD(vp)->flag & FN_DIRECTIO) { 1247 ioflag |= IO_DIRECT; 1248 } 1249 1250 return fuse_io_dispatch(vp, uio, ioflag, cred); 1251 } 1252 1253 /* 1254 struct vnop_readdir_args { 1255 struct vnode *a_vp; 1256 struct uio *a_uio; 1257 struct ucred *a_cred; 1258 int *a_eofflag; 1259 int *ncookies; 1260 u_long **a_cookies; 1261 }; 1262 */ 1263 static int 1264 fuse_vnop_readdir(struct vop_readdir_args *ap) 1265 { 1266 struct vnode *vp = ap->a_vp; 1267 struct uio *uio = ap->a_uio; 1268 struct ucred *cred = ap->a_cred; 1269 1270 struct fuse_filehandle *fufh = NULL; 1271 struct fuse_iov cookediov; 1272 1273 int err = 0; 1274 int freefufh = 0; 1275 1276 if (fuse_isdeadfs(vp)) { 1277 return ENXIO; 1278 } 1279 if ( /* XXXIP ((uio_iovcnt(uio) > 1)) || */ 1280 (uio_resid(uio) < sizeof(struct dirent))) { 1281 return EINVAL; 1282 } 1283 1284 if (!fuse_filehandle_valid(vp, FUFH_RDONLY)) { 1285 SDT_PROBE2(fuse, , vnops, trace, 1, 1286 "calling readdir() before open()"); 1287 err = fuse_filehandle_open(vp, FUFH_RDONLY, &fufh, NULL, cred); 1288 freefufh = 1; 1289 } else { 1290 err = fuse_filehandle_get(vp, FUFH_RDONLY, &fufh); 1291 } 1292 if (err) { 1293 return (err); 1294 } 1295 #define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1) 1296 fiov_init(&cookediov, DIRCOOKEDSIZE); 1297 1298 err = fuse_internal_readdir(vp, uio, fufh, &cookediov); 1299 1300 fiov_teardown(&cookediov); 1301 if (freefufh) { 1302 fuse_filehandle_close(vp, FUFH_RDONLY, NULL, cred); 1303 } 1304 return err; 1305 } 1306 1307 /* 1308 struct vnop_readlink_args { 1309 struct vnode *a_vp; 1310 struct uio *a_uio; 1311 struct ucred *a_cred; 1312 }; 1313 */ 1314 static int 1315 fuse_vnop_readlink(struct vop_readlink_args *ap) 1316 { 1317 struct vnode *vp = ap->a_vp; 1318 struct uio *uio = ap->a_uio; 1319 struct ucred *cred = ap->a_cred; 1320 1321 struct fuse_dispatcher fdi; 1322 int err; 1323 1324 if (fuse_isdeadfs(vp)) { 1325 return ENXIO; 1326 } 1327 if (!vnode_islnk(vp)) { 1328 return EINVAL; 1329 } 1330 fdisp_init(&fdi, 0); 1331 err = fdisp_simple_putget_vp(&fdi, FUSE_READLINK, vp, curthread, cred); 1332 if (err) { 1333 goto out; 1334 } 1335 if (((char *)fdi.answ)[0] == '/' && 1336 fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_PUSH_SYMLINKS_IN) { 1337 char *mpth = vnode_mount(vp)->mnt_stat.f_mntonname; 1338 1339 err = uiomove(mpth, strlen(mpth), uio); 1340 } 1341 if (!err) { 1342 err = uiomove(fdi.answ, fdi.iosize, uio); 1343 } 1344 out: 1345 fdisp_destroy(&fdi); 1346 return err; 1347 } 1348 1349 /* 1350 struct vnop_reclaim_args { 1351 struct vnode *a_vp; 1352 struct thread *a_td; 1353 }; 1354 */ 1355 static int 1356 fuse_vnop_reclaim(struct vop_reclaim_args *ap) 1357 { 1358 struct vnode *vp = ap->a_vp; 1359 struct thread *td = ap->a_td; 1360 1361 struct fuse_vnode_data *fvdat = VTOFUD(vp); 1362 struct fuse_filehandle *fufh = NULL; 1363 1364 int type; 1365 1366 if (!fvdat) { 1367 panic("FUSE: no vnode data during recycling"); 1368 } 1369 for (type = 0; type < FUFH_MAXTYPE; type++) { 1370 fufh = &(fvdat->fufh[type]); 1371 if (FUFH_IS_VALID(fufh)) { 1372 printf("FUSE: vnode being reclaimed but fufh (type=%d) is valid", 1373 type); 1374 fuse_filehandle_close(vp, type, td, NULL); 1375 } 1376 } 1377 1378 if ((!fuse_isdeadfs(vp)) && (fvdat->nlookup)) { 1379 fuse_internal_forget_send(vnode_mount(vp), td, NULL, VTOI(vp), 1380 fvdat->nlookup); 1381 } 1382 fuse_vnode_setparent(vp, NULL); 1383 cache_purge(vp); 1384 vfs_hash_remove(vp); 1385 vnode_destroy_vobject(vp); 1386 fuse_vnode_destroy(vp); 1387 1388 return 0; 1389 } 1390 1391 /* 1392 struct vnop_remove_args { 1393 struct vnode *a_dvp; 1394 struct vnode *a_vp; 1395 struct componentname *a_cnp; 1396 }; 1397 */ 1398 static int 1399 fuse_vnop_remove(struct vop_remove_args *ap) 1400 { 1401 struct vnode *dvp = ap->a_dvp; 1402 struct vnode *vp = ap->a_vp; 1403 struct componentname *cnp = ap->a_cnp; 1404 1405 int err; 1406 1407 if (fuse_isdeadfs(vp)) { 1408 return ENXIO; 1409 } 1410 if (vnode_isdir(vp)) { 1411 return EPERM; 1412 } 1413 cache_purge(vp); 1414 1415 err = fuse_internal_remove(dvp, vp, cnp, FUSE_UNLINK); 1416 1417 if (err == 0) 1418 fuse_internal_vnode_disappear(vp); 1419 return err; 1420 } 1421 1422 /* 1423 struct vnop_rename_args { 1424 struct vnode *a_fdvp; 1425 struct vnode *a_fvp; 1426 struct componentname *a_fcnp; 1427 struct vnode *a_tdvp; 1428 struct vnode *a_tvp; 1429 struct componentname *a_tcnp; 1430 }; 1431 */ 1432 static int 1433 fuse_vnop_rename(struct vop_rename_args *ap) 1434 { 1435 struct vnode *fdvp = ap->a_fdvp; 1436 struct vnode *fvp = ap->a_fvp; 1437 struct componentname *fcnp = ap->a_fcnp; 1438 struct vnode *tdvp = ap->a_tdvp; 1439 struct vnode *tvp = ap->a_tvp; 1440 struct componentname *tcnp = ap->a_tcnp; 1441 struct fuse_data *data; 1442 1443 int err = 0; 1444 1445 if (fuse_isdeadfs(fdvp)) { 1446 return ENXIO; 1447 } 1448 if (fvp->v_mount != tdvp->v_mount || 1449 (tvp && fvp->v_mount != tvp->v_mount)) { 1450 SDT_PROBE2(fuse, , vnops, trace, 1, "cross-device rename"); 1451 err = EXDEV; 1452 goto out; 1453 } 1454 cache_purge(fvp); 1455 1456 /* 1457 * FUSE library is expected to check if target directory is not 1458 * under the source directory in the file system tree. 1459 * Linux performs this check at VFS level. 1460 */ 1461 data = fuse_get_mpdata(vnode_mount(tdvp)); 1462 sx_xlock(&data->rename_lock); 1463 err = fuse_internal_rename(fdvp, fcnp, tdvp, tcnp); 1464 if (err == 0) { 1465 if (tdvp != fdvp) 1466 fuse_vnode_setparent(fvp, tdvp); 1467 if (tvp != NULL) 1468 fuse_vnode_setparent(tvp, NULL); 1469 } 1470 sx_unlock(&data->rename_lock); 1471 1472 if (tvp != NULL && tvp != fvp) { 1473 cache_purge(tvp); 1474 } 1475 if (vnode_isdir(fvp)) { 1476 if ((tvp != NULL) && vnode_isdir(tvp)) { 1477 cache_purge(tdvp); 1478 } 1479 cache_purge(fdvp); 1480 } 1481 out: 1482 if (tdvp == tvp) { 1483 vrele(tdvp); 1484 } else { 1485 vput(tdvp); 1486 } 1487 if (tvp != NULL) { 1488 vput(tvp); 1489 } 1490 vrele(fdvp); 1491 vrele(fvp); 1492 1493 return err; 1494 } 1495 1496 /* 1497 struct vnop_rmdir_args { 1498 struct vnode *a_dvp; 1499 struct vnode *a_vp; 1500 struct componentname *a_cnp; 1501 } *ap; 1502 */ 1503 static int 1504 fuse_vnop_rmdir(struct vop_rmdir_args *ap) 1505 { 1506 struct vnode *dvp = ap->a_dvp; 1507 struct vnode *vp = ap->a_vp; 1508 1509 int err; 1510 1511 if (fuse_isdeadfs(vp)) { 1512 return ENXIO; 1513 } 1514 if (VTOFUD(vp) == VTOFUD(dvp)) { 1515 return EINVAL; 1516 } 1517 err = fuse_internal_remove(dvp, vp, ap->a_cnp, FUSE_RMDIR); 1518 1519 if (err == 0) 1520 fuse_internal_vnode_disappear(vp); 1521 return err; 1522 } 1523 1524 /* 1525 struct vnop_setattr_args { 1526 struct vnode *a_vp; 1527 struct vattr *a_vap; 1528 struct ucred *a_cred; 1529 struct thread *a_td; 1530 }; 1531 */ 1532 static int 1533 fuse_vnop_setattr(struct vop_setattr_args *ap) 1534 { 1535 struct vnode *vp = ap->a_vp; 1536 struct vattr *vap = ap->a_vap; 1537 struct ucred *cred = ap->a_cred; 1538 struct thread *td = curthread; 1539 1540 struct fuse_dispatcher fdi; 1541 struct fuse_setattr_in *fsai; 1542 struct fuse_access_param facp; 1543 1544 int err = 0; 1545 enum vtype vtyp; 1546 int sizechanged = 0; 1547 uint64_t newsize = 0; 1548 1549 if (fuse_isdeadfs(vp)) { 1550 return ENXIO; 1551 } 1552 fdisp_init(&fdi, sizeof(*fsai)); 1553 fdisp_make_vp(&fdi, FUSE_SETATTR, vp, td, cred); 1554 fsai = fdi.indata; 1555 fsai->valid = 0; 1556 1557 bzero(&facp, sizeof(facp)); 1558 1559 facp.xuid = vap->va_uid; 1560 facp.xgid = vap->va_gid; 1561 1562 if (vap->va_uid != (uid_t)VNOVAL) { 1563 facp.facc_flags |= FACCESS_CHOWN; 1564 fsai->uid = vap->va_uid; 1565 fsai->valid |= FATTR_UID; 1566 } 1567 if (vap->va_gid != (gid_t)VNOVAL) { 1568 facp.facc_flags |= FACCESS_CHOWN; 1569 fsai->gid = vap->va_gid; 1570 fsai->valid |= FATTR_GID; 1571 } 1572 if (vap->va_size != VNOVAL) { 1573 1574 struct fuse_filehandle *fufh = NULL; 1575 1576 /*Truncate to a new value. */ 1577 fsai->size = vap->va_size; 1578 sizechanged = 1; 1579 newsize = vap->va_size; 1580 fsai->valid |= FATTR_SIZE; 1581 1582 fuse_filehandle_getrw(vp, FUFH_WRONLY, &fufh); 1583 if (fufh) { 1584 fsai->fh = fufh->fh_id; 1585 fsai->valid |= FATTR_FH; 1586 } 1587 } 1588 if (vap->va_atime.tv_sec != VNOVAL) { 1589 fsai->atime = vap->va_atime.tv_sec; 1590 fsai->atimensec = vap->va_atime.tv_nsec; 1591 fsai->valid |= FATTR_ATIME; 1592 } 1593 if (vap->va_mtime.tv_sec != VNOVAL) { 1594 fsai->mtime = vap->va_mtime.tv_sec; 1595 fsai->mtimensec = vap->va_mtime.tv_nsec; 1596 fsai->valid |= FATTR_MTIME; 1597 } 1598 if (vap->va_mode != (mode_t)VNOVAL) { 1599 fsai->mode = vap->va_mode & ALLPERMS; 1600 fsai->valid |= FATTR_MODE; 1601 } 1602 if (!fsai->valid) { 1603 goto out; 1604 } 1605 vtyp = vnode_vtype(vp); 1606 1607 if (fsai->valid & FATTR_SIZE && vtyp == VDIR) { 1608 err = EISDIR; 1609 goto out; 1610 } 1611 if (vfs_isrdonly(vnode_mount(vp)) && (fsai->valid & ~FATTR_SIZE || vtyp == VREG)) { 1612 err = EROFS; 1613 goto out; 1614 } 1615 if (fsai->valid & ~FATTR_SIZE) { 1616 /*err = fuse_internal_access(vp, VADMIN, context, &facp); */ 1617 /*XXX */ 1618 err = 0; 1619 } 1620 facp.facc_flags &= ~FACCESS_XQUERIES; 1621 1622 if (err && !(fsai->valid & ~(FATTR_ATIME | FATTR_MTIME)) && 1623 vap->va_vaflags & VA_UTIMES_NULL) { 1624 err = fuse_internal_access(vp, VWRITE, &facp, td, cred); 1625 } 1626 if (err) 1627 goto out; 1628 if ((err = fdisp_wait_answ(&fdi))) 1629 goto out; 1630 vtyp = IFTOVT(((struct fuse_attr_out *)fdi.answ)->attr.mode); 1631 1632 if (vnode_vtype(vp) != vtyp) { 1633 if (vnode_vtype(vp) == VNON && vtyp != VNON) { 1634 SDT_PROBE2(fuse, , vnops, trace, 1, "FUSE: Dang! " 1635 "vnode_vtype is VNON and vtype isn't."); 1636 } else { 1637 /* 1638 * STALE vnode, ditch 1639 * 1640 * The vnode has changed its type "behind our back". 1641 * There's nothing really we can do, so let us just 1642 * force an internal revocation and tell the caller to 1643 * try again, if interested. 1644 */ 1645 fuse_internal_vnode_disappear(vp); 1646 err = EAGAIN; 1647 } 1648 } 1649 if (err == 0) { 1650 struct fuse_attr_out *fao = (struct fuse_attr_out*)fdi.answ; 1651 fuse_internal_cache_attrs(vp, &fao->attr, fao->attr_valid, 1652 fao->attr_valid_nsec, NULL); 1653 } 1654 1655 out: 1656 fdisp_destroy(&fdi); 1657 if (!err && sizechanged) { 1658 fuse_vnode_setsize(vp, newsize); 1659 VTOFUD(vp)->flag &= ~FN_SIZECHANGE; 1660 } 1661 return err; 1662 } 1663 1664 /* 1665 struct vnop_strategy_args { 1666 struct vnode *a_vp; 1667 struct buf *a_bp; 1668 }; 1669 */ 1670 static int 1671 fuse_vnop_strategy(struct vop_strategy_args *ap) 1672 { 1673 struct vnode *vp = ap->a_vp; 1674 struct buf *bp = ap->a_bp; 1675 1676 if (!vp || fuse_isdeadfs(vp)) { 1677 bp->b_ioflags |= BIO_ERROR; 1678 bp->b_error = ENXIO; 1679 bufdone(bp); 1680 return ENXIO; 1681 } 1682 if (bp->b_iocmd == BIO_WRITE) 1683 fuse_vnode_refreshsize(vp, NOCRED); 1684 1685 (void)fuse_io_strategy(vp, bp); 1686 1687 /* 1688 * This is a dangerous function. If returns error, that might mean a 1689 * panic. We prefer pretty much anything over being forced to panic 1690 * by a malicious daemon (a demon?). So we just return 0 anyway. You 1691 * should never mind this: this function has its own error 1692 * propagation mechanism via the argument buffer, so 1693 * not-that-melodramatic residents of the call chain still will be 1694 * able to know what to do. 1695 */ 1696 return 0; 1697 } 1698 1699 1700 /* 1701 struct vnop_symlink_args { 1702 struct vnode *a_dvp; 1703 struct vnode **a_vpp; 1704 struct componentname *a_cnp; 1705 struct vattr *a_vap; 1706 char *a_target; 1707 }; 1708 */ 1709 static int 1710 fuse_vnop_symlink(struct vop_symlink_args *ap) 1711 { 1712 struct vnode *dvp = ap->a_dvp; 1713 struct vnode **vpp = ap->a_vpp; 1714 struct componentname *cnp = ap->a_cnp; 1715 const char *target = ap->a_target; 1716 1717 struct fuse_dispatcher fdi; 1718 1719 int err; 1720 size_t len; 1721 1722 if (fuse_isdeadfs(dvp)) { 1723 return ENXIO; 1724 } 1725 /* 1726 * Unlike the other creator type calls, here we have to create a message 1727 * where the name of the new entry comes first, and the data describing 1728 * the entry comes second. 1729 * Hence we can't rely on our handy fuse_internal_newentry() routine, 1730 * but put together the message manually and just call the core part. 1731 */ 1732 1733 len = strlen(target) + 1; 1734 fdisp_init(&fdi, len + cnp->cn_namelen + 1); 1735 fdisp_make_vp(&fdi, FUSE_SYMLINK, dvp, curthread, NULL); 1736 1737 memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen); 1738 ((char *)fdi.indata)[cnp->cn_namelen] = '\0'; 1739 memcpy((char *)fdi.indata + cnp->cn_namelen + 1, target, len); 1740 1741 err = fuse_internal_newentry_core(dvp, vpp, cnp, VLNK, &fdi); 1742 fdisp_destroy(&fdi); 1743 return err; 1744 } 1745 1746 /* 1747 struct vnop_write_args { 1748 struct vnode *a_vp; 1749 struct uio *a_uio; 1750 int a_ioflag; 1751 struct ucred *a_cred; 1752 }; 1753 */ 1754 static int 1755 fuse_vnop_write(struct vop_write_args *ap) 1756 { 1757 struct vnode *vp = ap->a_vp; 1758 struct uio *uio = ap->a_uio; 1759 int ioflag = ap->a_ioflag; 1760 struct ucred *cred = ap->a_cred; 1761 1762 if (fuse_isdeadfs(vp)) { 1763 return ENXIO; 1764 } 1765 fuse_vnode_refreshsize(vp, cred); 1766 1767 if (VTOFUD(vp)->flag & FN_DIRECTIO) { 1768 ioflag |= IO_DIRECT; 1769 } 1770 1771 return fuse_io_dispatch(vp, uio, ioflag, cred); 1772 } 1773 1774 SDT_PROBE_DEFINE1(fuse, , vnops, vnop_getpages_error, "int"); 1775 /* 1776 struct vnop_getpages_args { 1777 struct vnode *a_vp; 1778 vm_page_t *a_m; 1779 int a_count; 1780 int a_reqpage; 1781 }; 1782 */ 1783 static int 1784 fuse_vnop_getpages(struct vop_getpages_args *ap) 1785 { 1786 int i, error, nextoff, size, toff, count, npages; 1787 struct uio uio; 1788 struct iovec iov; 1789 vm_offset_t kva; 1790 struct buf *bp; 1791 struct vnode *vp; 1792 struct thread *td; 1793 struct ucred *cred; 1794 vm_page_t *pages; 1795 1796 vp = ap->a_vp; 1797 KASSERT(vp->v_object, ("objectless vp passed to getpages")); 1798 td = curthread; /* XXX */ 1799 cred = curthread->td_ucred; /* XXX */ 1800 pages = ap->a_m; 1801 npages = ap->a_count; 1802 1803 if (!fsess_opt_mmap(vnode_mount(vp))) { 1804 SDT_PROBE2(fuse, , vnops, trace, 1, 1805 "called on non-cacheable vnode??\n"); 1806 return (VM_PAGER_ERROR); 1807 } 1808 1809 /* 1810 * If the last page is partially valid, just return it and allow 1811 * the pager to zero-out the blanks. Partially valid pages can 1812 * only occur at the file EOF. 1813 * 1814 * XXXGL: is that true for FUSE, which is a local filesystem, 1815 * but still somewhat disconnected from the kernel? 1816 */ 1817 VM_OBJECT_WLOCK(vp->v_object); 1818 if (pages[npages - 1]->valid != 0 && --npages == 0) 1819 goto out; 1820 VM_OBJECT_WUNLOCK(vp->v_object); 1821 1822 /* 1823 * We use only the kva address for the buffer, but this is extremely 1824 * convenient and fast. 1825 */ 1826 bp = uma_zalloc(fuse_pbuf_zone, M_WAITOK); 1827 1828 kva = (vm_offset_t)bp->b_data; 1829 pmap_qenter(kva, pages, npages); 1830 VM_CNT_INC(v_vnodein); 1831 VM_CNT_ADD(v_vnodepgsin, npages); 1832 1833 count = npages << PAGE_SHIFT; 1834 iov.iov_base = (caddr_t)kva; 1835 iov.iov_len = count; 1836 uio.uio_iov = &iov; 1837 uio.uio_iovcnt = 1; 1838 uio.uio_offset = IDX_TO_OFF(pages[0]->pindex); 1839 uio.uio_resid = count; 1840 uio.uio_segflg = UIO_SYSSPACE; 1841 uio.uio_rw = UIO_READ; 1842 uio.uio_td = td; 1843 1844 error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred); 1845 pmap_qremove(kva, npages); 1846 1847 uma_zfree(fuse_pbuf_zone, bp); 1848 1849 if (error && (uio.uio_resid == count)) { 1850 SDT_PROBE1(fuse, , vnops, vnop_getpages_error, error); 1851 return VM_PAGER_ERROR; 1852 } 1853 /* 1854 * Calculate the number of bytes read and validate only that number 1855 * of bytes. Note that due to pending writes, size may be 0. This 1856 * does not mean that the remaining data is invalid! 1857 */ 1858 1859 size = count - uio.uio_resid; 1860 VM_OBJECT_WLOCK(vp->v_object); 1861 fuse_vm_page_lock_queues(); 1862 for (i = 0, toff = 0; i < npages; i++, toff = nextoff) { 1863 vm_page_t m; 1864 1865 nextoff = toff + PAGE_SIZE; 1866 m = pages[i]; 1867 1868 if (nextoff <= size) { 1869 /* 1870 * Read operation filled an entire page 1871 */ 1872 m->valid = VM_PAGE_BITS_ALL; 1873 KASSERT(m->dirty == 0, 1874 ("fuse_getpages: page %p is dirty", m)); 1875 } else if (size > toff) { 1876 /* 1877 * Read operation filled a partial page. 1878 */ 1879 m->valid = 0; 1880 vm_page_set_valid_range(m, 0, size - toff); 1881 KASSERT(m->dirty == 0, 1882 ("fuse_getpages: page %p is dirty", m)); 1883 } else { 1884 /* 1885 * Read operation was short. If no error occurred 1886 * we may have hit a zero-fill section. We simply 1887 * leave valid set to 0. 1888 */ 1889 ; 1890 } 1891 } 1892 fuse_vm_page_unlock_queues(); 1893 out: 1894 VM_OBJECT_WUNLOCK(vp->v_object); 1895 if (ap->a_rbehind) 1896 *ap->a_rbehind = 0; 1897 if (ap->a_rahead) 1898 *ap->a_rahead = 0; 1899 return (VM_PAGER_OK); 1900 } 1901 1902 /* 1903 struct vnop_putpages_args { 1904 struct vnode *a_vp; 1905 vm_page_t *a_m; 1906 int a_count; 1907 int a_sync; 1908 int *a_rtvals; 1909 vm_ooffset_t a_offset; 1910 }; 1911 */ 1912 static int 1913 fuse_vnop_putpages(struct vop_putpages_args *ap) 1914 { 1915 struct uio uio; 1916 struct iovec iov; 1917 vm_offset_t kva; 1918 struct buf *bp; 1919 int i, error, npages, count; 1920 off_t offset; 1921 int *rtvals; 1922 struct vnode *vp; 1923 struct thread *td; 1924 struct ucred *cred; 1925 vm_page_t *pages; 1926 vm_ooffset_t fsize; 1927 1928 vp = ap->a_vp; 1929 KASSERT(vp->v_object, ("objectless vp passed to putpages")); 1930 fsize = vp->v_object->un_pager.vnp.vnp_size; 1931 td = curthread; /* XXX */ 1932 cred = curthread->td_ucred; /* XXX */ 1933 pages = ap->a_m; 1934 count = ap->a_count; 1935 rtvals = ap->a_rtvals; 1936 npages = btoc(count); 1937 offset = IDX_TO_OFF(pages[0]->pindex); 1938 1939 if (!fsess_opt_mmap(vnode_mount(vp))) { 1940 SDT_PROBE2(fuse, , vnops, trace, 1, 1941 "called on non-cacheable vnode??\n"); 1942 } 1943 for (i = 0; i < npages; i++) 1944 rtvals[i] = VM_PAGER_AGAIN; 1945 1946 /* 1947 * When putting pages, do not extend file past EOF. 1948 */ 1949 1950 if (offset + count > fsize) { 1951 count = fsize - offset; 1952 if (count < 0) 1953 count = 0; 1954 } 1955 /* 1956 * We use only the kva address for the buffer, but this is extremely 1957 * convenient and fast. 1958 */ 1959 bp = uma_zalloc(fuse_pbuf_zone, M_WAITOK); 1960 1961 kva = (vm_offset_t)bp->b_data; 1962 pmap_qenter(kva, pages, npages); 1963 VM_CNT_INC(v_vnodeout); 1964 VM_CNT_ADD(v_vnodepgsout, count); 1965 1966 iov.iov_base = (caddr_t)kva; 1967 iov.iov_len = count; 1968 uio.uio_iov = &iov; 1969 uio.uio_iovcnt = 1; 1970 uio.uio_offset = offset; 1971 uio.uio_resid = count; 1972 uio.uio_segflg = UIO_SYSSPACE; 1973 uio.uio_rw = UIO_WRITE; 1974 uio.uio_td = td; 1975 1976 error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred); 1977 1978 pmap_qremove(kva, npages); 1979 uma_zfree(fuse_pbuf_zone, bp); 1980 1981 if (!error) { 1982 int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE; 1983 1984 for (i = 0; i < nwritten; i++) { 1985 rtvals[i] = VM_PAGER_OK; 1986 VM_OBJECT_WLOCK(pages[i]->object); 1987 vm_page_undirty(pages[i]); 1988 VM_OBJECT_WUNLOCK(pages[i]->object); 1989 } 1990 } 1991 return rtvals[0]; 1992 } 1993 1994 static const char extattr_namespace_separator = '.'; 1995 1996 /* 1997 struct vop_getextattr_args { 1998 struct vop_generic_args a_gen; 1999 struct vnode *a_vp; 2000 int a_attrnamespace; 2001 const char *a_name; 2002 struct uio *a_uio; 2003 size_t *a_size; 2004 struct ucred *a_cred; 2005 struct thread *a_td; 2006 }; 2007 */ 2008 static int 2009 fuse_vnop_getextattr(struct vop_getextattr_args *ap) 2010 { 2011 struct vnode *vp = ap->a_vp; 2012 struct uio *uio = ap->a_uio; 2013 struct fuse_dispatcher fdi; 2014 struct fuse_getxattr_in *get_xattr_in; 2015 struct fuse_getxattr_out *get_xattr_out; 2016 struct mount *mp = vnode_mount(vp); 2017 struct thread *td = ap->a_td; 2018 struct ucred *cred = ap->a_cred; 2019 char *prefix; 2020 char *attr_str; 2021 size_t len; 2022 int err; 2023 2024 if (fuse_isdeadfs(vp)) 2025 return (ENXIO); 2026 2027 /* Default to looking for user attributes. */ 2028 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2029 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2030 else 2031 prefix = EXTATTR_NAMESPACE_USER_STRING; 2032 2033 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2034 strlen(ap->a_name) + 1; 2035 2036 fdisp_init(&fdi, len + sizeof(*get_xattr_in)); 2037 fdisp_make_vp(&fdi, FUSE_GETXATTR, vp, td, cred); 2038 2039 get_xattr_in = fdi.indata; 2040 /* 2041 * Check to see whether we're querying the available size or 2042 * issuing the actual request. If we pass in 0, we get back struct 2043 * fuse_getxattr_out. If we pass in a non-zero size, we get back 2044 * that much data, without the struct fuse_getxattr_out header. 2045 */ 2046 if (uio == NULL) 2047 get_xattr_in->size = 0; 2048 else 2049 get_xattr_in->size = uio->uio_resid; 2050 2051 attr_str = (char *)fdi.indata + sizeof(*get_xattr_in); 2052 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2053 ap->a_name); 2054 2055 err = fdisp_wait_answ(&fdi); 2056 if (err != 0) { 2057 if (err == ENOSYS) 2058 fsess_set_notimpl(mp, FUSE_GETXATTR); 2059 goto out; 2060 } 2061 2062 get_xattr_out = fdi.answ; 2063 2064 if (ap->a_size != NULL) 2065 *ap->a_size = get_xattr_out->size; 2066 2067 if (uio != NULL) 2068 err = uiomove(fdi.answ, fdi.iosize, uio); 2069 2070 out: 2071 fdisp_destroy(&fdi); 2072 return (err); 2073 } 2074 2075 /* 2076 struct vop_setextattr_args { 2077 struct vop_generic_args a_gen; 2078 struct vnode *a_vp; 2079 int a_attrnamespace; 2080 const char *a_name; 2081 struct uio *a_uio; 2082 struct ucred *a_cred; 2083 struct thread *a_td; 2084 }; 2085 */ 2086 static int 2087 fuse_vnop_setextattr(struct vop_setextattr_args *ap) 2088 { 2089 struct vnode *vp = ap->a_vp; 2090 struct uio *uio = ap->a_uio; 2091 struct fuse_dispatcher fdi; 2092 struct fuse_setxattr_in *set_xattr_in; 2093 struct mount *mp = vnode_mount(vp); 2094 struct thread *td = ap->a_td; 2095 struct ucred *cred = ap->a_cred; 2096 char *prefix; 2097 size_t len; 2098 char *attr_str; 2099 int err; 2100 2101 if (fuse_isdeadfs(vp)) 2102 return (ENXIO); 2103 2104 /* Default to looking for user attributes. */ 2105 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2106 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2107 else 2108 prefix = EXTATTR_NAMESPACE_USER_STRING; 2109 2110 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2111 strlen(ap->a_name) + 1; 2112 2113 fdisp_init(&fdi, len + sizeof(*set_xattr_in) + uio->uio_resid); 2114 fdisp_make_vp(&fdi, FUSE_SETXATTR, vp, td, cred); 2115 2116 set_xattr_in = fdi.indata; 2117 set_xattr_in->size = uio->uio_resid; 2118 2119 attr_str = (char *)fdi.indata + sizeof(*set_xattr_in); 2120 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2121 ap->a_name); 2122 2123 err = uiomove((char *)fdi.indata + sizeof(*set_xattr_in) + len, 2124 uio->uio_resid, uio); 2125 if (err != 0) { 2126 goto out; 2127 } 2128 2129 err = fdisp_wait_answ(&fdi); 2130 2131 if (err != 0) { 2132 if (err == ENOSYS) 2133 fsess_set_notimpl(mp, FUSE_SETXATTR); 2134 goto out; 2135 } 2136 2137 out: 2138 fdisp_destroy(&fdi); 2139 return (err); 2140 } 2141 2142 /* 2143 * The Linux / FUSE extended attribute list is simply a collection of 2144 * NUL-terminated strings. The FreeBSD extended attribute list is a single 2145 * byte length followed by a non-NUL terminated string. So, this allows 2146 * conversion of the Linux / FUSE format to the FreeBSD format in place. 2147 * Linux attribute names are reported with the namespace as a prefix (e.g. 2148 * "user.attribute_name"), but in FreeBSD they are reported without the 2149 * namespace prefix (e.g. "attribute_name"). So, we're going from: 2150 * 2151 * user.attr_name1\0user.attr_name2\0 2152 * 2153 * to: 2154 * 2155 * <num>attr_name1<num>attr_name2 2156 * 2157 * Where "<num>" is a single byte number of characters in the attribute name. 2158 * 2159 * Args: 2160 * prefix - exattr namespace prefix string 2161 * list, list_len - input list with namespace prefixes 2162 * bsd_list, bsd_list_len - output list compatible with bsd vfs 2163 */ 2164 static int 2165 fuse_xattrlist_convert(char *prefix, const char *list, int list_len, 2166 char *bsd_list, int *bsd_list_len) 2167 { 2168 int len, pos, dist_to_next, prefix_len; 2169 2170 pos = 0; 2171 *bsd_list_len = 0; 2172 prefix_len = strlen(prefix); 2173 2174 while (pos < list_len && list[pos] != '\0') { 2175 dist_to_next = strlen(&list[pos]) + 1; 2176 if (bcmp(&list[pos], prefix, prefix_len) == 0 && 2177 list[pos + prefix_len] == extattr_namespace_separator) { 2178 len = dist_to_next - 2179 (prefix_len + sizeof(extattr_namespace_separator)) - 1; 2180 if (len >= EXTATTR_MAXNAMELEN) 2181 return (ENAMETOOLONG); 2182 2183 bsd_list[*bsd_list_len] = len; 2184 memcpy(&bsd_list[*bsd_list_len + 1], 2185 &list[pos + prefix_len + 2186 sizeof(extattr_namespace_separator)], len); 2187 2188 *bsd_list_len += len + 1; 2189 } 2190 2191 pos += dist_to_next; 2192 } 2193 2194 return (0); 2195 } 2196 2197 /* 2198 struct vop_listextattr_args { 2199 struct vop_generic_args a_gen; 2200 struct vnode *a_vp; 2201 int a_attrnamespace; 2202 struct uio *a_uio; 2203 size_t *a_size; 2204 struct ucred *a_cred; 2205 struct thread *a_td; 2206 }; 2207 */ 2208 static int 2209 fuse_vnop_listextattr(struct vop_listextattr_args *ap) 2210 { 2211 struct vnode *vp = ap->a_vp; 2212 struct uio *uio = ap->a_uio; 2213 struct fuse_dispatcher fdi; 2214 struct fuse_listxattr_in *list_xattr_in; 2215 struct fuse_listxattr_out *list_xattr_out; 2216 struct mount *mp = vnode_mount(vp); 2217 struct thread *td = ap->a_td; 2218 struct ucred *cred = ap->a_cred; 2219 size_t len; 2220 char *prefix; 2221 char *attr_str; 2222 char *bsd_list = NULL; 2223 char *linux_list; 2224 int bsd_list_len; 2225 int linux_list_len; 2226 int err; 2227 2228 if (fuse_isdeadfs(vp)) 2229 return (ENXIO); 2230 2231 /* 2232 * Add space for a NUL and the period separator if enabled. 2233 * Default to looking for user attributes. 2234 */ 2235 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2236 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2237 else 2238 prefix = EXTATTR_NAMESPACE_USER_STRING; 2239 2240 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 1; 2241 2242 fdisp_init(&fdi, sizeof(*list_xattr_in) + len); 2243 fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred); 2244 2245 /* 2246 * Retrieve Linux / FUSE compatible list size. 2247 */ 2248 list_xattr_in = fdi.indata; 2249 list_xattr_in->size = 0; 2250 attr_str = (char *)fdi.indata + sizeof(*list_xattr_in); 2251 snprintf(attr_str, len, "%s%c", prefix, extattr_namespace_separator); 2252 2253 err = fdisp_wait_answ(&fdi); 2254 if (err != 0) { 2255 if (err == ENOSYS) 2256 fsess_set_notimpl(mp, FUSE_LISTXATTR); 2257 goto out; 2258 } 2259 2260 list_xattr_out = fdi.answ; 2261 linux_list_len = list_xattr_out->size; 2262 if (linux_list_len == 0) { 2263 if (ap->a_size != NULL) 2264 *ap->a_size = linux_list_len; 2265 goto out; 2266 } 2267 2268 /* 2269 * Retrieve Linux / FUSE compatible list values. 2270 */ 2271 fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred); 2272 list_xattr_in = fdi.indata; 2273 list_xattr_in->size = linux_list_len + sizeof(*list_xattr_out); 2274 attr_str = (char *)fdi.indata + sizeof(*list_xattr_in); 2275 snprintf(attr_str, len, "%s%c", prefix, extattr_namespace_separator); 2276 2277 err = fdisp_wait_answ(&fdi); 2278 if (err != 0) 2279 goto out; 2280 2281 linux_list = fdi.answ; 2282 linux_list_len = fdi.iosize; 2283 2284 /* 2285 * Retrieve the BSD compatible list values. 2286 * The Linux / FUSE attribute list format isn't the same 2287 * as FreeBSD's format. So we need to transform it into 2288 * FreeBSD's format before giving it to the user. 2289 */ 2290 bsd_list = malloc(linux_list_len, M_TEMP, M_WAITOK); 2291 err = fuse_xattrlist_convert(prefix, linux_list, linux_list_len, 2292 bsd_list, &bsd_list_len); 2293 if (err != 0) 2294 goto out; 2295 2296 if (ap->a_size != NULL) 2297 *ap->a_size = bsd_list_len; 2298 2299 if (uio != NULL) 2300 err = uiomove(bsd_list, bsd_list_len, uio); 2301 2302 out: 2303 free(bsd_list, M_TEMP); 2304 fdisp_destroy(&fdi); 2305 return (err); 2306 } 2307 2308 /* 2309 struct vop_deleteextattr_args { 2310 struct vop_generic_args a_gen; 2311 struct vnode *a_vp; 2312 int a_attrnamespace; 2313 const char *a_name; 2314 struct ucred *a_cred; 2315 struct thread *a_td; 2316 }; 2317 */ 2318 static int 2319 fuse_vnop_deleteextattr(struct vop_deleteextattr_args *ap) 2320 { 2321 struct vnode *vp = ap->a_vp; 2322 struct fuse_dispatcher fdi; 2323 struct mount *mp = vnode_mount(vp); 2324 struct thread *td = ap->a_td; 2325 struct ucred *cred = ap->a_cred; 2326 char *prefix; 2327 size_t len; 2328 char *attr_str; 2329 int err; 2330 2331 if (fuse_isdeadfs(vp)) 2332 return (ENXIO); 2333 2334 /* Default to looking for user attributes. */ 2335 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2336 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2337 else 2338 prefix = EXTATTR_NAMESPACE_USER_STRING; 2339 2340 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2341 strlen(ap->a_name) + 1; 2342 2343 fdisp_init(&fdi, len); 2344 fdisp_make_vp(&fdi, FUSE_REMOVEXATTR, vp, td, cred); 2345 2346 attr_str = fdi.indata; 2347 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2348 ap->a_name); 2349 2350 err = fdisp_wait_answ(&fdi); 2351 if (err != 0) { 2352 if (err == ENOSYS) 2353 fsess_set_notimpl(mp, FUSE_REMOVEXATTR); 2354 } 2355 2356 fdisp_destroy(&fdi); 2357 return (err); 2358 } 2359 2360 /* 2361 struct vnop_print_args { 2362 struct vnode *a_vp; 2363 }; 2364 */ 2365 static int 2366 fuse_vnop_print(struct vop_print_args *ap) 2367 { 2368 struct fuse_vnode_data *fvdat = VTOFUD(ap->a_vp); 2369 2370 printf("nodeid: %ju, parent nodeid: %ju, nlookup: %ju, flag: %#x\n", 2371 (uintmax_t)VTOILLU(ap->a_vp), (uintmax_t)fvdat->parent_nid, 2372 (uintmax_t)fvdat->nlookup, 2373 fvdat->flag); 2374 2375 return 0; 2376 } 2377