1 /* $OpenBSD: fuse_vnops.c,v 1.33 2016/09/07 17:53:35 natano Exp $ */ 2 /* 3 * Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/dirent.h> 21 #include <sys/fcntl.h> 22 #include <sys/file.h> 23 #include <sys/lockf.h> 24 #include <sys/malloc.h> 25 #include <sys/mount.h> 26 #include <sys/namei.h> 27 #include <sys/poll.h> 28 #include <sys/proc.h> 29 #include <sys/specdev.h> 30 #include <sys/stat.h> 31 #include <sys/statvfs.h> 32 #include <sys/vnode.h> 33 #include <sys/lock.h> 34 #include <sys/fusebuf.h> 35 36 #include "fusefs_node.h" 37 #include "fusefs.h" 38 39 /* Prototypes for fusefs vnode ops */ 40 int fusefs_kqfilter(void *); 41 int fusefs_lookup(void *); 42 int fusefs_open(void *); 43 int fusefs_close(void *); 44 int fusefs_access(void *); 45 int fusefs_getattr(void *); 46 int fusefs_setattr(void *); 47 int fusefs_ioctl(void *); 48 int fusefs_link(void *); 49 int fusefs_symlink(void *); 50 int fusefs_readdir(void *); 51 int fusefs_readlink(void *); 52 int fusefs_inactive(void *); 53 int fusefs_reclaim(void *); 54 int fusefs_print(void *); 55 int fusefs_create(void *); 56 int fusefs_mknod(void *); 57 int fusefs_read(void *); 58 int fusefs_write(void *); 59 int fusefs_poll(void *); 60 int fusefs_remove(void *); 61 int fusefs_rename(void *); 62 int fusefs_mkdir(void *); 63 int fusefs_rmdir(void *); 64 int fusefs_strategy(void *); 65 int fusefs_lock(void *); 66 int fusefs_unlock(void *); 67 int fusefs_islocked(void *); 68 int fusefs_advlock(void *); 69 70 /* Prototypes for fusefs kqfilter */ 71 int filt_fusefsread(struct knote *, long); 72 int filt_fusefswrite(struct knote *, long); 73 int filt_fusefsvnode(struct knote *, long); 74 void filt_fusefsdetach(struct knote *); 75 76 struct vops fusefs_vops = { 77 .vop_lookup = fusefs_lookup, 78 .vop_create = fusefs_create, 79 .vop_mknod = fusefs_mknod, 80 .vop_open = fusefs_open, 81 .vop_close = fusefs_close, 82 .vop_access = fusefs_access, 83 .vop_getattr = fusefs_getattr, 84 .vop_setattr = fusefs_setattr, 85 .vop_read = fusefs_read, 86 .vop_write = fusefs_write, 87 .vop_ioctl = fusefs_ioctl, 88 .vop_poll = fusefs_poll, 89 .vop_kqfilter = fusefs_kqfilter, 90 .vop_fsync = nullop, 91 .vop_remove = fusefs_remove, 92 .vop_link = fusefs_link, 93 .vop_rename = fusefs_rename, 94 .vop_mkdir = fusefs_mkdir, 95 .vop_rmdir = fusefs_rmdir, 96 .vop_symlink = fusefs_symlink, 97 .vop_readdir = fusefs_readdir, 98 .vop_readlink = fusefs_readlink, 99 .vop_abortop = vop_generic_abortop, 100 .vop_inactive = fusefs_inactive, 101 .vop_reclaim = fusefs_reclaim, 102 .vop_lock = fusefs_lock, 103 .vop_unlock = fusefs_unlock, 104 .vop_bmap = vop_generic_bmap, 105 .vop_strategy = fusefs_strategy, 106 .vop_print = fusefs_print, 107 .vop_islocked = fusefs_islocked, 108 .vop_pathconf = spec_pathconf, 109 .vop_advlock = fusefs_advlock, 110 }; 111 112 struct filterops fusefsread_filtops = 113 { 1, NULL, filt_fusefsdetach, filt_fusefsread }; 114 struct filterops fusefswrite_filtops = 115 { 1, NULL, filt_fusefsdetach, filt_fusefswrite }; 116 struct filterops fusefsvnode_filtops = 117 { 1, NULL, filt_fusefsdetach, filt_fusefsvnode }; 118 119 int 120 fusefs_kqfilter(void *v) 121 { 122 struct vop_kqfilter_args *ap = v; 123 struct vnode *vp = ap->a_vp; 124 struct knote *kn = ap->a_kn; 125 126 switch (kn->kn_filter) { 127 case EVFILT_READ: 128 kn->kn_fop = &fusefsread_filtops; 129 break; 130 case EVFILT_WRITE: 131 kn->kn_fop = &fusefswrite_filtops; 132 break; 133 case EVFILT_VNODE: 134 kn->kn_fop = &fusefsvnode_filtops; 135 break; 136 default: 137 return (EINVAL); 138 } 139 140 kn->kn_hook = (caddr_t)vp; 141 142 SLIST_INSERT_HEAD(&vp->v_selectinfo.si_note, kn, kn_selnext); 143 144 return (0); 145 } 146 147 void 148 filt_fusefsdetach(struct knote *kn) 149 { 150 struct vnode *vp = (struct vnode *)kn->kn_hook; 151 152 SLIST_REMOVE(&vp->v_selectinfo.si_note, kn, knote, kn_selnext); 153 } 154 155 int 156 filt_fusefsread(struct knote *kn, long hint) 157 { 158 struct vnode *vp = (struct vnode *)kn->kn_hook; 159 struct fusefs_node *ip = VTOI(vp); 160 161 /* 162 * filesystem is gone, so set the EOF flag and schedule 163 * the knote for deletion 164 */ 165 if (hint == NOTE_REVOKE) { 166 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 167 return (1); 168 } 169 170 kn->kn_data = ip->filesize - kn->kn_fp->f_offset; 171 if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { 172 kn->kn_fflags |= NOTE_EOF; 173 return (1); 174 } 175 176 return (kn->kn_data != 0); 177 } 178 179 int 180 filt_fusefswrite(struct knote *kn, long hint) 181 { 182 /* 183 * filesystem is gone, so set the EOF flag and schedule 184 * the knote for deletion 185 */ 186 if (hint == NOTE_REVOKE) { 187 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 188 return (1); 189 } 190 191 kn->kn_data = 0; 192 return (1); 193 } 194 195 int 196 filt_fusefsvnode(struct knote *kn, long int hint) 197 { 198 if (kn->kn_sfflags & hint) 199 kn->kn_fflags |= hint; 200 if (hint == NOTE_REVOKE) { 201 kn->kn_flags |= EV_EOF; 202 return (1); 203 } 204 return (kn->kn_fflags != 0); 205 } 206 207 int 208 fusefs_open(void *v) 209 { 210 struct vop_open_args *ap; 211 struct fusefs_node *ip; 212 struct fusefs_mnt *fmp; 213 enum fufh_type fufh_type = FUFH_RDONLY; 214 int flags = O_RDONLY; 215 int error; 216 int isdir; 217 218 ap = v; 219 ip = VTOI(ap->a_vp); 220 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 221 222 if (!fmp->sess_init) 223 return (ENXIO); 224 225 isdir = 0; 226 if (ap->a_vp->v_type == VDIR) 227 isdir = 1; 228 else { 229 if ((ap->a_mode & FREAD) && (ap->a_mode & FWRITE)) { 230 fufh_type = FUFH_RDWR; 231 flags = O_RDWR; 232 } else if (ap->a_mode & (FWRITE)) { 233 fufh_type = FUFH_WRONLY; 234 flags = O_WRONLY; 235 } 236 } 237 238 /* already open i think all is ok */ 239 if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) 240 return (0); 241 242 error = fusefs_file_open(fmp, ip, fufh_type, flags, isdir, ap->a_p); 243 if (error) 244 return (error); 245 246 return (error); 247 } 248 249 int 250 fusefs_close(void *v) 251 { 252 struct vop_close_args *ap; 253 struct fusefs_node *ip; 254 struct fusefs_mnt *fmp; 255 enum fufh_type fufh_type = FUFH_RDONLY; 256 int isdir, i; 257 258 ap = v; 259 ip = VTOI(ap->a_vp); 260 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 261 262 if (!fmp->sess_init) 263 return (0); 264 265 if (ap->a_vp->v_type == VDIR) { 266 isdir = 1; 267 268 if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) 269 return (fusefs_file_close(fmp, ip, fufh_type, O_RDONLY, 270 isdir, ap->a_p)); 271 } else { 272 if (ap->a_fflag & IO_NDELAY) 273 return (0); 274 275 if ((ap->a_fflag & FREAD) && (ap->a_fflag & FWRITE)) 276 fufh_type = FUFH_RDWR; 277 else if (ap->a_fflag & (FWRITE)) 278 fufh_type = FUFH_WRONLY; 279 } 280 281 /* 282 * if fh not valid lookup for another valid fh in vnode. 283 * Do we need panic if there's not a valid fh ? 284 */ 285 if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) { 286 for (i = 0; i < FUFH_MAXTYPE; i++) 287 if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) 288 break; 289 return (0); 290 } 291 292 return (0); 293 } 294 295 int 296 fusefs_access(void *v) 297 { 298 struct vop_access_args *ap; 299 struct fusefs_node *ip; 300 struct fusefs_mnt *fmp; 301 struct fusebuf *fbuf; 302 struct ucred *cred; 303 struct vattr vattr; 304 struct proc *p; 305 uint32_t mask = 0; 306 int error = 0; 307 308 ap = v; 309 p = ap->a_p; 310 cred = p->p_ucred; 311 ip = VTOI(ap->a_vp); 312 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 313 314 if (!fmp->sess_init) 315 return (ENXIO); 316 317 if (fmp->undef_op & UNDEF_ACCESS) 318 goto system_check; 319 320 if (ap->a_vp->v_type == VLNK) 321 goto system_check; 322 323 if (ap->a_vp->v_type == VREG && (ap->a_mode & VWRITE & VEXEC)) 324 goto system_check; 325 326 if ((ap->a_mode & VWRITE) && (fmp->mp->mnt_flag & MNT_RDONLY)) 327 return (EACCES); 328 329 if ((ap->a_mode & VWRITE) != 0) 330 mask |= 0x2; 331 332 if ((ap->a_mode & VREAD) != 0) 333 mask |= 0x4; 334 335 if ((ap->a_mode & VEXEC) != 0) 336 mask |= 0x1; 337 338 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_ACCESS, p); 339 fbuf->fb_io_mode = mask; 340 341 error = fb_queue(fmp->dev, fbuf); 342 if (error) { 343 if (error == ENOSYS) { 344 fmp->undef_op |= UNDEF_ACCESS; 345 fb_delete(fbuf); 346 goto system_check; 347 } 348 349 printf("fusefs: access error %i\n", error); 350 fb_delete(fbuf); 351 return (error); 352 } 353 354 fb_delete(fbuf); 355 return (error); 356 357 system_check: 358 if ((error = VOP_GETATTR(ap->a_vp, &vattr, cred, p)) != 0) 359 return (error); 360 361 return (vaccess(ap->a_vp->v_type, vattr.va_mode & ALLPERMS, 362 vattr.va_uid, vattr.va_gid, ap->a_mode, 363 ap->a_cred)); 364 } 365 366 int 367 fusefs_getattr(void *v) 368 { 369 struct vop_getattr_args *ap = v; 370 struct vnode *vp = ap->a_vp; 371 struct fusefs_mnt *fmp; 372 struct vattr *vap = ap->a_vap; 373 struct proc *p = ap->a_p; 374 struct fusefs_node *ip; 375 struct fusebuf *fbuf; 376 struct stat *st; 377 int error = 0; 378 379 ip = VTOI(vp); 380 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 381 382 if (!fmp->sess_init) 383 return (ENXIO); 384 385 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_GETATTR, p); 386 387 error = fb_queue(fmp->dev, fbuf); 388 if (error) { 389 fb_delete(fbuf); 390 return (error); 391 } 392 393 VATTR_NULL(vap); 394 st = &fbuf->fb_attr; 395 396 vap->va_type = IFTOVT(st->st_mode); 397 vap->va_mode = st->st_mode & ~S_IFMT; 398 vap->va_nlink = st->st_nlink; 399 vap->va_uid = st->st_uid; 400 vap->va_gid = st->st_gid; 401 vap->va_fsid = fmp->mp->mnt_stat.f_fsid.val[0]; 402 vap->va_fileid = st->st_ino; 403 vap->va_size = st->st_size; 404 vap->va_blocksize = st->st_blksize; 405 vap->va_atime = st->st_atim; 406 vap->va_mtime = st->st_mtim; 407 vap->va_ctime = st->st_ctim; 408 vap->va_rdev = st->st_rdev; 409 vap->va_bytes = st->st_blocks * S_BLKSIZE; 410 411 fb_delete(fbuf); 412 return (error); 413 } 414 415 int 416 fusefs_setattr(void *v) 417 { 418 struct vop_setattr_args *ap = v; 419 struct vattr *vap = ap->a_vap; 420 struct vnode *vp = ap->a_vp; 421 struct fusefs_node *ip = VTOI(vp); 422 struct proc *p = ap->a_p; 423 struct fusefs_mnt *fmp; 424 struct fusebuf *fbuf; 425 struct fb_io *io; 426 int error = 0; 427 428 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 429 /* 430 * Check for unsettable attributes. 431 */ 432 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 433 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 434 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 435 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) 436 return (EINVAL); 437 438 if (!fmp->sess_init) 439 return (ENXIO); 440 441 if (fmp->undef_op & UNDEF_SETATTR) 442 return (ENOSYS); 443 444 fbuf = fb_setup(sizeof(*io), ip->ufs_ino.i_number, FBT_SETATTR, p); 445 io = fbtod(fbuf, struct fb_io *); 446 io->fi_flags = 0; 447 448 if (vap->va_uid != (uid_t)VNOVAL) { 449 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 450 error = EROFS; 451 goto out; 452 } 453 fbuf->fb_attr.st_uid = vap->va_uid; 454 io->fi_flags |= FUSE_FATTR_UID; 455 } 456 457 if (vap->va_gid != (gid_t)VNOVAL) { 458 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 459 error = EROFS; 460 goto out; 461 } 462 fbuf->fb_attr.st_gid = vap->va_gid; 463 io->fi_flags |= FUSE_FATTR_GID; 464 } 465 466 if (vap->va_size != VNOVAL) { 467 switch (vp->v_type) { 468 case VDIR: 469 error = EISDIR; 470 goto out; 471 case VLNK: 472 case VREG: 473 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 474 error = EROFS; 475 goto out; 476 } 477 break; 478 default: 479 break; 480 } 481 482 fbuf->fb_attr.st_size = vap->va_size; 483 io->fi_flags |= FUSE_FATTR_SIZE; 484 } 485 486 if (vap->va_atime.tv_nsec != VNOVAL) { 487 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 488 error = EROFS; 489 goto out; 490 } 491 fbuf->fb_attr.st_atim = vap->va_atime; 492 io->fi_flags |= FUSE_FATTR_ATIME; 493 } 494 495 if (vap->va_mtime.tv_nsec != VNOVAL) { 496 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 497 error = EROFS; 498 goto out; 499 } 500 fbuf->fb_attr.st_mtim = vap->va_mtime; 501 io->fi_flags |= FUSE_FATTR_MTIME; 502 } 503 /* XXX should set a flag if (vap->va_vaflags & VA_UTIMES_CHANGE) */ 504 505 if (vap->va_mode != (mode_t)VNOVAL) { 506 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 507 error = EROFS; 508 goto out; 509 } 510 fbuf->fb_attr.st_mode = vap->va_mode & ALLPERMS; 511 io->fi_flags |= FUSE_FATTR_MODE; 512 } 513 514 if (!io->fi_flags) { 515 goto out; 516 } 517 518 error = fb_queue(fmp->dev, fbuf); 519 if (error) { 520 if (error == ENOSYS) 521 fmp->undef_op |= UNDEF_SETATTR; 522 goto out; 523 } 524 525 VN_KNOTE(ap->a_vp, NOTE_ATTRIB); 526 527 out: 528 fb_delete(fbuf); 529 return (error); 530 } 531 532 int 533 fusefs_ioctl(void *v) 534 { 535 return (ENOTTY); 536 } 537 538 int 539 fusefs_link(void *v) 540 { 541 struct vop_link_args *ap = v; 542 struct vnode *dvp = ap->a_dvp; 543 struct vnode *vp = ap->a_vp; 544 struct componentname *cnp = ap->a_cnp; 545 struct proc *p = cnp->cn_proc; 546 struct fusefs_mnt *fmp; 547 struct fusefs_node *ip; 548 struct fusefs_node *dip; 549 struct fusebuf *fbuf; 550 int error = 0; 551 552 ip = VTOI(vp); 553 dip = VTOI(dvp); 554 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 555 556 if (!fmp->sess_init) { 557 VOP_ABORTOP(dvp, cnp); 558 error = ENXIO; 559 goto out2; 560 } 561 if (fmp->undef_op & UNDEF_LINK) { 562 VOP_ABORTOP(dvp, cnp); 563 error = ENOSYS; 564 goto out2; 565 } 566 if (vp->v_type == VDIR) { 567 VOP_ABORTOP(dvp, cnp); 568 error = EISDIR; 569 goto out2; 570 } 571 if (dvp->v_mount != vp->v_mount) { 572 VOP_ABORTOP(dvp, cnp); 573 error = EXDEV; 574 goto out2; 575 } 576 if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, p))) { 577 VOP_ABORTOP(dvp, cnp); 578 goto out2; 579 } 580 581 fbuf = fb_setup(cnp->cn_namelen + 1, dip->ufs_ino.i_number, 582 FBT_LINK, p); 583 584 fbuf->fb_io_ino = ip->ufs_ino.i_number; 585 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 586 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 587 588 error = fb_queue(fmp->dev, fbuf); 589 590 if (error) { 591 if (error == ENOSYS) 592 fmp->undef_op |= UNDEF_LINK; 593 594 fb_delete(fbuf); 595 goto out1; 596 } 597 598 fb_delete(fbuf); 599 VN_KNOTE(vp, NOTE_LINK); 600 VN_KNOTE(dvp, NOTE_WRITE); 601 602 out1: 603 if (dvp != vp) 604 VOP_UNLOCK(vp, p); 605 out2: 606 vput(dvp); 607 return (error); 608 } 609 610 int 611 fusefs_symlink(void *v) 612 { 613 struct vop_symlink_args *ap = v; 614 struct vnode **vpp = ap->a_vpp; 615 struct componentname *cnp = ap->a_cnp; 616 struct vnode *dvp = ap->a_dvp; 617 struct proc *p = cnp->cn_proc; 618 char *target = ap->a_target; 619 struct fusefs_node *dp; 620 struct fusefs_mnt *fmp; 621 struct fusebuf *fbuf; 622 struct vnode *tdp; 623 int error = 0; 624 int len; 625 626 dp = VTOI(dvp); 627 fmp = (struct fusefs_mnt *)dp->ufs_ino.i_ump; 628 629 if (!fmp->sess_init) { 630 error = ENXIO; 631 goto bad; 632 } 633 634 if (fmp->undef_op & UNDEF_SYMLINK) { 635 error = ENOSYS; 636 goto bad; 637 } 638 639 len = strlen(target) + 1; 640 641 fbuf = fb_setup(len + cnp->cn_namelen + 1, dp->ufs_ino.i_number, 642 FBT_SYMLINK, p); 643 644 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 645 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 646 memcpy(&fbuf->fb_dat[cnp->cn_namelen + 1], target, len); 647 648 error = fb_queue(fmp->dev, fbuf); 649 if (error) { 650 if (error == ENOSYS) 651 fmp->undef_op |= UNDEF_SYMLINK; 652 653 fb_delete(fbuf); 654 goto bad; 655 } 656 657 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) { 658 fb_delete(fbuf); 659 goto bad; 660 } 661 662 tdp->v_type = VLNK; 663 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 664 665 *vpp = tdp; 666 fb_delete(fbuf); 667 vput(tdp); 668 bad: 669 vput(dvp); 670 return (error); 671 } 672 673 int 674 fusefs_readdir(void *v) 675 { 676 struct vop_readdir_args *ap = v; 677 struct fusefs_node *ip; 678 struct fusefs_mnt *fmp; 679 struct fusebuf *fbuf; 680 struct vnode *vp; 681 struct proc *p; 682 struct uio *uio; 683 int error = 0, eofflag = 0; 684 685 vp = ap->a_vp; 686 uio = ap->a_uio; 687 p = uio->uio_procp; 688 689 ip = VTOI(vp); 690 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 691 692 if (!fmp->sess_init) 693 return (ENXIO); 694 695 if (uio->uio_resid < sizeof(struct dirent)) 696 return (EINVAL); 697 698 while (uio->uio_resid > 0) { 699 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READDIR, p); 700 701 if (ip->fufh[FUFH_RDONLY].fh_type == FUFH_INVALID) { 702 /* TODO open the file */ 703 fb_delete(fbuf); 704 return (error); 705 } 706 fbuf->fb_io_fd = ip->fufh[FUFH_RDONLY].fh_id; 707 fbuf->fb_io_off = uio->uio_offset; 708 fbuf->fb_io_len = MIN(uio->uio_resid, fmp->max_read); 709 710 error = fb_queue(fmp->dev, fbuf); 711 712 if (error) { 713 fb_delete(fbuf); 714 break; 715 } 716 717 /* ack end of readdir */ 718 if (fbuf->fb_len == 0) { 719 eofflag = 1; 720 fb_delete(fbuf); 721 break; 722 } 723 724 if ((error = uiomove(fbuf->fb_dat, fbuf->fb_len, uio))) { 725 fb_delete(fbuf); 726 break; 727 } 728 729 fb_delete(fbuf); 730 } 731 732 if (!error && ap->a_eofflag != NULL) 733 *ap->a_eofflag = eofflag; 734 735 return (error); 736 } 737 738 int 739 fusefs_inactive(void *v) 740 { 741 struct vop_inactive_args *ap = v; 742 struct vnode *vp = ap->a_vp; 743 struct proc *p = ap->a_p; 744 struct ucred *cred = p->p_ucred; 745 struct fusefs_node *ip = VTOI(vp); 746 struct fusefs_filehandle *fufh = NULL; 747 struct fusefs_mnt *fmp; 748 struct vattr vattr; 749 int error = 0; 750 int type; 751 752 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 753 754 for (type = 0; type < FUFH_MAXTYPE; type++) { 755 fufh = &(ip->fufh[type]); 756 if (fufh->fh_type != FUFH_INVALID) 757 fusefs_file_close(fmp, ip, fufh->fh_type, type, 758 (vp->v_type == VDIR), ap->a_p); 759 } 760 761 error = VOP_GETATTR(vp, &vattr, cred, p); 762 763 VOP_UNLOCK(vp, p); 764 765 if (error) 766 vrecycle(vp, p); 767 768 return (0); 769 } 770 771 int 772 fusefs_readlink(void *v) 773 { 774 struct vop_readlink_args *ap = v; 775 struct vnode *vp = ap->a_vp; 776 struct fusefs_node *ip; 777 struct fusefs_mnt *fmp; 778 struct fusebuf *fbuf; 779 struct uio *uio; 780 struct proc *p; 781 int error = 0; 782 783 ip = VTOI(vp); 784 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 785 uio = ap->a_uio; 786 p = uio->uio_procp; 787 788 if (!fmp->sess_init) 789 return (ENXIO); 790 791 if (fmp->undef_op & UNDEF_READLINK) 792 return (ENOSYS); 793 794 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READLINK, p); 795 796 error = fb_queue(fmp->dev, fbuf); 797 798 if (error) { 799 if (error == ENOSYS) 800 fmp->undef_op |= UNDEF_READLINK; 801 802 fb_delete(fbuf); 803 return (error); 804 } 805 806 error = uiomove(fbuf->fb_dat, fbuf->fb_len, uio); 807 fb_delete(fbuf); 808 809 return (error); 810 } 811 812 int 813 fusefs_reclaim(void *v) 814 { 815 struct vop_reclaim_args *ap = v; 816 struct vnode *vp = ap->a_vp; 817 struct fusefs_node *ip = VTOI(vp); 818 struct fusefs_filehandle *fufh = NULL; 819 struct fusefs_mnt *fmp; 820 struct fusebuf *fbuf; 821 int type; 822 823 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 824 825 /*close opened files*/ 826 for (type = 0; type < FUFH_MAXTYPE; type++) { 827 fufh = &(ip->fufh[type]); 828 if (fufh->fh_type != FUFH_INVALID) { 829 printf("fusefs: vnode being reclaimed is valid\n"); 830 fusefs_file_close(fmp, ip, fufh->fh_type, type, 831 (vp->v_type == VDIR), ap->a_p); 832 } 833 } 834 835 /* 836 * if the fuse connection is opened 837 * ask libfuse to free the vnodes 838 */ 839 if (fmp->sess_init && ip->ufs_ino.i_number != FUSE_ROOTINO) { 840 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_RECLAIM, ap->a_p); 841 if (fb_queue(fmp->dev, fbuf)) 842 printf("fusefs: libfuse vnode reclaim failed\n"); 843 fb_delete(fbuf); 844 } 845 846 /* 847 * Remove the inode from its hash chain. 848 */ 849 ufs_ihashrem(&ip->ufs_ino); 850 851 free(ip, M_FUSEFS, 0); 852 vp->v_data = NULL; 853 return (0); 854 } 855 856 int 857 fusefs_print(void *v) 858 { 859 struct vop_print_args *ap = v; 860 struct vnode *vp = ap->a_vp; 861 struct fusefs_node *ip = VTOI(vp); 862 863 /* Complete the information given by vprint(). */ 864 printf("tag VT_FUSE, hash id %u ", ip->ufs_ino.i_number); 865 printf("\n"); 866 return (0); 867 } 868 869 int 870 fusefs_create(void *v) 871 { 872 struct vop_create_args *ap = v; 873 struct componentname *cnp = ap->a_cnp; 874 struct vnode **vpp = ap->a_vpp; 875 struct vnode *dvp = ap->a_dvp; 876 struct vattr *vap = ap->a_vap; 877 struct proc *p = cnp->cn_proc; 878 struct vnode *tdp = NULL; 879 struct fusefs_mnt *fmp; 880 struct fusefs_node *ip; 881 struct fusebuf *fbuf; 882 int error = 0; 883 mode_t mode; 884 885 ip = VTOI(dvp); 886 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 887 mode = MAKEIMODE(vap->va_type, vap->va_mode); 888 889 if (!fmp->sess_init) { 890 error = ENXIO; 891 goto out; 892 } 893 894 if (fmp->undef_op & UNDEF_CREATE) { 895 error = ENOSYS; 896 goto out; 897 } 898 899 fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number, 900 FBT_CREATE, p); 901 902 fbuf->fb_io_mode = mode; 903 fbuf->fb_io_flags = O_CREAT | O_RDWR; 904 905 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 906 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 907 908 error = fb_queue(fmp->dev, fbuf); 909 if (error) { 910 if (error == ENOSYS) 911 fmp->undef_op |= UNDEF_CREATE; 912 913 fb_delete(fbuf); 914 goto out; 915 } 916 917 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) { 918 fb_delete(fbuf); 919 goto out; 920 } 921 922 tdp->v_type = IFTOVT(fbuf->fb_io_mode); 923 924 *vpp = tdp; 925 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 926 fb_delete(fbuf); 927 out: 928 vput(ap->a_dvp); 929 return (error); 930 } 931 932 int 933 fusefs_mknod(void *v) 934 { 935 struct vop_mknod_args *ap = v; 936 struct componentname *cnp = ap->a_cnp; 937 struct vnode **vpp = ap->a_vpp; 938 struct vnode *dvp = ap->a_dvp; 939 struct vattr *vap = ap->a_vap; 940 struct proc *p = cnp->cn_proc; 941 struct vnode *tdp = NULL; 942 struct fusefs_mnt *fmp; 943 struct fusefs_node *ip; 944 struct fusebuf *fbuf; 945 int error = 0; 946 947 ip = VTOI(dvp); 948 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 949 950 if (!fmp->sess_init) { 951 error = ENXIO; 952 goto out; 953 } 954 955 if (fmp->undef_op & UNDEF_MKNOD) { 956 error = ENOSYS; 957 goto out; 958 } 959 960 fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number, 961 FBT_MKNOD, p); 962 963 fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode); 964 if (vap->va_rdev != VNOVAL) 965 fbuf->fb_io_rdev = vap->va_rdev; 966 967 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 968 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 969 970 error = fb_queue(fmp->dev, fbuf); 971 if (error) { 972 if (error == ENOSYS) 973 fmp->undef_op |= UNDEF_MKNOD; 974 975 fb_delete(fbuf); 976 goto out; 977 } 978 979 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) { 980 fb_delete(fbuf); 981 goto out; 982 } 983 984 tdp->v_type = IFTOVT(fbuf->fb_io_mode); 985 986 *vpp = tdp; 987 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 988 fb_delete(fbuf); 989 vput(ap->a_dvp); 990 991 /* Remove inode so that it will be reloaded by VFS_VGET and 992 * checked to see if it is an alias of an existing entry in 993 * the inode cache. 994 */ 995 vput(*vpp); 996 (*vpp)->v_type = VNON; 997 vgone(*vpp); 998 *vpp = NULL; 999 return (0); 1000 out: 1001 vput(ap->a_dvp); 1002 return (error); 1003 } 1004 1005 int 1006 fusefs_read(void *v) 1007 { 1008 struct vop_read_args *ap = v; 1009 struct vnode *vp = ap->a_vp; 1010 struct uio *uio = ap->a_uio; 1011 struct proc *p = uio->uio_procp; 1012 struct fusefs_node *ip; 1013 struct fusefs_mnt *fmp; 1014 struct fusebuf *fbuf = NULL; 1015 size_t size; 1016 int error=0; 1017 1018 ip = VTOI(vp); 1019 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1020 1021 if (!fmp->sess_init) 1022 return (ENXIO); 1023 if (uio->uio_resid == 0) 1024 return (error); 1025 if (uio->uio_offset < 0) 1026 return (EINVAL); 1027 1028 while (uio->uio_resid > 0) { 1029 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READ, p); 1030 1031 size = MIN(uio->uio_resid, fmp->max_read); 1032 fbuf->fb_io_fd = fusefs_fd_get(ip, FUFH_RDONLY); 1033 fbuf->fb_io_off = uio->uio_offset; 1034 fbuf->fb_io_len = size; 1035 1036 error = fb_queue(fmp->dev, fbuf); 1037 1038 if (error) 1039 break; 1040 1041 error = uiomove(fbuf->fb_dat, ulmin(size, fbuf->fb_len), uio); 1042 if (error) 1043 break; 1044 1045 if (fbuf->fb_len < size) 1046 break; 1047 1048 fb_delete(fbuf); 1049 fbuf = NULL; 1050 } 1051 1052 fb_delete(fbuf); 1053 return (error); 1054 } 1055 1056 int 1057 fusefs_write(void *v) 1058 { 1059 struct vop_write_args *ap = v; 1060 struct vnode *vp = ap->a_vp; 1061 struct uio *uio = ap->a_uio; 1062 struct proc *p = uio->uio_procp; 1063 struct ucred *cred = p->p_ucred; 1064 struct vattr vattr; 1065 int ioflag = ap->a_ioflag; 1066 struct fusefs_node *ip; 1067 struct fusefs_mnt *fmp; 1068 struct fusebuf *fbuf = NULL; 1069 size_t len, diff; 1070 int error=0; 1071 1072 ip = VTOI(vp); 1073 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1074 1075 if (!fmp->sess_init) 1076 return (ENXIO); 1077 if (uio->uio_resid == 0) 1078 return (error); 1079 1080 if (ioflag & IO_APPEND) { 1081 if ((error = VOP_GETATTR(vp, &vattr, cred, p)) != 0) 1082 return (error); 1083 1084 uio->uio_offset = vattr.va_size; 1085 } 1086 1087 while (uio->uio_resid > 0) { 1088 len = MIN(uio->uio_resid, fmp->max_read); 1089 fbuf = fb_setup(len, ip->ufs_ino.i_number, FBT_WRITE, p); 1090 1091 fbuf->fb_io_fd = fusefs_fd_get(ip, FUFH_WRONLY); 1092 fbuf->fb_io_off = uio->uio_offset; 1093 fbuf->fb_io_len = len; 1094 1095 if ((error = uiomove(fbuf->fb_dat, len, uio))) { 1096 printf("fusefs: uio error %i\n", error); 1097 break; 1098 } 1099 1100 error = fb_queue(fmp->dev, fbuf); 1101 1102 if (error) 1103 break; 1104 1105 diff = len - fbuf->fb_io_len; 1106 if (fbuf->fb_io_len > len) { 1107 error = EINVAL; 1108 break; 1109 } 1110 1111 uio->uio_resid += diff; 1112 uio->uio_offset -= diff; 1113 1114 fb_delete(fbuf); 1115 fbuf = NULL; 1116 } 1117 1118 fb_delete(fbuf); 1119 return (error); 1120 } 1121 1122 int 1123 fusefs_poll(void *v) 1124 { 1125 struct vop_poll_args *ap = v; 1126 1127 /* 1128 * We should really check to see if I/O is possible. 1129 */ 1130 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 1131 } 1132 1133 int 1134 fusefs_rename(void *v) 1135 { 1136 struct vop_rename_args *ap = v; 1137 struct vnode *tvp = ap->a_tvp; 1138 struct vnode *tdvp = ap->a_tdvp; 1139 struct vnode *fvp = ap->a_fvp; 1140 struct vnode *fdvp = ap->a_fdvp; 1141 struct componentname *tcnp = ap->a_tcnp; 1142 struct componentname *fcnp = ap->a_fcnp; 1143 struct proc *p = fcnp->cn_proc; 1144 struct fusefs_node *ip, *dp; 1145 struct fusefs_mnt *fmp; 1146 struct fusebuf *fbuf; 1147 int error = 0; 1148 1149 #ifdef DIAGNOSTIC 1150 if ((tcnp->cn_flags & HASBUF) == 0 || 1151 (fcnp->cn_flags & HASBUF) == 0) 1152 panic("fusefs_rename: no name"); 1153 #endif 1154 /* 1155 * Check for cross-device rename. 1156 */ 1157 if ((fvp->v_mount != tdvp->v_mount) || 1158 (tvp && (fvp->v_mount != tvp->v_mount))) { 1159 error = EXDEV; 1160 abortit: 1161 VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */ 1162 if (tdvp == tvp) 1163 vrele(tdvp); 1164 else 1165 vput(tdvp); 1166 if (tvp) 1167 vput(tvp); 1168 VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */ 1169 vrele(fdvp); 1170 vrele(fvp); 1171 return (error); 1172 } 1173 1174 /* 1175 * If source and dest are the same, do nothing. 1176 */ 1177 if (tvp == fvp) { 1178 error = 0; 1179 goto abortit; 1180 } 1181 1182 if ((error = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, p)) != 0) 1183 goto abortit; 1184 dp = VTOI(fdvp); 1185 ip = VTOI(fvp); 1186 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1187 1188 /* 1189 * Be sure we are not renaming ".", "..", or an alias of ".". This 1190 * leads to a crippled directory tree. It's pretty tough to do a 1191 * "ls" or "pwd" with the "." directory entry missing, and "cd .." 1192 * doesn't work if the ".." entry is missing. 1193 */ 1194 if (fvp->v_type == VDIR) { 1195 /* 1196 * Avoid ".", "..", and aliases of "." for obvious reasons. 1197 */ 1198 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || 1199 dp == ip || 1200 (fcnp->cn_flags & ISDOTDOT) || 1201 (tcnp->cn_flags & ISDOTDOT)) { 1202 VOP_UNLOCK(fvp, p); 1203 error = EINVAL; 1204 goto abortit; 1205 } 1206 } 1207 VN_KNOTE(fdvp, NOTE_WRITE); /* XXX right place? */ 1208 1209 if (!fmp->sess_init) { 1210 error = ENXIO; 1211 VOP_UNLOCK(fvp, p); 1212 goto abortit; 1213 } 1214 1215 if (fmp->undef_op & UNDEF_RENAME) { 1216 error = ENOSYS; 1217 VOP_UNLOCK(fvp, p); 1218 goto abortit; 1219 } 1220 1221 fbuf = fb_setup(fcnp->cn_namelen + tcnp->cn_namelen + 2, 1222 dp->ufs_ino.i_number, FBT_RENAME, p); 1223 1224 memcpy(fbuf->fb_dat, fcnp->cn_nameptr, fcnp->cn_namelen); 1225 fbuf->fb_dat[fcnp->cn_namelen] = '\0'; 1226 memcpy(fbuf->fb_dat + fcnp->cn_namelen + 1, tcnp->cn_nameptr, 1227 tcnp->cn_namelen); 1228 fbuf->fb_dat[fcnp->cn_namelen + tcnp->cn_namelen + 1] = '\0'; 1229 fbuf->fb_io_ino = VTOI(tdvp)->ufs_ino.i_number; 1230 1231 error = fb_queue(fmp->dev, fbuf); 1232 1233 if (error) { 1234 if (error == ENOSYS) { 1235 fmp->undef_op |= UNDEF_RENAME; 1236 } 1237 1238 fb_delete(fbuf); 1239 VOP_UNLOCK(fvp, p); 1240 goto abortit; 1241 } 1242 1243 fb_delete(fbuf); 1244 VN_KNOTE(fvp, NOTE_RENAME); 1245 1246 VOP_UNLOCK(fvp, p); 1247 if (tdvp == tvp) 1248 vrele(tdvp); 1249 else 1250 vput(tdvp); 1251 vrele(fdvp); 1252 vrele(fvp); 1253 1254 return (error); 1255 } 1256 1257 int 1258 fusefs_mkdir(void *v) 1259 { 1260 struct vop_mkdir_args *ap = v; 1261 struct vnode *dvp = ap->a_dvp; 1262 struct vnode **vpp = ap->a_vpp; 1263 struct componentname *cnp = ap->a_cnp; 1264 struct vattr *vap = ap->a_vap; 1265 struct proc *p = cnp->cn_proc; 1266 struct vnode *tdp = NULL; 1267 struct fusefs_node *ip; 1268 struct fusefs_mnt *fmp; 1269 struct fusebuf *fbuf; 1270 int error = 0; 1271 1272 ip = VTOI(dvp); 1273 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1274 1275 1276 if (!fmp->sess_init) { 1277 error = ENXIO; 1278 goto out; 1279 } 1280 1281 if (fmp->undef_op & UNDEF_MKDIR) { 1282 error = ENOSYS; 1283 goto out; 1284 } 1285 1286 fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number, 1287 FBT_MKDIR, p); 1288 1289 fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode); 1290 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1291 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1292 1293 error = fb_queue(fmp->dev, fbuf); 1294 if (error) { 1295 if (error == ENOSYS) 1296 fmp->undef_op |= UNDEF_MKDIR; 1297 1298 fb_delete(fbuf); 1299 goto out; 1300 } 1301 1302 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) { 1303 fb_delete(fbuf); 1304 goto out; 1305 } 1306 1307 tdp->v_type = IFTOVT(fbuf->fb_io_mode); 1308 1309 *vpp = tdp; 1310 VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK); 1311 fb_delete(fbuf); 1312 out: 1313 vput(dvp); 1314 return (error); 1315 } 1316 1317 int 1318 fusefs_rmdir(void *v) 1319 { 1320 struct vop_rmdir_args *ap = v; 1321 struct vnode *vp = ap->a_vp; 1322 struct vnode *dvp = ap->a_dvp; 1323 struct componentname *cnp = ap->a_cnp; 1324 struct proc *p = cnp->cn_proc; 1325 struct fusefs_node *ip, *dp; 1326 struct fusefs_mnt *fmp; 1327 struct fusebuf *fbuf; 1328 int error; 1329 1330 ip = VTOI(vp); 1331 dp = VTOI(dvp); 1332 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1333 1334 if (!fmp->sess_init) { 1335 error = ENXIO; 1336 goto out; 1337 } 1338 1339 if (fmp->undef_op & UNDEF_RMDIR) { 1340 error = ENOSYS; 1341 goto out; 1342 } 1343 1344 /* 1345 * No rmdir "." please. 1346 */ 1347 if (dp == ip) { 1348 vrele(dvp); 1349 vput(vp); 1350 return (EINVAL); 1351 } 1352 1353 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); 1354 1355 fbuf = fb_setup(cnp->cn_namelen + 1, dp->ufs_ino.i_number, 1356 FBT_RMDIR, p); 1357 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1358 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1359 1360 error = fb_queue(fmp->dev, fbuf); 1361 1362 if (error) { 1363 if (error == ENOSYS) 1364 fmp->undef_op |= UNDEF_RMDIR; 1365 if (error != ENOTEMPTY) 1366 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); 1367 1368 fb_delete(fbuf); 1369 goto out; 1370 } 1371 1372 vput(dvp); 1373 dvp = NULL; 1374 1375 fb_delete(fbuf); 1376 out: 1377 if (dvp) 1378 vput(dvp); 1379 VN_KNOTE(vp, NOTE_DELETE); 1380 vput(vp); 1381 return (error); 1382 } 1383 1384 int 1385 fusefs_remove(void *v) 1386 { 1387 struct vop_remove_args *ap = v; 1388 struct vnode *vp = ap->a_vp; 1389 struct vnode *dvp = ap->a_dvp; 1390 struct componentname *cnp = ap->a_cnp; 1391 struct proc *p = cnp->cn_proc; 1392 struct fusefs_node *ip; 1393 struct fusefs_node *dp; 1394 struct fusefs_mnt *fmp; 1395 struct fusebuf *fbuf; 1396 int error = 0; 1397 1398 ip = VTOI(vp); 1399 dp = VTOI(dvp); 1400 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1401 1402 if (!fmp->sess_init) { 1403 error = ENXIO; 1404 goto out; 1405 } 1406 1407 if (fmp->undef_op & UNDEF_REMOVE) { 1408 error = ENOSYS; 1409 goto out; 1410 } 1411 1412 fbuf = fb_setup(cnp->cn_namelen + 1, dp->ufs_ino.i_number, 1413 FBT_UNLINK, p); 1414 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1415 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1416 1417 error = fb_queue(fmp->dev, fbuf); 1418 if (error) { 1419 if (error == ENOSYS) 1420 fmp->undef_op |= UNDEF_REMOVE; 1421 1422 fb_delete(fbuf); 1423 goto out; 1424 } 1425 1426 VN_KNOTE(vp, NOTE_DELETE); 1427 VN_KNOTE(dvp, NOTE_WRITE); 1428 fb_delete(fbuf); 1429 out: 1430 if (dvp == vp) 1431 vrele(vp); 1432 else 1433 vput(vp); 1434 vput(dvp); 1435 return (error); 1436 } 1437 1438 int 1439 fusefs_strategy(void *v) 1440 { 1441 return (0); 1442 } 1443 1444 int 1445 fusefs_lock(void *v) 1446 { 1447 struct vop_lock_args *ap = v; 1448 struct vnode *vp = ap->a_vp; 1449 1450 return rrw_enter(&VTOI(vp)->ufs_ino.i_lock, ap->a_flags & LK_RWFLAGS); 1451 } 1452 1453 int 1454 fusefs_unlock(void *v) 1455 { 1456 struct vop_unlock_args *ap = v; 1457 struct vnode *vp = ap->a_vp; 1458 1459 rrw_exit(&VTOI(vp)->ufs_ino.i_lock); 1460 return 0; 1461 } 1462 1463 int 1464 fusefs_islocked(void *v) 1465 { 1466 struct vop_islocked_args *ap = v; 1467 1468 return rrw_status(&VTOI(ap->a_vp)->ufs_ino.i_lock); 1469 } 1470 1471 int 1472 fusefs_advlock(void *v) 1473 { 1474 struct vop_advlock_args *ap = v; 1475 struct fusefs_node *ip = VTOI(ap->a_vp); 1476 1477 return (lf_advlock(&ip->ufs_ino.i_lockf, ip->filesize, ap->a_id, 1478 ap->a_op, ap->a_fl, ap->a_flags)); 1479 } 1480