1 /* $OpenBSD: fuse_vnops.c,v 1.67 2023/09/08 20:00:28 mvs 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/pool.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_remove(void *); 60 int fusefs_rename(void *); 61 int fusefs_mkdir(void *); 62 int fusefs_rmdir(void *); 63 int fusefs_strategy(void *); 64 int fusefs_lock(void *); 65 int fusefs_unlock(void *); 66 int fusefs_islocked(void *); 67 int fusefs_advlock(void *); 68 int fusefs_fsync(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 const 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_kqfilter = fusefs_kqfilter, 89 .vop_revoke = NULL, 90 .vop_fsync = fusefs_fsync, 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 .vop_bwrite = NULL, 111 }; 112 113 const struct filterops fusefsread_filtops = { 114 .f_flags = FILTEROP_ISFD, 115 .f_attach = NULL, 116 .f_detach = filt_fusefsdetach, 117 .f_event = filt_fusefsread, 118 }; 119 120 const struct filterops fusefswrite_filtops = { 121 .f_flags = FILTEROP_ISFD, 122 .f_attach = NULL, 123 .f_detach = filt_fusefsdetach, 124 .f_event = filt_fusefswrite, 125 }; 126 127 const struct filterops fusefsvnode_filtops = { 128 .f_flags = FILTEROP_ISFD, 129 .f_attach = NULL, 130 .f_detach = filt_fusefsdetach, 131 .f_event = filt_fusefsvnode, 132 }; 133 134 int 135 fusefs_kqfilter(void *v) 136 { 137 struct vop_kqfilter_args *ap = v; 138 struct vnode *vp = ap->a_vp; 139 struct knote *kn = ap->a_kn; 140 141 switch (kn->kn_filter) { 142 case EVFILT_READ: 143 kn->kn_fop = &fusefsread_filtops; 144 break; 145 case EVFILT_WRITE: 146 kn->kn_fop = &fusefswrite_filtops; 147 break; 148 case EVFILT_VNODE: 149 kn->kn_fop = &fusefsvnode_filtops; 150 break; 151 default: 152 return (EINVAL); 153 } 154 155 kn->kn_hook = (caddr_t)vp; 156 157 klist_insert_locked(&vp->v_klist, kn); 158 159 return (0); 160 } 161 162 void 163 filt_fusefsdetach(struct knote *kn) 164 { 165 struct vnode *vp = (struct vnode *)kn->kn_hook; 166 167 klist_remove_locked(&vp->v_klist, kn); 168 } 169 170 int 171 filt_fusefsread(struct knote *kn, long hint) 172 { 173 struct vnode *vp = (struct vnode *)kn->kn_hook; 174 struct fusefs_node *ip = VTOI(vp); 175 176 /* 177 * filesystem is gone, so set the EOF flag and schedule 178 * the knote for deletion 179 */ 180 if (hint == NOTE_REVOKE) { 181 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 182 return (1); 183 } 184 185 kn->kn_data = ip->filesize - foffset(kn->kn_fp); 186 if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { 187 kn->kn_fflags |= NOTE_EOF; 188 return (1); 189 } 190 191 if (kn->kn_flags & (__EV_POLL | __EV_SELECT)) 192 return (1); 193 194 return (kn->kn_data != 0); 195 } 196 197 int 198 filt_fusefswrite(struct knote *kn, long hint) 199 { 200 /* 201 * filesystem is gone, so set the EOF flag and schedule 202 * the knote for deletion 203 */ 204 if (hint == NOTE_REVOKE) { 205 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 206 return (1); 207 } 208 209 kn->kn_data = 0; 210 return (1); 211 } 212 213 int 214 filt_fusefsvnode(struct knote *kn, long int hint) 215 { 216 if (kn->kn_sfflags & hint) 217 kn->kn_fflags |= hint; 218 if (hint == NOTE_REVOKE) { 219 kn->kn_flags |= EV_EOF; 220 return (1); 221 } 222 return (kn->kn_fflags != 0); 223 } 224 225 /* 226 * FUSE file systems can maintain a file handle for each VFS file descriptor 227 * that is opened. The OpenBSD VFS does not make file descriptors visible to 228 * us so we fake it by mapping open flags to file handles. 229 * There is no way for FUSE to know which file descriptor is being used 230 * by an application for a file operation. We only maintain 3 descriptors, 231 * one each for O_RDONLY, O_WRONLY and O_RDWR. When reading and writing, the 232 * first open descriptor is used and this may well not be the one that was set 233 * by FUSE open and may have even been opened by another application. 234 */ 235 int 236 fusefs_open(void *v) 237 { 238 struct vop_open_args *ap; 239 struct fusefs_node *ip; 240 struct fusefs_mnt *fmp; 241 struct vnode *vp; 242 enum fufh_type fufh_type = FUFH_RDONLY; 243 int flags; 244 int error; 245 int isdir; 246 247 ap = v; 248 vp = ap->a_vp; 249 ip = VTOI(vp); 250 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 251 252 if (!fmp->sess_init) 253 return (ENXIO); 254 255 isdir = 0; 256 if (vp->v_type == VDIR) 257 isdir = 1; 258 else { 259 if ((ap->a_mode & FREAD) && (ap->a_mode & FWRITE)) 260 fufh_type = FUFH_RDWR; 261 else if (ap->a_mode & (FWRITE)) 262 fufh_type = FUFH_WRONLY; 263 264 /* 265 * Due to possible attribute caching, there is no 266 * reliable way to determine if the file was modified 267 * externally (e.g. network file system) so clear the 268 * UVM cache to ensure that it is not stale. The file 269 * can still become stale later on read but this will 270 * satisfy most situations. 271 */ 272 uvm_vnp_uncache(vp); 273 } 274 275 /* already open i think all is ok */ 276 if (ip->fufh[fufh_type].fh_type != FUFH_INVALID) 277 return (0); 278 279 /* 280 * The file has already been created and/or truncated so FUSE dictates 281 * that no creation and truncation flags are passed to open. 282 */ 283 flags = OFLAGS(ap->a_mode) & ~(O_CREAT|O_EXCL|O_TRUNC); 284 error = fusefs_file_open(fmp, ip, fufh_type, flags, isdir, ap->a_p); 285 286 return (error); 287 } 288 289 int 290 fusefs_close(void *v) 291 { 292 struct vop_close_args *ap; 293 struct fusefs_node *ip; 294 struct fusefs_mnt *fmp; 295 struct fusebuf *fbuf; 296 enum fufh_type fufh_type = FUFH_RDONLY; 297 int error = 0; 298 299 ap = v; 300 ip = VTOI(ap->a_vp); 301 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 302 303 if (!fmp->sess_init) 304 return (0); 305 306 /* 307 * The file or directory may have been opened more than once so there 308 * is no reliable way to determine when to ask the FUSE daemon to 309 * release its file descriptor. For files, ask the daemon to flush any 310 * buffers to disk now. All open file descriptors will be released on 311 * VOP_INACTIVE(9). 312 */ 313 314 if (ap->a_vp->v_type == VDIR) 315 return (0); 316 317 /* Implementing flush is optional so don't error. */ 318 if (fmp->undef_op & UNDEF_FLUSH) 319 return (0); 320 321 /* Only flush writeable file descriptors. */ 322 if ((ap->a_fflag & FREAD) && (ap->a_fflag & FWRITE)) 323 fufh_type = FUFH_RDWR; 324 else if (ap->a_fflag & (FWRITE)) 325 fufh_type = FUFH_WRONLY; 326 else 327 return (0); 328 329 if (ip->fufh[fufh_type].fh_type == FUFH_INVALID) 330 return (EBADF); 331 332 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_FLUSH, ap->a_p); 333 fbuf->fb_io_fd = ip->fufh[fufh_type].fh_id; 334 error = fb_queue(fmp->dev, fbuf); 335 fb_delete(fbuf); 336 if (error == ENOSYS) { 337 fmp->undef_op |= UNDEF_FLUSH; 338 339 /* Implementing flush is optional so don't error. */ 340 return (0); 341 } 342 343 return (error); 344 } 345 346 int 347 fusefs_access(void *v) 348 { 349 struct vop_access_args *ap; 350 struct fusefs_node *ip; 351 struct fusefs_mnt *fmp; 352 struct ucred *cred; 353 struct vattr vattr; 354 struct proc *p; 355 int error = 0; 356 357 ap = v; 358 p = ap->a_p; 359 cred = p->p_ucred; 360 ip = VTOI(ap->a_vp); 361 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 362 363 /* 364 * Only user that mounted the file system can access it unless 365 * allow_other mount option was specified. 366 */ 367 if (!fmp->allow_other && cred->cr_uid != fmp->mp->mnt_stat.f_owner) 368 return (EACCES); 369 370 if (!fmp->sess_init) 371 return (ENXIO); 372 373 /* 374 * Disallow write attempts on filesystems mounted read-only; 375 * unless the file is a socket, fifo, or a block or character 376 * device resident on the filesystem. 377 */ 378 if ((ap->a_mode & VWRITE) && (fmp->mp->mnt_flag & MNT_RDONLY)) { 379 switch (ap->a_vp->v_type) { 380 case VREG: 381 case VDIR: 382 case VLNK: 383 return (EROFS); 384 default: 385 break; 386 } 387 } 388 389 if ((error = VOP_GETATTR(ap->a_vp, &vattr, cred, p)) != 0) 390 return (error); 391 392 return (vaccess(ap->a_vp->v_type, vattr.va_mode & ALLPERMS, 393 vattr.va_uid, vattr.va_gid, ap->a_mode, 394 ap->a_cred)); 395 } 396 397 int 398 fusefs_getattr(void *v) 399 { 400 struct vop_getattr_args *ap = v; 401 struct vnode *vp = ap->a_vp; 402 struct fusefs_mnt *fmp; 403 struct vattr *vap = ap->a_vap; 404 struct proc *p = ap->a_p; 405 struct ucred *cred = p->p_ucred; 406 struct fusefs_node *ip; 407 struct fusebuf *fbuf; 408 struct stat *st; 409 int error = 0; 410 411 ip = VTOI(vp); 412 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 413 414 /* 415 * Only user that mounted the file system can access it unless 416 * allow_other mount option was specified. Return dummy values 417 * for the root inode in this situation. 418 */ 419 if (!fmp->allow_other && cred->cr_uid != fmp->mp->mnt_stat.f_owner) { 420 memset(vap, 0, sizeof(*vap)); 421 vap->va_type = VNON; 422 if (vp->v_mount->mnt_flag & MNT_RDONLY) 423 vap->va_mode = S_IRUSR | S_IXUSR; 424 else 425 vap->va_mode = S_IRWXU; 426 vap->va_nlink = 1; 427 vap->va_uid = fmp->mp->mnt_stat.f_owner; 428 vap->va_gid = fmp->mp->mnt_stat.f_owner; 429 vap->va_fsid = fmp->mp->mnt_stat.f_fsid.val[0]; 430 vap->va_fileid = ip->ufs_ino.i_number; 431 vap->va_size = S_BLKSIZE; 432 vap->va_blocksize = S_BLKSIZE; 433 vap->va_atime.tv_sec = fmp->mp->mnt_stat.f_ctime; 434 vap->va_mtime.tv_sec = fmp->mp->mnt_stat.f_ctime; 435 vap->va_ctime.tv_sec = fmp->mp->mnt_stat.f_ctime; 436 vap->va_rdev = fmp->dev; 437 vap->va_bytes = S_BLKSIZE; 438 return (0); 439 } 440 441 if (!fmp->sess_init) 442 return (ENXIO); 443 444 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_GETATTR, p); 445 446 error = fb_queue(fmp->dev, fbuf); 447 if (error) { 448 fb_delete(fbuf); 449 return (error); 450 } 451 452 st = &fbuf->fb_attr; 453 454 memset(vap, 0, sizeof(*vap)); 455 vap->va_type = IFTOVT(st->st_mode); 456 vap->va_mode = st->st_mode & ~S_IFMT; 457 vap->va_nlink = st->st_nlink; 458 vap->va_uid = st->st_uid; 459 vap->va_gid = st->st_gid; 460 vap->va_fsid = fmp->mp->mnt_stat.f_fsid.val[0]; 461 vap->va_fileid = st->st_ino; 462 vap->va_size = st->st_size; 463 vap->va_blocksize = st->st_blksize; 464 vap->va_atime = st->st_atim; 465 vap->va_mtime = st->st_mtim; 466 vap->va_ctime = st->st_ctim; 467 vap->va_rdev = st->st_rdev; 468 vap->va_bytes = st->st_blocks * S_BLKSIZE; 469 470 fb_delete(fbuf); 471 return (error); 472 } 473 474 int 475 fusefs_setattr(void *v) 476 { 477 struct vop_setattr_args *ap = v; 478 struct vattr *vap = ap->a_vap; 479 struct vnode *vp = ap->a_vp; 480 struct fusefs_node *ip = VTOI(vp); 481 struct ucred *cred = ap->a_cred; 482 struct proc *p = ap->a_p; 483 struct fusefs_mnt *fmp; 484 struct fusebuf *fbuf; 485 struct fb_io *io; 486 int error = 0; 487 488 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 489 /* 490 * Check for unsettable attributes. 491 */ 492 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 493 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 494 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 495 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) 496 return (EINVAL); 497 498 if (!fmp->sess_init) 499 return (ENXIO); 500 501 if (fmp->undef_op & UNDEF_SETATTR) 502 return (ENOSYS); 503 504 fbuf = fb_setup(sizeof(*io), ip->ufs_ino.i_number, FBT_SETATTR, p); 505 io = fbtod(fbuf, struct fb_io *); 506 io->fi_flags = 0; 507 508 if (vap->va_uid != (uid_t)VNOVAL) { 509 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 510 error = EROFS; 511 goto out; 512 } 513 fbuf->fb_attr.st_uid = vap->va_uid; 514 io->fi_flags |= FUSE_FATTR_UID; 515 } 516 517 if (vap->va_gid != (gid_t)VNOVAL) { 518 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 519 error = EROFS; 520 goto out; 521 } 522 fbuf->fb_attr.st_gid = vap->va_gid; 523 io->fi_flags |= FUSE_FATTR_GID; 524 } 525 526 if (vap->va_size != VNOVAL) { 527 /* 528 * Disallow write attempts on read-only file systems; 529 * unless the file is a socket, fifo, or a block or 530 * character device resident on the file system. 531 */ 532 switch (vp->v_type) { 533 case VDIR: 534 error = EISDIR; 535 goto out; 536 case VLNK: 537 case VREG: 538 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 539 error = EROFS; 540 goto out; 541 } 542 break; 543 default: 544 break; 545 } 546 547 fbuf->fb_attr.st_size = vap->va_size; 548 io->fi_flags |= FUSE_FATTR_SIZE; 549 } 550 551 if (vap->va_atime.tv_nsec != VNOVAL) { 552 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 553 error = EROFS; 554 goto out; 555 } 556 fbuf->fb_attr.st_atim = vap->va_atime; 557 io->fi_flags |= FUSE_FATTR_ATIME; 558 } 559 560 if (vap->va_mtime.tv_nsec != VNOVAL) { 561 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 562 error = EROFS; 563 goto out; 564 } 565 fbuf->fb_attr.st_mtim = vap->va_mtime; 566 io->fi_flags |= FUSE_FATTR_MTIME; 567 } 568 /* XXX should set a flag if (vap->va_vaflags & VA_UTIMES_CHANGE) */ 569 570 if (vap->va_mode != (mode_t)VNOVAL) { 571 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 572 error = EROFS; 573 goto out; 574 } 575 576 /* 577 * chmod returns EFTYPE if the effective user ID is not the 578 * super-user, the mode includes the sticky bit (S_ISVTX), and 579 * path does not refer to a directory 580 */ 581 if (cred->cr_uid != 0 && vp->v_type != VDIR && 582 (vap->va_mode & S_ISTXT)) { 583 error = EFTYPE; 584 goto out; 585 } 586 587 fbuf->fb_attr.st_mode = vap->va_mode & ALLPERMS; 588 io->fi_flags |= FUSE_FATTR_MODE; 589 } 590 591 if (!io->fi_flags) { 592 goto out; 593 } 594 595 error = fb_queue(fmp->dev, fbuf); 596 if (error) { 597 if (error == ENOSYS) 598 fmp->undef_op |= UNDEF_SETATTR; 599 goto out; 600 } 601 602 /* truncate was successful, let uvm know */ 603 if (vap->va_size != VNOVAL && vap->va_size != ip->filesize) { 604 ip->filesize = vap->va_size; 605 uvm_vnp_setsize(vp, vap->va_size); 606 } 607 608 VN_KNOTE(ap->a_vp, NOTE_ATTRIB); 609 610 out: 611 fb_delete(fbuf); 612 return (error); 613 } 614 615 int 616 fusefs_ioctl(void *v) 617 { 618 return (ENOTTY); 619 } 620 621 int 622 fusefs_link(void *v) 623 { 624 struct vop_link_args *ap = v; 625 struct vnode *dvp = ap->a_dvp; 626 struct vnode *vp = ap->a_vp; 627 struct componentname *cnp = ap->a_cnp; 628 struct proc *p = cnp->cn_proc; 629 struct fusefs_mnt *fmp; 630 struct fusefs_node *ip; 631 struct fusefs_node *dip; 632 struct fusebuf *fbuf; 633 int error = 0; 634 635 ip = VTOI(vp); 636 dip = VTOI(dvp); 637 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 638 639 if (!fmp->sess_init) { 640 VOP_ABORTOP(dvp, cnp); 641 error = ENXIO; 642 goto out2; 643 } 644 if (fmp->undef_op & UNDEF_LINK) { 645 VOP_ABORTOP(dvp, cnp); 646 error = ENOSYS; 647 goto out2; 648 } 649 if (vp->v_type == VDIR) { 650 VOP_ABORTOP(dvp, cnp); 651 error = EPERM; 652 goto out2; 653 } 654 if (dvp->v_mount != vp->v_mount) { 655 VOP_ABORTOP(dvp, cnp); 656 error = EXDEV; 657 goto out2; 658 } 659 if (dvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE))) { 660 VOP_ABORTOP(dvp, cnp); 661 goto out2; 662 } 663 664 fbuf = fb_setup(cnp->cn_namelen + 1, dip->ufs_ino.i_number, 665 FBT_LINK, p); 666 667 fbuf->fb_io_ino = ip->ufs_ino.i_number; 668 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 669 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 670 671 error = fb_queue(fmp->dev, fbuf); 672 673 if (error) { 674 if (error == ENOSYS) 675 fmp->undef_op |= UNDEF_LINK; 676 677 fb_delete(fbuf); 678 goto out1; 679 } 680 681 fb_delete(fbuf); 682 VN_KNOTE(vp, NOTE_LINK); 683 VN_KNOTE(dvp, NOTE_WRITE); 684 685 out1: 686 pool_put(&namei_pool, cnp->cn_pnbuf); 687 if (dvp != vp) 688 VOP_UNLOCK(vp); 689 out2: 690 vput(dvp); 691 return (error); 692 } 693 694 int 695 fusefs_symlink(void *v) 696 { 697 struct vop_symlink_args *ap = v; 698 struct vnode **vpp = ap->a_vpp; 699 struct componentname *cnp = ap->a_cnp; 700 struct vnode *dvp = ap->a_dvp; 701 struct proc *p = cnp->cn_proc; 702 char *target = ap->a_target; 703 struct fusefs_node *dp; 704 struct fusefs_mnt *fmp; 705 struct fusebuf *fbuf; 706 struct vnode *tdp; 707 int error = 0; 708 int len; 709 710 dp = VTOI(dvp); 711 fmp = (struct fusefs_mnt *)dp->ufs_ino.i_ump; 712 713 if (!fmp->sess_init) { 714 error = ENXIO; 715 goto bad; 716 } 717 718 if (fmp->undef_op & UNDEF_SYMLINK) { 719 error = ENOSYS; 720 goto bad; 721 } 722 723 len = strlen(target) + 1; 724 725 fbuf = fb_setup(len + cnp->cn_namelen + 1, dp->ufs_ino.i_number, 726 FBT_SYMLINK, p); 727 728 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 729 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 730 memcpy(&fbuf->fb_dat[cnp->cn_namelen + 1], target, len); 731 732 error = fb_queue(fmp->dev, fbuf); 733 if (error) { 734 if (error == ENOSYS) 735 fmp->undef_op |= UNDEF_SYMLINK; 736 737 fb_delete(fbuf); 738 goto bad; 739 } 740 741 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) { 742 fb_delete(fbuf); 743 goto bad; 744 } 745 746 tdp->v_type = VLNK; 747 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 748 749 *vpp = tdp; 750 fb_delete(fbuf); 751 vput(tdp); 752 bad: 753 pool_put(&namei_pool, cnp->cn_pnbuf); 754 vput(dvp); 755 return (error); 756 } 757 758 int 759 fusefs_readdir(void *v) 760 { 761 struct vop_readdir_args *ap = v; 762 struct fusefs_node *ip; 763 struct fusefs_mnt *fmp; 764 struct fusebuf *fbuf; 765 struct vnode *vp; 766 struct proc *p; 767 struct uio *uio; 768 int error = 0, eofflag = 0, diropen = 0; 769 770 vp = ap->a_vp; 771 uio = ap->a_uio; 772 p = uio->uio_procp; 773 774 ip = VTOI(vp); 775 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 776 777 if (!fmp->sess_init) 778 return (ENXIO); 779 780 if (uio->uio_resid < sizeof(struct dirent)) 781 return (EINVAL); 782 783 if (ip->fufh[FUFH_RDONLY].fh_type == FUFH_INVALID) { 784 error = fusefs_file_open(fmp, ip, FUFH_RDONLY, O_RDONLY, 1, p); 785 if (error) 786 return (error); 787 788 diropen = 1; 789 } 790 791 while (uio->uio_resid > 0) { 792 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READDIR, p); 793 794 fbuf->fb_io_fd = ip->fufh[FUFH_RDONLY].fh_id; 795 fbuf->fb_io_off = uio->uio_offset; 796 fbuf->fb_io_len = MIN(uio->uio_resid, fmp->max_read); 797 798 error = fb_queue(fmp->dev, fbuf); 799 800 if (error) { 801 /* 802 * dirent was larger than residual space left in 803 * buffer. 804 */ 805 if (error == ENOBUFS) 806 error = 0; 807 808 fb_delete(fbuf); 809 break; 810 } 811 812 /* ack end of readdir */ 813 if (fbuf->fb_len == 0) { 814 eofflag = 1; 815 fb_delete(fbuf); 816 break; 817 } 818 819 if ((error = uiomove(fbuf->fb_dat, fbuf->fb_len, uio))) { 820 fb_delete(fbuf); 821 break; 822 } 823 824 fb_delete(fbuf); 825 } 826 827 if (!error && ap->a_eofflag != NULL) 828 *ap->a_eofflag = eofflag; 829 830 if (diropen) 831 fusefs_file_close(fmp, ip, FUFH_RDONLY, O_RDONLY, 1, p); 832 833 return (error); 834 } 835 836 int 837 fusefs_inactive(void *v) 838 { 839 struct vop_inactive_args *ap = v; 840 struct vnode *vp = ap->a_vp; 841 struct proc *p = ap->a_p; 842 struct fusefs_node *ip = VTOI(vp); 843 struct fusefs_filehandle *fufh = NULL; 844 struct fusefs_mnt *fmp; 845 int type, flags; 846 847 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 848 849 /* Close all open file handles. */ 850 for (type = 0; type < FUFH_MAXTYPE; type++) { 851 fufh = &(ip->fufh[type]); 852 if (fufh->fh_type != FUFH_INVALID) { 853 854 /* 855 * FUSE file systems expect the same flags to be sent 856 * on release that were sent on open. We don't have a 857 * record of them so make a best guess. 858 */ 859 switch (type) { 860 case FUFH_RDONLY: 861 flags = O_RDONLY; 862 break; 863 case FUFH_WRONLY: 864 flags = O_WRONLY; 865 break; 866 default: 867 flags = O_RDWR; 868 } 869 870 fusefs_file_close(fmp, ip, fufh->fh_type, flags, 871 (vp->v_type == VDIR), p); 872 } 873 } 874 875 VOP_UNLOCK(vp); 876 877 /* Don't return error to prevent kernel panic in vclean(9). */ 878 return (0); 879 } 880 881 int 882 fusefs_readlink(void *v) 883 { 884 struct vop_readlink_args *ap = v; 885 struct vnode *vp = ap->a_vp; 886 struct fusefs_node *ip; 887 struct fusefs_mnt *fmp; 888 struct fusebuf *fbuf; 889 struct uio *uio; 890 struct proc *p; 891 int error = 0; 892 893 ip = VTOI(vp); 894 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 895 uio = ap->a_uio; 896 p = uio->uio_procp; 897 898 if (!fmp->sess_init) 899 return (ENXIO); 900 901 if (fmp->undef_op & UNDEF_READLINK) 902 return (ENOSYS); 903 904 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READLINK, p); 905 906 error = fb_queue(fmp->dev, fbuf); 907 908 if (error) { 909 if (error == ENOSYS) 910 fmp->undef_op |= UNDEF_READLINK; 911 912 fb_delete(fbuf); 913 return (error); 914 } 915 916 error = uiomove(fbuf->fb_dat, fbuf->fb_len, uio); 917 fb_delete(fbuf); 918 919 return (error); 920 } 921 922 int 923 fusefs_reclaim(void *v) 924 { 925 struct vop_reclaim_args *ap = v; 926 struct vnode *vp = ap->a_vp; 927 struct proc *p = ap->a_p; 928 struct fusefs_node *ip = VTOI(vp); 929 struct fusefs_filehandle *fufh = NULL; 930 struct fusefs_mnt *fmp; 931 struct fusebuf *fbuf; 932 int type, error = 0; 933 934 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 935 936 /* Close opened files. */ 937 for (type = 0; type < FUFH_MAXTYPE; type++) { 938 fufh = &(ip->fufh[type]); 939 if (fufh->fh_type != FUFH_INVALID) { 940 printf("fusefs: vnode being reclaimed is valid\n"); 941 fusefs_file_close(fmp, ip, fufh->fh_type, type, 942 (vp->v_type == VDIR), ap->a_p); 943 } 944 } 945 946 /* 947 * If the fuse connection is opened ask libfuse to free the vnodes. 948 */ 949 if (fmp->sess_init && ip->ufs_ino.i_number != FUSE_ROOTINO) { 950 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_RECLAIM, p); 951 error = fb_queue(fmp->dev, fbuf); 952 if (error) 953 printf("fusefs: vnode reclaim failed: %d\n", error); 954 fb_delete(fbuf); 955 } 956 957 /* 958 * Remove the inode from its hash chain. 959 */ 960 ufs_ihashrem(&ip->ufs_ino); 961 962 free(ip, M_FUSEFS, sizeof(*ip)); 963 vp->v_data = NULL; 964 965 /* Must return success otherwise kernel panic in vclean(9). */ 966 return (0); 967 } 968 969 int 970 fusefs_print(void *v) 971 { 972 struct vop_print_args *ap = v; 973 struct vnode *vp = ap->a_vp; 974 struct fusefs_node *ip = VTOI(vp); 975 976 /* Complete the information given by vprint(). */ 977 printf("tag VT_FUSE, hash id %u ", ip->ufs_ino.i_number); 978 printf("\n"); 979 return (0); 980 } 981 982 int 983 fusefs_create(void *v) 984 { 985 struct vop_create_args *ap = v; 986 struct componentname *cnp = ap->a_cnp; 987 struct vnode **vpp = ap->a_vpp; 988 struct vnode *dvp = ap->a_dvp; 989 struct vattr *vap = ap->a_vap; 990 struct proc *p = cnp->cn_proc; 991 struct vnode *tdp = NULL; 992 struct fusefs_mnt *fmp; 993 struct fusefs_node *ip; 994 struct fusebuf *fbuf; 995 int error = 0; 996 mode_t mode; 997 998 ip = VTOI(dvp); 999 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1000 mode = MAKEIMODE(vap->va_type, vap->va_mode); 1001 1002 if (!fmp->sess_init) { 1003 VOP_ABORTOP(dvp, cnp); 1004 return (ENXIO); 1005 } 1006 1007 if (fmp->undef_op & UNDEF_MKNOD) { 1008 VOP_ABORTOP(dvp, cnp); 1009 return (ENOSYS); 1010 } 1011 1012 fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number, 1013 FBT_MKNOD, p); 1014 1015 fbuf->fb_io_mode = mode; 1016 1017 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1018 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1019 1020 error = fb_queue(fmp->dev, fbuf); 1021 if (error) { 1022 if (error == ENOSYS) 1023 fmp->undef_op |= UNDEF_MKNOD; 1024 1025 goto out; 1026 } 1027 1028 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) 1029 goto out; 1030 1031 tdp->v_type = IFTOVT(fbuf->fb_io_mode); 1032 1033 *vpp = tdp; 1034 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 1035 out: 1036 fb_delete(fbuf); 1037 pool_put(&namei_pool, cnp->cn_pnbuf); 1038 return (error); 1039 } 1040 1041 int 1042 fusefs_mknod(void *v) 1043 { 1044 struct vop_mknod_args *ap = v; 1045 struct componentname *cnp = ap->a_cnp; 1046 struct vnode **vpp = ap->a_vpp; 1047 struct vnode *dvp = ap->a_dvp; 1048 struct vattr *vap = ap->a_vap; 1049 struct proc *p = cnp->cn_proc; 1050 struct vnode *tdp = NULL; 1051 struct fusefs_mnt *fmp; 1052 struct fusefs_node *ip; 1053 struct fusebuf *fbuf; 1054 int error = 0; 1055 1056 ip = VTOI(dvp); 1057 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1058 1059 if (!fmp->sess_init) { 1060 VOP_ABORTOP(dvp, cnp); 1061 return (ENXIO); 1062 } 1063 1064 if (fmp->undef_op & UNDEF_MKNOD) { 1065 VOP_ABORTOP(dvp, cnp); 1066 return (ENOSYS); 1067 } 1068 1069 fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number, 1070 FBT_MKNOD, p); 1071 1072 fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode); 1073 if (vap->va_rdev != VNOVAL) 1074 fbuf->fb_io_rdev = vap->va_rdev; 1075 1076 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1077 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1078 1079 error = fb_queue(fmp->dev, fbuf); 1080 if (error) { 1081 if (error == ENOSYS) 1082 fmp->undef_op |= UNDEF_MKNOD; 1083 1084 goto out; 1085 } 1086 1087 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) 1088 goto out; 1089 1090 tdp->v_type = IFTOVT(fbuf->fb_io_mode); 1091 1092 *vpp = tdp; 1093 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 1094 1095 /* Remove inode so that it will be reloaded by VFS_VGET and 1096 * checked to see if it is an alias of an existing entry in 1097 * the inode cache. 1098 */ 1099 vput(*vpp); 1100 (*vpp)->v_type = VNON; 1101 vgone(*vpp); 1102 *vpp = NULL; 1103 out: 1104 fb_delete(fbuf); 1105 pool_put(&namei_pool, cnp->cn_pnbuf); 1106 return (error); 1107 } 1108 1109 int 1110 fusefs_read(void *v) 1111 { 1112 struct vop_read_args *ap = v; 1113 struct vnode *vp = ap->a_vp; 1114 struct uio *uio = ap->a_uio; 1115 struct proc *p = uio->uio_procp; 1116 struct fusefs_node *ip; 1117 struct fusefs_mnt *fmp; 1118 struct fusebuf *fbuf = NULL; 1119 size_t size; 1120 int error=0; 1121 1122 ip = VTOI(vp); 1123 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1124 1125 if (!fmp->sess_init) 1126 return (ENXIO); 1127 if (uio->uio_resid == 0) 1128 return (error); 1129 if (uio->uio_offset < 0) 1130 return (EINVAL); 1131 1132 while (uio->uio_resid > 0) { 1133 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READ, p); 1134 1135 size = MIN(uio->uio_resid, fmp->max_read); 1136 fbuf->fb_io_fd = fusefs_fd_get(ip, FUFH_RDONLY); 1137 fbuf->fb_io_off = uio->uio_offset; 1138 fbuf->fb_io_len = size; 1139 1140 error = fb_queue(fmp->dev, fbuf); 1141 1142 if (error) 1143 break; 1144 1145 error = uiomove(fbuf->fb_dat, ulmin(size, fbuf->fb_len), uio); 1146 if (error) 1147 break; 1148 1149 if (fbuf->fb_len < size) 1150 break; 1151 1152 fb_delete(fbuf); 1153 fbuf = NULL; 1154 } 1155 1156 fb_delete(fbuf); 1157 return (error); 1158 } 1159 1160 int 1161 fusefs_write(void *v) 1162 { 1163 struct vop_write_args *ap = v; 1164 struct vnode *vp = ap->a_vp; 1165 struct uio *uio = ap->a_uio; 1166 struct proc *p = uio->uio_procp; 1167 struct ucred *cred = p->p_ucred; 1168 struct vattr vattr; 1169 int ioflag = ap->a_ioflag; 1170 struct fusefs_node *ip; 1171 struct fusefs_mnt *fmp; 1172 struct fusebuf *fbuf = NULL; 1173 size_t len, diff; 1174 int error=0; 1175 1176 ip = VTOI(vp); 1177 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1178 1179 if (!fmp->sess_init) 1180 return (ENXIO); 1181 if (uio->uio_resid == 0) 1182 return (error); 1183 1184 if (ioflag & IO_APPEND) { 1185 if ((error = VOP_GETATTR(vp, &vattr, cred, p)) != 0) 1186 return (error); 1187 1188 uio->uio_offset = vattr.va_size; 1189 } 1190 1191 while (uio->uio_resid > 0) { 1192 len = MIN(uio->uio_resid, fmp->max_read); 1193 fbuf = fb_setup(len, ip->ufs_ino.i_number, FBT_WRITE, p); 1194 1195 fbuf->fb_io_fd = fusefs_fd_get(ip, FUFH_WRONLY); 1196 fbuf->fb_io_off = uio->uio_offset; 1197 fbuf->fb_io_len = len; 1198 1199 if ((error = uiomove(fbuf->fb_dat, len, uio))) { 1200 printf("fusefs: uio error %i\n", error); 1201 break; 1202 } 1203 1204 error = fb_queue(fmp->dev, fbuf); 1205 1206 if (error) 1207 break; 1208 1209 diff = len - fbuf->fb_io_len; 1210 if (fbuf->fb_io_len > len) { 1211 error = EINVAL; 1212 break; 1213 } 1214 1215 uio->uio_resid += diff; 1216 uio->uio_offset -= diff; 1217 1218 if (uio->uio_offset > ip->filesize) { 1219 ip->filesize = uio->uio_offset; 1220 uvm_vnp_setsize(vp, uio->uio_offset); 1221 } 1222 uvm_vnp_uncache(vp); 1223 1224 fb_delete(fbuf); 1225 fbuf = NULL; 1226 } 1227 1228 fb_delete(fbuf); 1229 return (error); 1230 } 1231 1232 int 1233 fusefs_rename(void *v) 1234 { 1235 struct vop_rename_args *ap = v; 1236 struct vnode *tvp = ap->a_tvp; 1237 struct vnode *tdvp = ap->a_tdvp; 1238 struct vnode *fvp = ap->a_fvp; 1239 struct vnode *fdvp = ap->a_fdvp; 1240 struct componentname *tcnp = ap->a_tcnp; 1241 struct componentname *fcnp = ap->a_fcnp; 1242 struct proc *p = fcnp->cn_proc; 1243 struct fusefs_node *ip, *dp; 1244 struct fusefs_mnt *fmp; 1245 struct fusebuf *fbuf; 1246 int error = 0; 1247 1248 #ifdef DIAGNOSTIC 1249 if ((tcnp->cn_flags & HASBUF) == 0 || 1250 (fcnp->cn_flags & HASBUF) == 0) 1251 panic("fusefs_rename: no name"); 1252 #endif 1253 /* 1254 * Check for cross-device rename. 1255 */ 1256 if ((fvp->v_mount != tdvp->v_mount) || 1257 (tvp && (fvp->v_mount != tvp->v_mount))) { 1258 error = EXDEV; 1259 abortit: 1260 VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */ 1261 if (tdvp == tvp) 1262 vrele(tdvp); 1263 else 1264 vput(tdvp); 1265 if (tvp) 1266 vput(tvp); 1267 VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */ 1268 vrele(fdvp); 1269 vrele(fvp); 1270 return (error); 1271 } 1272 1273 /* 1274 * If source and dest are the same, do nothing. 1275 */ 1276 if (tvp == fvp) { 1277 error = 0; 1278 goto abortit; 1279 } 1280 1281 if ((error = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY)) != 0) 1282 goto abortit; 1283 dp = VTOI(fdvp); 1284 ip = VTOI(fvp); 1285 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1286 1287 /* 1288 * Be sure we are not renaming ".", "..", or an alias of ".". This 1289 * leads to a crippled directory tree. It's pretty tough to do a 1290 * "ls" or "pwd" with the "." directory entry missing, and "cd .." 1291 * doesn't work if the ".." entry is missing. 1292 */ 1293 if (fvp->v_type == VDIR) { 1294 /* 1295 * Avoid ".", "..", and aliases of "." for obvious reasons. 1296 */ 1297 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || 1298 dp == ip || 1299 (fcnp->cn_flags & ISDOTDOT) || 1300 (tcnp->cn_flags & ISDOTDOT)) { 1301 VOP_UNLOCK(fvp); 1302 error = EINVAL; 1303 goto abortit; 1304 } 1305 } 1306 VN_KNOTE(fdvp, NOTE_WRITE); /* XXX right place? */ 1307 1308 if (!fmp->sess_init) { 1309 error = ENXIO; 1310 VOP_UNLOCK(fvp); 1311 goto abortit; 1312 } 1313 1314 if (fmp->undef_op & UNDEF_RENAME) { 1315 error = ENOSYS; 1316 VOP_UNLOCK(fvp); 1317 goto abortit; 1318 } 1319 1320 fbuf = fb_setup(fcnp->cn_namelen + tcnp->cn_namelen + 2, 1321 dp->ufs_ino.i_number, FBT_RENAME, p); 1322 1323 memcpy(fbuf->fb_dat, fcnp->cn_nameptr, fcnp->cn_namelen); 1324 fbuf->fb_dat[fcnp->cn_namelen] = '\0'; 1325 memcpy(fbuf->fb_dat + fcnp->cn_namelen + 1, tcnp->cn_nameptr, 1326 tcnp->cn_namelen); 1327 fbuf->fb_dat[fcnp->cn_namelen + tcnp->cn_namelen + 1] = '\0'; 1328 fbuf->fb_io_ino = VTOI(tdvp)->ufs_ino.i_number; 1329 1330 error = fb_queue(fmp->dev, fbuf); 1331 1332 if (error) { 1333 if (error == ENOSYS) { 1334 fmp->undef_op |= UNDEF_RENAME; 1335 } 1336 1337 fb_delete(fbuf); 1338 VOP_UNLOCK(fvp); 1339 goto abortit; 1340 } 1341 1342 fb_delete(fbuf); 1343 VN_KNOTE(fvp, NOTE_RENAME); 1344 1345 VOP_UNLOCK(fvp); 1346 if (tdvp == tvp) 1347 vrele(tdvp); 1348 else 1349 vput(tdvp); 1350 if (tvp) 1351 vput(tvp); 1352 vrele(fdvp); 1353 vrele(fvp); 1354 1355 return (error); 1356 } 1357 1358 int 1359 fusefs_mkdir(void *v) 1360 { 1361 struct vop_mkdir_args *ap = v; 1362 struct vnode *dvp = ap->a_dvp; 1363 struct vnode **vpp = ap->a_vpp; 1364 struct componentname *cnp = ap->a_cnp; 1365 struct vattr *vap = ap->a_vap; 1366 struct proc *p = cnp->cn_proc; 1367 struct vnode *tdp = NULL; 1368 struct fusefs_node *ip; 1369 struct fusefs_mnt *fmp; 1370 struct fusebuf *fbuf; 1371 int error = 0; 1372 1373 ip = VTOI(dvp); 1374 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1375 1376 1377 if (!fmp->sess_init) { 1378 error = ENXIO; 1379 goto out; 1380 } 1381 1382 if (fmp->undef_op & UNDEF_MKDIR) { 1383 error = ENOSYS; 1384 goto out; 1385 } 1386 1387 fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number, 1388 FBT_MKDIR, p); 1389 1390 fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode); 1391 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1392 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1393 1394 error = fb_queue(fmp->dev, fbuf); 1395 if (error) { 1396 if (error == ENOSYS) 1397 fmp->undef_op |= UNDEF_MKDIR; 1398 1399 fb_delete(fbuf); 1400 goto out; 1401 } 1402 1403 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) { 1404 fb_delete(fbuf); 1405 goto out; 1406 } 1407 1408 tdp->v_type = IFTOVT(fbuf->fb_io_mode); 1409 1410 *vpp = tdp; 1411 VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK); 1412 fb_delete(fbuf); 1413 out: 1414 pool_put(&namei_pool, cnp->cn_pnbuf); 1415 vput(dvp); 1416 return (error); 1417 } 1418 1419 int 1420 fusefs_rmdir(void *v) 1421 { 1422 struct vop_rmdir_args *ap = v; 1423 struct vnode *vp = ap->a_vp; 1424 struct vnode *dvp = ap->a_dvp; 1425 struct componentname *cnp = ap->a_cnp; 1426 struct proc *p = cnp->cn_proc; 1427 struct fusefs_node *ip, *dp; 1428 struct fusefs_mnt *fmp; 1429 struct fusebuf *fbuf; 1430 int error; 1431 1432 ip = VTOI(vp); 1433 dp = VTOI(dvp); 1434 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1435 1436 if (!fmp->sess_init) { 1437 error = ENXIO; 1438 goto out; 1439 } 1440 1441 if (fmp->undef_op & UNDEF_RMDIR) { 1442 error = ENOSYS; 1443 goto out; 1444 } 1445 1446 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); 1447 1448 fbuf = fb_setup(cnp->cn_namelen + 1, dp->ufs_ino.i_number, 1449 FBT_RMDIR, p); 1450 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1451 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1452 1453 error = fb_queue(fmp->dev, fbuf); 1454 1455 if (error) { 1456 if (error == ENOSYS) 1457 fmp->undef_op |= UNDEF_RMDIR; 1458 if (error != ENOTEMPTY) 1459 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); 1460 1461 fb_delete(fbuf); 1462 goto out; 1463 } 1464 1465 vput(dvp); 1466 dvp = NULL; 1467 1468 fb_delete(fbuf); 1469 out: 1470 if (dvp) 1471 vput(dvp); 1472 VN_KNOTE(vp, NOTE_DELETE); 1473 pool_put(&namei_pool, cnp->cn_pnbuf); 1474 vput(vp); 1475 return (error); 1476 } 1477 1478 int 1479 fusefs_remove(void *v) 1480 { 1481 struct vop_remove_args *ap = v; 1482 struct vnode *vp = ap->a_vp; 1483 struct vnode *dvp = ap->a_dvp; 1484 struct componentname *cnp = ap->a_cnp; 1485 struct proc *p = cnp->cn_proc; 1486 struct fusefs_node *ip; 1487 struct fusefs_node *dp; 1488 struct fusefs_mnt *fmp; 1489 struct fusebuf *fbuf; 1490 int error = 0; 1491 1492 ip = VTOI(vp); 1493 dp = VTOI(dvp); 1494 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1495 1496 if (!fmp->sess_init) { 1497 error = ENXIO; 1498 goto out; 1499 } 1500 1501 if (fmp->undef_op & UNDEF_REMOVE) { 1502 error = ENOSYS; 1503 goto out; 1504 } 1505 1506 fbuf = fb_setup(cnp->cn_namelen + 1, dp->ufs_ino.i_number, 1507 FBT_UNLINK, p); 1508 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1509 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1510 1511 error = fb_queue(fmp->dev, fbuf); 1512 if (error) { 1513 if (error == ENOSYS) 1514 fmp->undef_op |= UNDEF_REMOVE; 1515 1516 fb_delete(fbuf); 1517 goto out; 1518 } 1519 1520 VN_KNOTE(vp, NOTE_DELETE); 1521 VN_KNOTE(dvp, NOTE_WRITE); 1522 fb_delete(fbuf); 1523 out: 1524 pool_put(&namei_pool, cnp->cn_pnbuf); 1525 if (dvp == vp) 1526 vrele(vp); 1527 else 1528 vput(vp); 1529 vput(dvp); 1530 return (error); 1531 } 1532 1533 int 1534 fusefs_strategy(void *v) 1535 { 1536 return (0); 1537 } 1538 1539 int 1540 fusefs_lock(void *v) 1541 { 1542 struct vop_lock_args *ap = v; 1543 struct vnode *vp = ap->a_vp; 1544 1545 return rrw_enter(&VTOI(vp)->ufs_ino.i_lock, ap->a_flags & LK_RWFLAGS); 1546 } 1547 1548 int 1549 fusefs_unlock(void *v) 1550 { 1551 struct vop_unlock_args *ap = v; 1552 struct vnode *vp = ap->a_vp; 1553 1554 rrw_exit(&VTOI(vp)->ufs_ino.i_lock); 1555 return 0; 1556 } 1557 1558 int 1559 fusefs_islocked(void *v) 1560 { 1561 struct vop_islocked_args *ap = v; 1562 1563 return rrw_status(&VTOI(ap->a_vp)->ufs_ino.i_lock); 1564 } 1565 1566 int 1567 fusefs_advlock(void *v) 1568 { 1569 struct vop_advlock_args *ap = v; 1570 struct fusefs_node *ip = VTOI(ap->a_vp); 1571 1572 return (lf_advlock(&ip->ufs_ino.i_lockf, ip->filesize, ap->a_id, 1573 ap->a_op, ap->a_fl, ap->a_flags)); 1574 } 1575 1576 int 1577 fusefs_fsync(void *v) 1578 { 1579 struct vop_fsync_args *ap = v; 1580 struct vnode *vp = ap->a_vp; 1581 struct proc *p = ap->a_p; 1582 struct fusefs_node *ip; 1583 struct fusefs_mnt *fmp; 1584 struct fusefs_filehandle *fufh; 1585 struct fusebuf *fbuf; 1586 int type, error = 0; 1587 1588 /* 1589 * Can't write to directory file handles so no need to fsync. 1590 * FUSE has fsyncdir but it doesn't make sense on OpenBSD. 1591 */ 1592 if (vp->v_type == VDIR) 1593 return (0); 1594 1595 ip = VTOI(vp); 1596 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1597 1598 if (!fmp->sess_init) 1599 return (ENXIO); 1600 1601 /* Implementing fsync is optional so don't error. */ 1602 if (fmp->undef_op & UNDEF_FSYNC) 1603 return (0); 1604 1605 /* Sync all writeable file descriptors. */ 1606 for (type = 0; type < FUFH_MAXTYPE; type++) { 1607 fufh = &(ip->fufh[type]); 1608 if (fufh->fh_type == FUFH_WRONLY || 1609 fufh->fh_type == FUFH_RDWR) { 1610 1611 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_FSYNC, p); 1612 fbuf->fb_io_fd = fufh->fh_id; 1613 1614 /* Always behave as if ap->a_waitfor = MNT_WAIT. */ 1615 error = fb_queue(fmp->dev, fbuf); 1616 fb_delete(fbuf); 1617 if (error) 1618 break; 1619 } 1620 } 1621 1622 if (error == ENOSYS) { 1623 fmp->undef_op |= UNDEF_FSYNC; 1624 1625 /* Implementing fsync is optional so don't error. */ 1626 return (0); 1627 } 1628 1629 return (error); 1630 } 1631