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