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