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