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 fvdat = VTOFUD(vp); 1178 1179 if (vnode_isdir(vp)) { 1180 isdir = 1; 1181 } 1182 fuse_open_flags = 0; 1183 if (isdir) { 1184 fufh_type = FUFH_RDONLY; 1185 } else { 1186 fufh_type = fuse_filehandle_xlate_from_fflags(mode); 1187 /* 1188 * For WRONLY opens, force DIRECT_IO. This is necessary 1189 * since writing a partial block through the buffer cache 1190 * will result in a read of the block and that read won't 1191 * be allowed by the WRONLY open. 1192 */ 1193 if (fufh_type == FUFH_WRONLY || 1194 (fvdat->flag & FN_DIRECTIO) != 0) 1195 fuse_open_flags = FOPEN_DIRECT_IO; 1196 } 1197 1198 if (fuse_filehandle_validrw(vp, fufh_type) != FUFH_INVALID) { 1199 fuse_vnode_open(vp, fuse_open_flags, td); 1200 return 0; 1201 } 1202 error = fuse_filehandle_open(vp, fufh_type, NULL, td, cred); 1203 1204 return error; 1205 } 1206 1207 static int 1208 fuse_vnop_pathconf(struct vop_pathconf_args *ap) 1209 { 1210 1211 switch (ap->a_name) { 1212 case _PC_FILESIZEBITS: 1213 *ap->a_retval = 64; 1214 return (0); 1215 case _PC_NAME_MAX: 1216 *ap->a_retval = NAME_MAX; 1217 return (0); 1218 case _PC_LINK_MAX: 1219 *ap->a_retval = MIN(LONG_MAX, FUSE_LINK_MAX); 1220 return (0); 1221 case _PC_SYMLINK_MAX: 1222 *ap->a_retval = MAXPATHLEN; 1223 return (0); 1224 case _PC_NO_TRUNC: 1225 *ap->a_retval = 1; 1226 return (0); 1227 default: 1228 return (vop_stdpathconf(ap)); 1229 } 1230 } 1231 1232 /* 1233 struct vnop_read_args { 1234 struct vnode *a_vp; 1235 struct uio *a_uio; 1236 int a_ioflag; 1237 struct ucred *a_cred; 1238 }; 1239 */ 1240 static int 1241 fuse_vnop_read(struct vop_read_args *ap) 1242 { 1243 struct vnode *vp = ap->a_vp; 1244 struct uio *uio = ap->a_uio; 1245 int ioflag = ap->a_ioflag; 1246 struct ucred *cred = ap->a_cred; 1247 1248 FS_DEBUG2G("inode=%ju offset=%jd resid=%zd\n", 1249 (uintmax_t)VTOI(vp), uio->uio_offset, uio->uio_resid); 1250 1251 if (fuse_isdeadfs(vp)) { 1252 return ENXIO; 1253 } 1254 1255 if (VTOFUD(vp)->flag & FN_DIRECTIO) { 1256 ioflag |= IO_DIRECT; 1257 } 1258 1259 return fuse_io_dispatch(vp, uio, ioflag, cred); 1260 } 1261 1262 /* 1263 struct vnop_readdir_args { 1264 struct vnode *a_vp; 1265 struct uio *a_uio; 1266 struct ucred *a_cred; 1267 int *a_eofflag; 1268 int *ncookies; 1269 u_long **a_cookies; 1270 }; 1271 */ 1272 static int 1273 fuse_vnop_readdir(struct vop_readdir_args *ap) 1274 { 1275 struct vnode *vp = ap->a_vp; 1276 struct uio *uio = ap->a_uio; 1277 struct ucred *cred = ap->a_cred; 1278 1279 struct fuse_filehandle *fufh = NULL; 1280 struct fuse_iov cookediov; 1281 1282 int err = 0; 1283 int freefufh = 0; 1284 1285 FS_DEBUG2G("inode=%ju\n", (uintmax_t)VTOI(vp)); 1286 1287 if (fuse_isdeadfs(vp)) { 1288 return ENXIO; 1289 } 1290 if ( /* XXXIP ((uio_iovcnt(uio) > 1)) || */ 1291 (uio_resid(uio) < sizeof(struct dirent))) { 1292 return EINVAL; 1293 } 1294 1295 if (!fuse_filehandle_valid(vp, FUFH_RDONLY)) { 1296 FS_DEBUG("calling readdir() before open()"); 1297 err = fuse_filehandle_open(vp, FUFH_RDONLY, &fufh, NULL, cred); 1298 freefufh = 1; 1299 } else { 1300 err = fuse_filehandle_get(vp, FUFH_RDONLY, &fufh); 1301 } 1302 if (err) { 1303 return (err); 1304 } 1305 #define DIRCOOKEDSIZE FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + MAXNAMLEN + 1) 1306 fiov_init(&cookediov, DIRCOOKEDSIZE); 1307 1308 err = fuse_internal_readdir(vp, uio, fufh, &cookediov); 1309 1310 fiov_teardown(&cookediov); 1311 if (freefufh) { 1312 fuse_filehandle_close(vp, FUFH_RDONLY, NULL, cred); 1313 } 1314 return err; 1315 } 1316 1317 /* 1318 struct vnop_readlink_args { 1319 struct vnode *a_vp; 1320 struct uio *a_uio; 1321 struct ucred *a_cred; 1322 }; 1323 */ 1324 static int 1325 fuse_vnop_readlink(struct vop_readlink_args *ap) 1326 { 1327 struct vnode *vp = ap->a_vp; 1328 struct uio *uio = ap->a_uio; 1329 struct ucred *cred = ap->a_cred; 1330 1331 struct fuse_dispatcher fdi; 1332 int err; 1333 1334 FS_DEBUG2G("inode=%ju\n", (uintmax_t)VTOI(vp)); 1335 1336 if (fuse_isdeadfs(vp)) { 1337 return ENXIO; 1338 } 1339 if (!vnode_islnk(vp)) { 1340 return EINVAL; 1341 } 1342 fdisp_init(&fdi, 0); 1343 err = fdisp_simple_putget_vp(&fdi, FUSE_READLINK, vp, curthread, cred); 1344 if (err) { 1345 goto out; 1346 } 1347 if (((char *)fdi.answ)[0] == '/' && 1348 fuse_get_mpdata(vnode_mount(vp))->dataflags & FSESS_PUSH_SYMLINKS_IN) { 1349 char *mpth = vnode_mount(vp)->mnt_stat.f_mntonname; 1350 1351 err = uiomove(mpth, strlen(mpth), uio); 1352 } 1353 if (!err) { 1354 err = uiomove(fdi.answ, fdi.iosize, uio); 1355 } 1356 out: 1357 fdisp_destroy(&fdi); 1358 return err; 1359 } 1360 1361 /* 1362 struct vnop_reclaim_args { 1363 struct vnode *a_vp; 1364 struct thread *a_td; 1365 }; 1366 */ 1367 static int 1368 fuse_vnop_reclaim(struct vop_reclaim_args *ap) 1369 { 1370 struct vnode *vp = ap->a_vp; 1371 struct thread *td = ap->a_td; 1372 1373 struct fuse_vnode_data *fvdat = VTOFUD(vp); 1374 struct fuse_filehandle *fufh = NULL; 1375 1376 int type; 1377 1378 if (!fvdat) { 1379 panic("FUSE: no vnode data during recycling"); 1380 } 1381 FS_DEBUG("inode=%ju\n", (uintmax_t)VTOI(vp)); 1382 1383 for (type = 0; type < FUFH_MAXTYPE; type++) { 1384 fufh = &(fvdat->fufh[type]); 1385 if (FUFH_IS_VALID(fufh)) { 1386 printf("FUSE: vnode being reclaimed but fufh (type=%d) is valid", 1387 type); 1388 fuse_filehandle_close(vp, type, td, NULL); 1389 } 1390 } 1391 1392 if ((!fuse_isdeadfs(vp)) && (fvdat->nlookup)) { 1393 fuse_internal_forget_send(vnode_mount(vp), td, NULL, VTOI(vp), 1394 fvdat->nlookup); 1395 } 1396 fuse_vnode_setparent(vp, NULL); 1397 cache_purge(vp); 1398 vfs_hash_remove(vp); 1399 vnode_destroy_vobject(vp); 1400 fuse_vnode_destroy(vp); 1401 1402 return 0; 1403 } 1404 1405 /* 1406 struct vnop_remove_args { 1407 struct vnode *a_dvp; 1408 struct vnode *a_vp; 1409 struct componentname *a_cnp; 1410 }; 1411 */ 1412 static int 1413 fuse_vnop_remove(struct vop_remove_args *ap) 1414 { 1415 struct vnode *dvp = ap->a_dvp; 1416 struct vnode *vp = ap->a_vp; 1417 struct componentname *cnp = ap->a_cnp; 1418 1419 int err; 1420 1421 FS_DEBUG2G("inode=%ju name=%*s\n", 1422 (uintmax_t)VTOI(vp), (int)cnp->cn_namelen, cnp->cn_nameptr); 1423 1424 if (fuse_isdeadfs(vp)) { 1425 return ENXIO; 1426 } 1427 if (vnode_isdir(vp)) { 1428 return EPERM; 1429 } 1430 cache_purge(vp); 1431 1432 err = fuse_internal_remove(dvp, vp, cnp, FUSE_UNLINK); 1433 1434 if (err == 0) 1435 fuse_internal_vnode_disappear(vp); 1436 return err; 1437 } 1438 1439 /* 1440 struct vnop_rename_args { 1441 struct vnode *a_fdvp; 1442 struct vnode *a_fvp; 1443 struct componentname *a_fcnp; 1444 struct vnode *a_tdvp; 1445 struct vnode *a_tvp; 1446 struct componentname *a_tcnp; 1447 }; 1448 */ 1449 static int 1450 fuse_vnop_rename(struct vop_rename_args *ap) 1451 { 1452 struct vnode *fdvp = ap->a_fdvp; 1453 struct vnode *fvp = ap->a_fvp; 1454 struct componentname *fcnp = ap->a_fcnp; 1455 struct vnode *tdvp = ap->a_tdvp; 1456 struct vnode *tvp = ap->a_tvp; 1457 struct componentname *tcnp = ap->a_tcnp; 1458 struct fuse_data *data; 1459 1460 int err = 0; 1461 1462 FS_DEBUG2G("from: inode=%ju name=%*s -> to: inode=%ju name=%*s\n", 1463 (uintmax_t)VTOI(fvp), (int)fcnp->cn_namelen, fcnp->cn_nameptr, 1464 (uintmax_t)(tvp == NULL ? -1 : VTOI(tvp)), 1465 (int)tcnp->cn_namelen, tcnp->cn_nameptr); 1466 1467 if (fuse_isdeadfs(fdvp)) { 1468 return ENXIO; 1469 } 1470 if (fvp->v_mount != tdvp->v_mount || 1471 (tvp && fvp->v_mount != tvp->v_mount)) { 1472 FS_DEBUG("cross-device rename: %s -> %s\n", 1473 fcnp->cn_nameptr, (tcnp != NULL ? tcnp->cn_nameptr : "(NULL)")); 1474 err = EXDEV; 1475 goto out; 1476 } 1477 cache_purge(fvp); 1478 1479 /* 1480 * FUSE library is expected to check if target directory is not 1481 * under the source directory in the file system tree. 1482 * Linux performs this check at VFS level. 1483 */ 1484 data = fuse_get_mpdata(vnode_mount(tdvp)); 1485 sx_xlock(&data->rename_lock); 1486 err = fuse_internal_rename(fdvp, fcnp, tdvp, tcnp); 1487 if (err == 0) { 1488 if (tdvp != fdvp) 1489 fuse_vnode_setparent(fvp, tdvp); 1490 if (tvp != NULL) 1491 fuse_vnode_setparent(tvp, NULL); 1492 } 1493 sx_unlock(&data->rename_lock); 1494 1495 if (tvp != NULL && tvp != fvp) { 1496 cache_purge(tvp); 1497 } 1498 if (vnode_isdir(fvp)) { 1499 if ((tvp != NULL) && vnode_isdir(tvp)) { 1500 cache_purge(tdvp); 1501 } 1502 cache_purge(fdvp); 1503 } 1504 out: 1505 if (tdvp == tvp) { 1506 vrele(tdvp); 1507 } else { 1508 vput(tdvp); 1509 } 1510 if (tvp != NULL) { 1511 vput(tvp); 1512 } 1513 vrele(fdvp); 1514 vrele(fvp); 1515 1516 return err; 1517 } 1518 1519 /* 1520 struct vnop_rmdir_args { 1521 struct vnode *a_dvp; 1522 struct vnode *a_vp; 1523 struct componentname *a_cnp; 1524 } *ap; 1525 */ 1526 static int 1527 fuse_vnop_rmdir(struct vop_rmdir_args *ap) 1528 { 1529 struct vnode *dvp = ap->a_dvp; 1530 struct vnode *vp = ap->a_vp; 1531 1532 int err; 1533 1534 FS_DEBUG2G("inode=%ju\n", (uintmax_t)VTOI(vp)); 1535 1536 if (fuse_isdeadfs(vp)) { 1537 return ENXIO; 1538 } 1539 if (VTOFUD(vp) == VTOFUD(dvp)) { 1540 return EINVAL; 1541 } 1542 err = fuse_internal_remove(dvp, vp, ap->a_cnp, FUSE_RMDIR); 1543 1544 if (err == 0) 1545 fuse_internal_vnode_disappear(vp); 1546 return err; 1547 } 1548 1549 /* 1550 struct vnop_setattr_args { 1551 struct vnode *a_vp; 1552 struct vattr *a_vap; 1553 struct ucred *a_cred; 1554 struct thread *a_td; 1555 }; 1556 */ 1557 static int 1558 fuse_vnop_setattr(struct vop_setattr_args *ap) 1559 { 1560 struct vnode *vp = ap->a_vp; 1561 struct vattr *vap = ap->a_vap; 1562 struct ucred *cred = ap->a_cred; 1563 struct thread *td = curthread; 1564 1565 struct fuse_dispatcher fdi; 1566 struct fuse_setattr_in *fsai; 1567 struct fuse_access_param facp; 1568 1569 int err = 0; 1570 enum vtype vtyp; 1571 int sizechanged = 0; 1572 uint64_t newsize = 0; 1573 1574 FS_DEBUG2G("inode=%ju\n", (uintmax_t)VTOI(vp)); 1575 1576 if (fuse_isdeadfs(vp)) { 1577 return ENXIO; 1578 } 1579 fdisp_init(&fdi, sizeof(*fsai)); 1580 fdisp_make_vp(&fdi, FUSE_SETATTR, vp, td, cred); 1581 fsai = fdi.indata; 1582 fsai->valid = 0; 1583 1584 bzero(&facp, sizeof(facp)); 1585 1586 facp.xuid = vap->va_uid; 1587 facp.xgid = vap->va_gid; 1588 1589 if (vap->va_uid != (uid_t)VNOVAL) { 1590 facp.facc_flags |= FACCESS_CHOWN; 1591 fsai->uid = vap->va_uid; 1592 fsai->valid |= FATTR_UID; 1593 } 1594 if (vap->va_gid != (gid_t)VNOVAL) { 1595 facp.facc_flags |= FACCESS_CHOWN; 1596 fsai->gid = vap->va_gid; 1597 fsai->valid |= FATTR_GID; 1598 } 1599 if (vap->va_size != VNOVAL) { 1600 1601 struct fuse_filehandle *fufh = NULL; 1602 1603 /*Truncate to a new value. */ 1604 fsai->size = vap->va_size; 1605 sizechanged = 1; 1606 newsize = vap->va_size; 1607 fsai->valid |= FATTR_SIZE; 1608 1609 fuse_filehandle_getrw(vp, FUFH_WRONLY, &fufh); 1610 if (fufh) { 1611 fsai->fh = fufh->fh_id; 1612 fsai->valid |= FATTR_FH; 1613 } 1614 } 1615 if (vap->va_atime.tv_sec != VNOVAL) { 1616 fsai->atime = vap->va_atime.tv_sec; 1617 fsai->atimensec = vap->va_atime.tv_nsec; 1618 fsai->valid |= FATTR_ATIME; 1619 } 1620 if (vap->va_mtime.tv_sec != VNOVAL) { 1621 fsai->mtime = vap->va_mtime.tv_sec; 1622 fsai->mtimensec = vap->va_mtime.tv_nsec; 1623 fsai->valid |= FATTR_MTIME; 1624 } 1625 if (vap->va_mode != (mode_t)VNOVAL) { 1626 fsai->mode = vap->va_mode & ALLPERMS; 1627 fsai->valid |= FATTR_MODE; 1628 } 1629 if (!fsai->valid) { 1630 goto out; 1631 } 1632 vtyp = vnode_vtype(vp); 1633 1634 if (fsai->valid & FATTR_SIZE && vtyp == VDIR) { 1635 err = EISDIR; 1636 goto out; 1637 } 1638 if (vfs_isrdonly(vnode_mount(vp)) && (fsai->valid & ~FATTR_SIZE || vtyp == VREG)) { 1639 err = EROFS; 1640 goto out; 1641 } 1642 if (fsai->valid & ~FATTR_SIZE) { 1643 /*err = fuse_internal_access(vp, VADMIN, context, &facp); */ 1644 /*XXX */ 1645 err = 0; 1646 } 1647 facp.facc_flags &= ~FACCESS_XQUERIES; 1648 1649 if (err && !(fsai->valid & ~(FATTR_ATIME | FATTR_MTIME)) && 1650 vap->va_vaflags & VA_UTIMES_NULL) { 1651 err = fuse_internal_access(vp, VWRITE, &facp, td, cred); 1652 } 1653 if (err) 1654 goto out; 1655 if ((err = fdisp_wait_answ(&fdi))) 1656 goto out; 1657 vtyp = IFTOVT(((struct fuse_attr_out *)fdi.answ)->attr.mode); 1658 1659 if (vnode_vtype(vp) != vtyp) { 1660 if (vnode_vtype(vp) == VNON && vtyp != VNON) { 1661 debug_printf("FUSE: Dang! vnode_vtype is VNON and vtype isn't.\n"); 1662 } else { 1663 /* 1664 * STALE vnode, ditch 1665 * 1666 * The vnode has changed its type "behind our back". There's 1667 * nothing really we can do, so let us just force an internal 1668 * revocation and tell the caller to try again, if interested. 1669 */ 1670 fuse_internal_vnode_disappear(vp); 1671 err = EAGAIN; 1672 } 1673 } 1674 if (err == 0) 1675 cache_attrs(vp, (struct fuse_attr_out *)fdi.answ, NULL); 1676 1677 out: 1678 fdisp_destroy(&fdi); 1679 if (!err && sizechanged) { 1680 fuse_vnode_setsize(vp, cred, newsize); 1681 VTOFUD(vp)->flag &= ~FN_SIZECHANGE; 1682 } 1683 return err; 1684 } 1685 1686 /* 1687 struct vnop_strategy_args { 1688 struct vnode *a_vp; 1689 struct buf *a_bp; 1690 }; 1691 */ 1692 static int 1693 fuse_vnop_strategy(struct vop_strategy_args *ap) 1694 { 1695 struct vnode *vp = ap->a_vp; 1696 struct buf *bp = ap->a_bp; 1697 1698 fuse_trace_printf_vnop(); 1699 1700 if (!vp || fuse_isdeadfs(vp)) { 1701 bp->b_ioflags |= BIO_ERROR; 1702 bp->b_error = ENXIO; 1703 bufdone(bp); 1704 return ENXIO; 1705 } 1706 if (bp->b_iocmd == BIO_WRITE) 1707 fuse_vnode_refreshsize(vp, NOCRED); 1708 1709 (void)fuse_io_strategy(vp, bp); 1710 1711 /* 1712 * This is a dangerous function. If returns error, that might mean a 1713 * panic. We prefer pretty much anything over being forced to panic 1714 * by a malicious daemon (a demon?). So we just return 0 anyway. You 1715 * should never mind this: this function has its own error 1716 * propagation mechanism via the argument buffer, so 1717 * not-that-melodramatic residents of the call chain still will be 1718 * able to know what to do. 1719 */ 1720 return 0; 1721 } 1722 1723 1724 /* 1725 struct vnop_symlink_args { 1726 struct vnode *a_dvp; 1727 struct vnode **a_vpp; 1728 struct componentname *a_cnp; 1729 struct vattr *a_vap; 1730 char *a_target; 1731 }; 1732 */ 1733 static int 1734 fuse_vnop_symlink(struct vop_symlink_args *ap) 1735 { 1736 struct vnode *dvp = ap->a_dvp; 1737 struct vnode **vpp = ap->a_vpp; 1738 struct componentname *cnp = ap->a_cnp; 1739 const char *target = ap->a_target; 1740 1741 struct fuse_dispatcher fdi; 1742 1743 int err; 1744 size_t len; 1745 1746 FS_DEBUG2G("inode=%ju name=%*s\n", 1747 (uintmax_t)VTOI(dvp), (int)cnp->cn_namelen, cnp->cn_nameptr); 1748 1749 if (fuse_isdeadfs(dvp)) { 1750 return ENXIO; 1751 } 1752 /* 1753 * Unlike the other creator type calls, here we have to create a message 1754 * where the name of the new entry comes first, and the data describing 1755 * the entry comes second. 1756 * Hence we can't rely on our handy fuse_internal_newentry() routine, 1757 * but put together the message manually and just call the core part. 1758 */ 1759 1760 len = strlen(target) + 1; 1761 fdisp_init(&fdi, len + cnp->cn_namelen + 1); 1762 fdisp_make_vp(&fdi, FUSE_SYMLINK, dvp, curthread, NULL); 1763 1764 memcpy(fdi.indata, cnp->cn_nameptr, cnp->cn_namelen); 1765 ((char *)fdi.indata)[cnp->cn_namelen] = '\0'; 1766 memcpy((char *)fdi.indata + cnp->cn_namelen + 1, target, len); 1767 1768 err = fuse_internal_newentry_core(dvp, vpp, cnp, VLNK, &fdi); 1769 fdisp_destroy(&fdi); 1770 return err; 1771 } 1772 1773 /* 1774 struct vnop_write_args { 1775 struct vnode *a_vp; 1776 struct uio *a_uio; 1777 int a_ioflag; 1778 struct ucred *a_cred; 1779 }; 1780 */ 1781 static int 1782 fuse_vnop_write(struct vop_write_args *ap) 1783 { 1784 struct vnode *vp = ap->a_vp; 1785 struct uio *uio = ap->a_uio; 1786 int ioflag = ap->a_ioflag; 1787 struct ucred *cred = ap->a_cred; 1788 1789 fuse_trace_printf_vnop(); 1790 1791 if (fuse_isdeadfs(vp)) { 1792 return ENXIO; 1793 } 1794 fuse_vnode_refreshsize(vp, cred); 1795 1796 if (VTOFUD(vp)->flag & FN_DIRECTIO) { 1797 ioflag |= IO_DIRECT; 1798 } 1799 1800 return fuse_io_dispatch(vp, uio, ioflag, cred); 1801 } 1802 1803 /* 1804 struct vnop_getpages_args { 1805 struct vnode *a_vp; 1806 vm_page_t *a_m; 1807 int a_count; 1808 int a_reqpage; 1809 }; 1810 */ 1811 static int 1812 fuse_vnop_getpages(struct vop_getpages_args *ap) 1813 { 1814 int i, error, nextoff, size, toff, count, npages; 1815 struct uio uio; 1816 struct iovec iov; 1817 vm_offset_t kva; 1818 struct buf *bp; 1819 struct vnode *vp; 1820 struct thread *td; 1821 struct ucred *cred; 1822 vm_page_t *pages; 1823 1824 FS_DEBUG2G("heh\n"); 1825 1826 vp = ap->a_vp; 1827 KASSERT(vp->v_object, ("objectless vp passed to getpages")); 1828 td = curthread; /* XXX */ 1829 cred = curthread->td_ucred; /* XXX */ 1830 pages = ap->a_m; 1831 npages = ap->a_count; 1832 1833 if (!fsess_opt_mmap(vnode_mount(vp))) { 1834 FS_DEBUG("called on non-cacheable vnode??\n"); 1835 return (VM_PAGER_ERROR); 1836 } 1837 1838 /* 1839 * If the last page is partially valid, just return it and allow 1840 * the pager to zero-out the blanks. Partially valid pages can 1841 * only occur at the file EOF. 1842 * 1843 * XXXGL: is that true for FUSE, which is a local filesystem, 1844 * but still somewhat disconnected from the kernel? 1845 */ 1846 VM_OBJECT_WLOCK(vp->v_object); 1847 if (pages[npages - 1]->valid != 0 && --npages == 0) 1848 goto out; 1849 VM_OBJECT_WUNLOCK(vp->v_object); 1850 1851 /* 1852 * We use only the kva address for the buffer, but this is extremely 1853 * convenient and fast. 1854 */ 1855 bp = uma_zalloc(fuse_pbuf_zone, M_WAITOK); 1856 1857 kva = (vm_offset_t)bp->b_data; 1858 pmap_qenter(kva, pages, npages); 1859 VM_CNT_INC(v_vnodein); 1860 VM_CNT_ADD(v_vnodepgsin, npages); 1861 1862 count = npages << PAGE_SHIFT; 1863 iov.iov_base = (caddr_t)kva; 1864 iov.iov_len = count; 1865 uio.uio_iov = &iov; 1866 uio.uio_iovcnt = 1; 1867 uio.uio_offset = IDX_TO_OFF(pages[0]->pindex); 1868 uio.uio_resid = count; 1869 uio.uio_segflg = UIO_SYSSPACE; 1870 uio.uio_rw = UIO_READ; 1871 uio.uio_td = td; 1872 1873 error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred); 1874 pmap_qremove(kva, npages); 1875 1876 uma_zfree(fuse_pbuf_zone, bp); 1877 1878 if (error && (uio.uio_resid == count)) { 1879 FS_DEBUG("error %d\n", error); 1880 return VM_PAGER_ERROR; 1881 } 1882 /* 1883 * Calculate the number of bytes read and validate only that number 1884 * of bytes. Note that due to pending writes, size may be 0. This 1885 * does not mean that the remaining data is invalid! 1886 */ 1887 1888 size = count - uio.uio_resid; 1889 VM_OBJECT_WLOCK(vp->v_object); 1890 fuse_vm_page_lock_queues(); 1891 for (i = 0, toff = 0; i < npages; i++, toff = nextoff) { 1892 vm_page_t m; 1893 1894 nextoff = toff + PAGE_SIZE; 1895 m = pages[i]; 1896 1897 if (nextoff <= size) { 1898 /* 1899 * Read operation filled an entire page 1900 */ 1901 m->valid = VM_PAGE_BITS_ALL; 1902 KASSERT(m->dirty == 0, 1903 ("fuse_getpages: page %p is dirty", m)); 1904 } else if (size > toff) { 1905 /* 1906 * Read operation filled a partial page. 1907 */ 1908 m->valid = 0; 1909 vm_page_set_valid_range(m, 0, size - toff); 1910 KASSERT(m->dirty == 0, 1911 ("fuse_getpages: page %p is dirty", m)); 1912 } else { 1913 /* 1914 * Read operation was short. If no error occurred 1915 * we may have hit a zero-fill section. We simply 1916 * leave valid set to 0. 1917 */ 1918 ; 1919 } 1920 } 1921 fuse_vm_page_unlock_queues(); 1922 out: 1923 VM_OBJECT_WUNLOCK(vp->v_object); 1924 if (ap->a_rbehind) 1925 *ap->a_rbehind = 0; 1926 if (ap->a_rahead) 1927 *ap->a_rahead = 0; 1928 return (VM_PAGER_OK); 1929 } 1930 1931 /* 1932 struct vnop_putpages_args { 1933 struct vnode *a_vp; 1934 vm_page_t *a_m; 1935 int a_count; 1936 int a_sync; 1937 int *a_rtvals; 1938 vm_ooffset_t a_offset; 1939 }; 1940 */ 1941 static int 1942 fuse_vnop_putpages(struct vop_putpages_args *ap) 1943 { 1944 struct uio uio; 1945 struct iovec iov; 1946 vm_offset_t kva; 1947 struct buf *bp; 1948 int i, error, npages, count; 1949 off_t offset; 1950 int *rtvals; 1951 struct vnode *vp; 1952 struct thread *td; 1953 struct ucred *cred; 1954 vm_page_t *pages; 1955 vm_ooffset_t fsize; 1956 1957 FS_DEBUG2G("heh\n"); 1958 1959 vp = ap->a_vp; 1960 KASSERT(vp->v_object, ("objectless vp passed to putpages")); 1961 fsize = vp->v_object->un_pager.vnp.vnp_size; 1962 td = curthread; /* XXX */ 1963 cred = curthread->td_ucred; /* XXX */ 1964 pages = ap->a_m; 1965 count = ap->a_count; 1966 rtvals = ap->a_rtvals; 1967 npages = btoc(count); 1968 offset = IDX_TO_OFF(pages[0]->pindex); 1969 1970 if (!fsess_opt_mmap(vnode_mount(vp))) { 1971 FS_DEBUG("called on non-cacheable vnode??\n"); 1972 } 1973 for (i = 0; i < npages; i++) 1974 rtvals[i] = VM_PAGER_AGAIN; 1975 1976 /* 1977 * When putting pages, do not extend file past EOF. 1978 */ 1979 1980 if (offset + count > fsize) { 1981 count = fsize - offset; 1982 if (count < 0) 1983 count = 0; 1984 } 1985 /* 1986 * We use only the kva address for the buffer, but this is extremely 1987 * convenient and fast. 1988 */ 1989 bp = uma_zalloc(fuse_pbuf_zone, M_WAITOK); 1990 1991 kva = (vm_offset_t)bp->b_data; 1992 pmap_qenter(kva, pages, npages); 1993 VM_CNT_INC(v_vnodeout); 1994 VM_CNT_ADD(v_vnodepgsout, count); 1995 1996 iov.iov_base = (caddr_t)kva; 1997 iov.iov_len = count; 1998 uio.uio_iov = &iov; 1999 uio.uio_iovcnt = 1; 2000 uio.uio_offset = offset; 2001 uio.uio_resid = count; 2002 uio.uio_segflg = UIO_SYSSPACE; 2003 uio.uio_rw = UIO_WRITE; 2004 uio.uio_td = td; 2005 2006 error = fuse_io_dispatch(vp, &uio, IO_DIRECT, cred); 2007 2008 pmap_qremove(kva, npages); 2009 uma_zfree(fuse_pbuf_zone, bp); 2010 2011 if (!error) { 2012 int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE; 2013 2014 for (i = 0; i < nwritten; i++) { 2015 rtvals[i] = VM_PAGER_OK; 2016 VM_OBJECT_WLOCK(pages[i]->object); 2017 vm_page_undirty(pages[i]); 2018 VM_OBJECT_WUNLOCK(pages[i]->object); 2019 } 2020 } 2021 return rtvals[0]; 2022 } 2023 2024 static const char extattr_namespace_separator = '.'; 2025 2026 /* 2027 struct vop_getextattr_args { 2028 struct vop_generic_args a_gen; 2029 struct vnode *a_vp; 2030 int a_attrnamespace; 2031 const char *a_name; 2032 struct uio *a_uio; 2033 size_t *a_size; 2034 struct ucred *a_cred; 2035 struct thread *a_td; 2036 }; 2037 */ 2038 static int 2039 fuse_vnop_getextattr(struct vop_getextattr_args *ap) 2040 { 2041 struct vnode *vp = ap->a_vp; 2042 struct uio *uio = ap->a_uio; 2043 struct fuse_dispatcher fdi; 2044 struct fuse_getxattr_in *get_xattr_in; 2045 struct fuse_getxattr_out *get_xattr_out; 2046 struct mount *mp = vnode_mount(vp); 2047 struct thread *td = ap->a_td; 2048 struct ucred *cred = ap->a_cred; 2049 char *prefix; 2050 char *attr_str; 2051 size_t len; 2052 int err; 2053 2054 fuse_trace_printf_vnop(); 2055 2056 if (fuse_isdeadfs(vp)) 2057 return (ENXIO); 2058 2059 /* Default to looking for user attributes. */ 2060 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2061 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2062 else 2063 prefix = EXTATTR_NAMESPACE_USER_STRING; 2064 2065 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2066 strlen(ap->a_name) + 1; 2067 2068 fdisp_init(&fdi, len + sizeof(*get_xattr_in)); 2069 fdisp_make_vp(&fdi, FUSE_GETXATTR, vp, td, cred); 2070 2071 get_xattr_in = fdi.indata; 2072 /* 2073 * Check to see whether we're querying the available size or 2074 * issuing the actual request. If we pass in 0, we get back struct 2075 * fuse_getxattr_out. If we pass in a non-zero size, we get back 2076 * that much data, without the struct fuse_getxattr_out header. 2077 */ 2078 if (uio == NULL) 2079 get_xattr_in->size = 0; 2080 else 2081 get_xattr_in->size = uio->uio_resid; 2082 2083 attr_str = (char *)fdi.indata + sizeof(*get_xattr_in); 2084 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2085 ap->a_name); 2086 2087 err = fdisp_wait_answ(&fdi); 2088 if (err != 0) { 2089 if (err == ENOSYS) 2090 fsess_set_notimpl(mp, FUSE_GETXATTR); 2091 debug_printf("getxattr: got err=%d from daemon\n", err); 2092 goto out; 2093 } 2094 2095 get_xattr_out = fdi.answ; 2096 2097 if (ap->a_size != NULL) 2098 *ap->a_size = get_xattr_out->size; 2099 2100 if (uio != NULL) 2101 err = uiomove(fdi.answ, fdi.iosize, uio); 2102 2103 out: 2104 fdisp_destroy(&fdi); 2105 return (err); 2106 } 2107 2108 /* 2109 struct vop_setextattr_args { 2110 struct vop_generic_args a_gen; 2111 struct vnode *a_vp; 2112 int a_attrnamespace; 2113 const char *a_name; 2114 struct uio *a_uio; 2115 struct ucred *a_cred; 2116 struct thread *a_td; 2117 }; 2118 */ 2119 static int 2120 fuse_vnop_setextattr(struct vop_setextattr_args *ap) 2121 { 2122 struct vnode *vp = ap->a_vp; 2123 struct uio *uio = ap->a_uio; 2124 struct fuse_dispatcher fdi; 2125 struct fuse_setxattr_in *set_xattr_in; 2126 struct mount *mp = vnode_mount(vp); 2127 struct thread *td = ap->a_td; 2128 struct ucred *cred = ap->a_cred; 2129 char *prefix; 2130 size_t len; 2131 char *attr_str; 2132 int err; 2133 2134 fuse_trace_printf_vnop(); 2135 2136 if (fuse_isdeadfs(vp)) 2137 return (ENXIO); 2138 2139 /* Default to looking for user attributes. */ 2140 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2141 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2142 else 2143 prefix = EXTATTR_NAMESPACE_USER_STRING; 2144 2145 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2146 strlen(ap->a_name) + 1; 2147 2148 fdisp_init(&fdi, len + sizeof(*set_xattr_in) + uio->uio_resid); 2149 fdisp_make_vp(&fdi, FUSE_SETXATTR, vp, td, cred); 2150 2151 set_xattr_in = fdi.indata; 2152 set_xattr_in->size = uio->uio_resid; 2153 2154 attr_str = (char *)fdi.indata + sizeof(*set_xattr_in); 2155 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2156 ap->a_name); 2157 2158 err = uiomove((char *)fdi.indata + sizeof(*set_xattr_in) + len, 2159 uio->uio_resid, uio); 2160 if (err != 0) { 2161 debug_printf("setxattr: got error %d from uiomove\n", err); 2162 goto out; 2163 } 2164 2165 err = fdisp_wait_answ(&fdi); 2166 2167 if (err != 0) { 2168 if (err == ENOSYS) 2169 fsess_set_notimpl(mp, FUSE_SETXATTR); 2170 debug_printf("setxattr: got err=%d from daemon\n", err); 2171 goto out; 2172 } 2173 2174 out: 2175 fdisp_destroy(&fdi); 2176 return (err); 2177 } 2178 2179 /* 2180 * The Linux / FUSE extended attribute list is simply a collection of 2181 * NUL-terminated strings. The FreeBSD extended attribute list is a single 2182 * byte length followed by a non-NUL terminated string. So, this allows 2183 * conversion of the Linux / FUSE format to the FreeBSD format in place. 2184 * Linux attribute names are reported with the namespace as a prefix (e.g. 2185 * "user.attribute_name"), but in FreeBSD they are reported without the 2186 * namespace prefix (e.g. "attribute_name"). So, we're going from: 2187 * 2188 * user.attr_name1\0user.attr_name2\0 2189 * 2190 * to: 2191 * 2192 * <num>attr_name1<num>attr_name2 2193 * 2194 * Where "<num>" is a single byte number of characters in the attribute name. 2195 * 2196 * Args: 2197 * prefix - exattr namespace prefix string 2198 * list, list_len - input list with namespace prefixes 2199 * bsd_list, bsd_list_len - output list compatible with bsd vfs 2200 */ 2201 static int 2202 fuse_xattrlist_convert(char *prefix, const char *list, int list_len, 2203 char *bsd_list, int *bsd_list_len) 2204 { 2205 int len, pos, dist_to_next, prefix_len; 2206 2207 pos = 0; 2208 *bsd_list_len = 0; 2209 prefix_len = strlen(prefix); 2210 2211 while (pos < list_len && list[pos] != '\0') { 2212 dist_to_next = strlen(&list[pos]) + 1; 2213 if (bcmp(&list[pos], prefix, prefix_len) == 0 && 2214 list[pos + prefix_len] == extattr_namespace_separator) { 2215 len = dist_to_next - 2216 (prefix_len + sizeof(extattr_namespace_separator)) - 1; 2217 if (len >= EXTATTR_MAXNAMELEN) 2218 return (ENAMETOOLONG); 2219 2220 bsd_list[*bsd_list_len] = len; 2221 memcpy(&bsd_list[*bsd_list_len + 1], 2222 &list[pos + prefix_len + 2223 sizeof(extattr_namespace_separator)], len); 2224 2225 *bsd_list_len += len + 1; 2226 } 2227 2228 pos += dist_to_next; 2229 } 2230 2231 return (0); 2232 } 2233 2234 /* 2235 struct vop_listextattr_args { 2236 struct vop_generic_args a_gen; 2237 struct vnode *a_vp; 2238 int a_attrnamespace; 2239 struct uio *a_uio; 2240 size_t *a_size; 2241 struct ucred *a_cred; 2242 struct thread *a_td; 2243 }; 2244 */ 2245 static int 2246 fuse_vnop_listextattr(struct vop_listextattr_args *ap) 2247 { 2248 struct vnode *vp = ap->a_vp; 2249 struct uio *uio = ap->a_uio; 2250 struct fuse_dispatcher fdi; 2251 struct fuse_listxattr_in *list_xattr_in; 2252 struct fuse_listxattr_out *list_xattr_out; 2253 struct mount *mp = vnode_mount(vp); 2254 struct thread *td = ap->a_td; 2255 struct ucred *cred = ap->a_cred; 2256 size_t len; 2257 char *prefix; 2258 char *attr_str; 2259 char *bsd_list = NULL; 2260 char *linux_list; 2261 int bsd_list_len; 2262 int linux_list_len; 2263 int err; 2264 2265 fuse_trace_printf_vnop(); 2266 2267 if (fuse_isdeadfs(vp)) 2268 return (ENXIO); 2269 2270 /* 2271 * Add space for a NUL and the period separator if enabled. 2272 * Default to looking for user attributes. 2273 */ 2274 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2275 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2276 else 2277 prefix = EXTATTR_NAMESPACE_USER_STRING; 2278 2279 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 1; 2280 2281 fdisp_init(&fdi, sizeof(*list_xattr_in) + len); 2282 fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred); 2283 2284 /* 2285 * Retrieve Linux / FUSE compatible list size. 2286 */ 2287 list_xattr_in = fdi.indata; 2288 list_xattr_in->size = 0; 2289 attr_str = (char *)fdi.indata + sizeof(*list_xattr_in); 2290 snprintf(attr_str, len, "%s%c", prefix, extattr_namespace_separator); 2291 2292 err = fdisp_wait_answ(&fdi); 2293 if (err != 0) { 2294 if (err == ENOSYS) 2295 fsess_set_notimpl(mp, FUSE_LISTXATTR); 2296 debug_printf("listextattr: got err=%d from daemon\n", err); 2297 goto out; 2298 } 2299 2300 list_xattr_out = fdi.answ; 2301 linux_list_len = list_xattr_out->size; 2302 if (linux_list_len == 0) { 2303 if (ap->a_size != NULL) 2304 *ap->a_size = linux_list_len; 2305 goto out; 2306 } 2307 2308 /* 2309 * Retrieve Linux / FUSE compatible list values. 2310 */ 2311 fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred); 2312 list_xattr_in = fdi.indata; 2313 list_xattr_in->size = linux_list_len + sizeof(*list_xattr_out); 2314 attr_str = (char *)fdi.indata + sizeof(*list_xattr_in); 2315 snprintf(attr_str, len, "%s%c", prefix, extattr_namespace_separator); 2316 2317 err = fdisp_wait_answ(&fdi); 2318 if (err != 0) 2319 goto out; 2320 2321 linux_list = fdi.answ; 2322 linux_list_len = fdi.iosize; 2323 2324 /* 2325 * Retrieve the BSD compatible list values. 2326 * The Linux / FUSE attribute list format isn't the same 2327 * as FreeBSD's format. So we need to transform it into 2328 * FreeBSD's format before giving it to the user. 2329 */ 2330 bsd_list = malloc(linux_list_len, M_TEMP, M_WAITOK); 2331 err = fuse_xattrlist_convert(prefix, linux_list, linux_list_len, 2332 bsd_list, &bsd_list_len); 2333 if (err != 0) 2334 goto out; 2335 2336 if (ap->a_size != NULL) 2337 *ap->a_size = bsd_list_len; 2338 2339 if (uio != NULL) 2340 err = uiomove(bsd_list, bsd_list_len, uio); 2341 2342 out: 2343 free(bsd_list, M_TEMP); 2344 fdisp_destroy(&fdi); 2345 return (err); 2346 } 2347 2348 /* 2349 struct vop_deleteextattr_args { 2350 struct vop_generic_args a_gen; 2351 struct vnode *a_vp; 2352 int a_attrnamespace; 2353 const char *a_name; 2354 struct ucred *a_cred; 2355 struct thread *a_td; 2356 }; 2357 */ 2358 static int 2359 fuse_vnop_deleteextattr(struct vop_deleteextattr_args *ap) 2360 { 2361 struct vnode *vp = ap->a_vp; 2362 struct fuse_dispatcher fdi; 2363 struct mount *mp = vnode_mount(vp); 2364 struct thread *td = ap->a_td; 2365 struct ucred *cred = ap->a_cred; 2366 char *prefix; 2367 size_t len; 2368 char *attr_str; 2369 int err; 2370 2371 fuse_trace_printf_vnop(); 2372 2373 if (fuse_isdeadfs(vp)) 2374 return (ENXIO); 2375 2376 /* Default to looking for user attributes. */ 2377 if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) 2378 prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; 2379 else 2380 prefix = EXTATTR_NAMESPACE_USER_STRING; 2381 2382 len = strlen(prefix) + sizeof(extattr_namespace_separator) + 2383 strlen(ap->a_name) + 1; 2384 2385 fdisp_init(&fdi, len); 2386 fdisp_make_vp(&fdi, FUSE_REMOVEXATTR, vp, td, cred); 2387 2388 attr_str = fdi.indata; 2389 snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, 2390 ap->a_name); 2391 2392 err = fdisp_wait_answ(&fdi); 2393 if (err != 0) { 2394 if (err == ENOSYS) 2395 fsess_set_notimpl(mp, FUSE_REMOVEXATTR); 2396 debug_printf("removexattr: got err=%d from daemon\n", err); 2397 } 2398 2399 fdisp_destroy(&fdi); 2400 return (err); 2401 } 2402 2403 /* 2404 struct vnop_print_args { 2405 struct vnode *a_vp; 2406 }; 2407 */ 2408 static int 2409 fuse_vnop_print(struct vop_print_args *ap) 2410 { 2411 struct fuse_vnode_data *fvdat = VTOFUD(ap->a_vp); 2412 2413 printf("nodeid: %ju, parent nodeid: %ju, nlookup: %ju, flag: %#x\n", 2414 (uintmax_t)VTOILLU(ap->a_vp), (uintmax_t)fvdat->parent_nid, 2415 (uintmax_t)fvdat->nlookup, 2416 fvdat->flag); 2417 2418 return 0; 2419 } 2420