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