1 /* $OpenBSD: fuse_vnops.c,v 1.61 2020/06/11 09:18:43 mpi 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 int fusefs_fsync(void *); 70 71 /* Prototypes for fusefs kqfilter */ 72 int filt_fusefsread(struct knote *, long); 73 int filt_fusefswrite(struct knote *, long); 74 int filt_fusefsvnode(struct knote *, long); 75 void filt_fusefsdetach(struct knote *); 76 77 const struct vops fusefs_vops = { 78 .vop_lookup = fusefs_lookup, 79 .vop_create = fusefs_create, 80 .vop_mknod = fusefs_mknod, 81 .vop_open = fusefs_open, 82 .vop_close = fusefs_close, 83 .vop_access = fusefs_access, 84 .vop_getattr = fusefs_getattr, 85 .vop_setattr = fusefs_setattr, 86 .vop_read = fusefs_read, 87 .vop_write = fusefs_write, 88 .vop_ioctl = fusefs_ioctl, 89 .vop_poll = fusefs_poll, 90 .vop_kqfilter = fusefs_kqfilter, 91 .vop_fsync = fusefs_fsync, 92 .vop_remove = fusefs_remove, 93 .vop_link = fusefs_link, 94 .vop_rename = fusefs_rename, 95 .vop_mkdir = fusefs_mkdir, 96 .vop_rmdir = fusefs_rmdir, 97 .vop_symlink = fusefs_symlink, 98 .vop_readdir = fusefs_readdir, 99 .vop_readlink = fusefs_readlink, 100 .vop_abortop = vop_generic_abortop, 101 .vop_inactive = fusefs_inactive, 102 .vop_reclaim = fusefs_reclaim, 103 .vop_lock = fusefs_lock, 104 .vop_unlock = fusefs_unlock, 105 .vop_bmap = vop_generic_bmap, 106 .vop_strategy = fusefs_strategy, 107 .vop_print = fusefs_print, 108 .vop_islocked = fusefs_islocked, 109 .vop_pathconf = spec_pathconf, 110 .vop_advlock = fusefs_advlock, 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(&vp->v_selectinfo.si_note, 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(&vp->v_selectinfo.si_note, 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) 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 if (dvp != vp) 687 VOP_UNLOCK(vp); 688 out2: 689 vput(dvp); 690 return (error); 691 } 692 693 int 694 fusefs_symlink(void *v) 695 { 696 struct vop_symlink_args *ap = v; 697 struct vnode **vpp = ap->a_vpp; 698 struct componentname *cnp = ap->a_cnp; 699 struct vnode *dvp = ap->a_dvp; 700 struct proc *p = cnp->cn_proc; 701 char *target = ap->a_target; 702 struct fusefs_node *dp; 703 struct fusefs_mnt *fmp; 704 struct fusebuf *fbuf; 705 struct vnode *tdp; 706 int error = 0; 707 int len; 708 709 dp = VTOI(dvp); 710 fmp = (struct fusefs_mnt *)dp->ufs_ino.i_ump; 711 712 if (!fmp->sess_init) { 713 error = ENXIO; 714 goto bad; 715 } 716 717 if (fmp->undef_op & UNDEF_SYMLINK) { 718 error = ENOSYS; 719 goto bad; 720 } 721 722 len = strlen(target) + 1; 723 724 fbuf = fb_setup(len + cnp->cn_namelen + 1, dp->ufs_ino.i_number, 725 FBT_SYMLINK, p); 726 727 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 728 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 729 memcpy(&fbuf->fb_dat[cnp->cn_namelen + 1], target, len); 730 731 error = fb_queue(fmp->dev, fbuf); 732 if (error) { 733 if (error == ENOSYS) 734 fmp->undef_op |= UNDEF_SYMLINK; 735 736 fb_delete(fbuf); 737 goto bad; 738 } 739 740 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) { 741 fb_delete(fbuf); 742 goto bad; 743 } 744 745 tdp->v_type = VLNK; 746 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 747 748 *vpp = tdp; 749 fb_delete(fbuf); 750 vput(tdp); 751 bad: 752 vput(dvp); 753 return (error); 754 } 755 756 int 757 fusefs_readdir(void *v) 758 { 759 struct vop_readdir_args *ap = v; 760 struct fusefs_node *ip; 761 struct fusefs_mnt *fmp; 762 struct fusebuf *fbuf; 763 struct vnode *vp; 764 struct proc *p; 765 struct uio *uio; 766 int error = 0, eofflag = 0, diropen = 0; 767 768 vp = ap->a_vp; 769 uio = ap->a_uio; 770 p = uio->uio_procp; 771 772 ip = VTOI(vp); 773 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 774 775 if (!fmp->sess_init) 776 return (ENXIO); 777 778 if (uio->uio_resid < sizeof(struct dirent)) 779 return (EINVAL); 780 781 if (ip->fufh[FUFH_RDONLY].fh_type == FUFH_INVALID) { 782 error = fusefs_file_open(fmp, ip, FUFH_RDONLY, O_RDONLY, 1, p); 783 if (error) 784 return (error); 785 786 diropen = 1; 787 } 788 789 while (uio->uio_resid > 0) { 790 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READDIR, p); 791 792 fbuf->fb_io_fd = ip->fufh[FUFH_RDONLY].fh_id; 793 fbuf->fb_io_off = uio->uio_offset; 794 fbuf->fb_io_len = MIN(uio->uio_resid, fmp->max_read); 795 796 error = fb_queue(fmp->dev, fbuf); 797 798 if (error) { 799 /* 800 * dirent was larger than residual space left in 801 * buffer. 802 */ 803 if (error == ENOBUFS) 804 error = 0; 805 806 fb_delete(fbuf); 807 break; 808 } 809 810 /* ack end of readdir */ 811 if (fbuf->fb_len == 0) { 812 eofflag = 1; 813 fb_delete(fbuf); 814 break; 815 } 816 817 if ((error = uiomove(fbuf->fb_dat, fbuf->fb_len, uio))) { 818 fb_delete(fbuf); 819 break; 820 } 821 822 fb_delete(fbuf); 823 } 824 825 if (!error && ap->a_eofflag != NULL) 826 *ap->a_eofflag = eofflag; 827 828 if (diropen) 829 fusefs_file_close(fmp, ip, FUFH_RDONLY, O_RDONLY, 1, p); 830 831 return (error); 832 } 833 834 int 835 fusefs_inactive(void *v) 836 { 837 struct vop_inactive_args *ap = v; 838 struct vnode *vp = ap->a_vp; 839 struct proc *p = ap->a_p; 840 struct fusefs_node *ip = VTOI(vp); 841 struct fusefs_filehandle *fufh = NULL; 842 struct fusefs_mnt *fmp; 843 int type, flags; 844 845 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 846 847 /* Close all open file handles. */ 848 for (type = 0; type < FUFH_MAXTYPE; type++) { 849 fufh = &(ip->fufh[type]); 850 if (fufh->fh_type != FUFH_INVALID) { 851 852 /* 853 * FUSE file systems expect the same flags to be sent 854 * on release that were sent on open. We don't have a 855 * record of them so make a best guess. 856 */ 857 switch (type) { 858 case FUFH_RDONLY: 859 flags = O_RDONLY; 860 break; 861 case FUFH_WRONLY: 862 flags = O_WRONLY; 863 break; 864 default: 865 flags = O_RDWR; 866 } 867 868 fusefs_file_close(fmp, ip, fufh->fh_type, flags, 869 (vp->v_type == VDIR), p); 870 } 871 } 872 873 VOP_UNLOCK(vp); 874 875 /* Don't return error to prevent kernel panic in vclean(9). */ 876 return (0); 877 } 878 879 int 880 fusefs_readlink(void *v) 881 { 882 struct vop_readlink_args *ap = v; 883 struct vnode *vp = ap->a_vp; 884 struct fusefs_node *ip; 885 struct fusefs_mnt *fmp; 886 struct fusebuf *fbuf; 887 struct uio *uio; 888 struct proc *p; 889 int error = 0; 890 891 ip = VTOI(vp); 892 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 893 uio = ap->a_uio; 894 p = uio->uio_procp; 895 896 if (!fmp->sess_init) 897 return (ENXIO); 898 899 if (fmp->undef_op & UNDEF_READLINK) 900 return (ENOSYS); 901 902 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READLINK, p); 903 904 error = fb_queue(fmp->dev, fbuf); 905 906 if (error) { 907 if (error == ENOSYS) 908 fmp->undef_op |= UNDEF_READLINK; 909 910 fb_delete(fbuf); 911 return (error); 912 } 913 914 error = uiomove(fbuf->fb_dat, fbuf->fb_len, uio); 915 fb_delete(fbuf); 916 917 return (error); 918 } 919 920 int 921 fusefs_reclaim(void *v) 922 { 923 struct vop_reclaim_args *ap = v; 924 struct vnode *vp = ap->a_vp; 925 struct proc *p = ap->a_p; 926 struct fusefs_node *ip = VTOI(vp); 927 struct fusefs_filehandle *fufh = NULL; 928 struct fusefs_mnt *fmp; 929 struct fusebuf *fbuf; 930 int type, error = 0; 931 932 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 933 934 /* Close opened files. */ 935 for (type = 0; type < FUFH_MAXTYPE; type++) { 936 fufh = &(ip->fufh[type]); 937 if (fufh->fh_type != FUFH_INVALID) { 938 printf("fusefs: vnode being reclaimed is valid\n"); 939 fusefs_file_close(fmp, ip, fufh->fh_type, type, 940 (vp->v_type == VDIR), ap->a_p); 941 } 942 } 943 944 /* 945 * If the fuse connection is opened ask libfuse to free the vnodes. 946 */ 947 if (fmp->sess_init && ip->ufs_ino.i_number != FUSE_ROOTINO) { 948 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_RECLAIM, p); 949 error = fb_queue(fmp->dev, fbuf); 950 if (error) 951 printf("fusefs: vnode reclaim failed: %d\n", error); 952 fb_delete(fbuf); 953 } 954 955 /* 956 * Remove the inode from its hash chain. 957 */ 958 ufs_ihashrem(&ip->ufs_ino); 959 960 free(ip, M_FUSEFS, sizeof(*ip)); 961 vp->v_data = NULL; 962 963 /* Must return success otherwise kernel panic in vclean(9). */ 964 return (0); 965 } 966 967 int 968 fusefs_print(void *v) 969 { 970 struct vop_print_args *ap = v; 971 struct vnode *vp = ap->a_vp; 972 struct fusefs_node *ip = VTOI(vp); 973 974 /* Complete the information given by vprint(). */ 975 printf("tag VT_FUSE, hash id %u ", ip->ufs_ino.i_number); 976 printf("\n"); 977 return (0); 978 } 979 980 int 981 fusefs_create(void *v) 982 { 983 struct vop_create_args *ap = v; 984 struct componentname *cnp = ap->a_cnp; 985 struct vnode **vpp = ap->a_vpp; 986 struct vnode *dvp = ap->a_dvp; 987 struct vattr *vap = ap->a_vap; 988 struct proc *p = cnp->cn_proc; 989 struct vnode *tdp = NULL; 990 struct fusefs_mnt *fmp; 991 struct fusefs_node *ip; 992 struct fusebuf *fbuf; 993 int error = 0; 994 mode_t mode; 995 996 ip = VTOI(dvp); 997 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 998 mode = MAKEIMODE(vap->va_type, vap->va_mode); 999 1000 if (!fmp->sess_init) 1001 return (ENXIO); 1002 1003 if (fmp->undef_op & UNDEF_MKNOD) 1004 return (ENOSYS); 1005 1006 fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number, 1007 FBT_MKNOD, p); 1008 1009 fbuf->fb_io_mode = mode; 1010 1011 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1012 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1013 1014 error = fb_queue(fmp->dev, fbuf); 1015 if (error) { 1016 if (error == ENOSYS) 1017 fmp->undef_op |= UNDEF_MKNOD; 1018 1019 goto out; 1020 } 1021 1022 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) 1023 goto out; 1024 1025 tdp->v_type = IFTOVT(fbuf->fb_io_mode); 1026 1027 *vpp = tdp; 1028 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 1029 out: 1030 fb_delete(fbuf); 1031 return (error); 1032 } 1033 1034 int 1035 fusefs_mknod(void *v) 1036 { 1037 struct vop_mknod_args *ap = v; 1038 struct componentname *cnp = ap->a_cnp; 1039 struct vnode **vpp = ap->a_vpp; 1040 struct vnode *dvp = ap->a_dvp; 1041 struct vattr *vap = ap->a_vap; 1042 struct proc *p = cnp->cn_proc; 1043 struct vnode *tdp = NULL; 1044 struct fusefs_mnt *fmp; 1045 struct fusefs_node *ip; 1046 struct fusebuf *fbuf; 1047 int error = 0; 1048 1049 ip = VTOI(dvp); 1050 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1051 1052 if (!fmp->sess_init) 1053 return (ENXIO); 1054 1055 if (fmp->undef_op & UNDEF_MKNOD) 1056 return (ENOSYS); 1057 1058 fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number, 1059 FBT_MKNOD, p); 1060 1061 fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode); 1062 if (vap->va_rdev != VNOVAL) 1063 fbuf->fb_io_rdev = vap->va_rdev; 1064 1065 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1066 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1067 1068 error = fb_queue(fmp->dev, fbuf); 1069 if (error) { 1070 if (error == ENOSYS) 1071 fmp->undef_op |= UNDEF_MKNOD; 1072 1073 goto out; 1074 } 1075 1076 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) 1077 goto out; 1078 1079 tdp->v_type = IFTOVT(fbuf->fb_io_mode); 1080 1081 *vpp = tdp; 1082 VN_KNOTE(ap->a_dvp, NOTE_WRITE); 1083 1084 /* Remove inode so that it will be reloaded by VFS_VGET and 1085 * checked to see if it is an alias of an existing entry in 1086 * the inode cache. 1087 */ 1088 vput(*vpp); 1089 (*vpp)->v_type = VNON; 1090 vgone(*vpp); 1091 *vpp = NULL; 1092 out: 1093 fb_delete(fbuf); 1094 return (error); 1095 } 1096 1097 int 1098 fusefs_read(void *v) 1099 { 1100 struct vop_read_args *ap = v; 1101 struct vnode *vp = ap->a_vp; 1102 struct uio *uio = ap->a_uio; 1103 struct proc *p = uio->uio_procp; 1104 struct fusefs_node *ip; 1105 struct fusefs_mnt *fmp; 1106 struct fusebuf *fbuf = NULL; 1107 size_t size; 1108 int error=0; 1109 1110 ip = VTOI(vp); 1111 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1112 1113 if (!fmp->sess_init) 1114 return (ENXIO); 1115 if (uio->uio_resid == 0) 1116 return (error); 1117 if (uio->uio_offset < 0) 1118 return (EINVAL); 1119 1120 while (uio->uio_resid > 0) { 1121 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_READ, p); 1122 1123 size = MIN(uio->uio_resid, fmp->max_read); 1124 fbuf->fb_io_fd = fusefs_fd_get(ip, FUFH_RDONLY); 1125 fbuf->fb_io_off = uio->uio_offset; 1126 fbuf->fb_io_len = size; 1127 1128 error = fb_queue(fmp->dev, fbuf); 1129 1130 if (error) 1131 break; 1132 1133 error = uiomove(fbuf->fb_dat, ulmin(size, fbuf->fb_len), uio); 1134 if (error) 1135 break; 1136 1137 if (fbuf->fb_len < size) 1138 break; 1139 1140 fb_delete(fbuf); 1141 fbuf = NULL; 1142 } 1143 1144 fb_delete(fbuf); 1145 return (error); 1146 } 1147 1148 int 1149 fusefs_write(void *v) 1150 { 1151 struct vop_write_args *ap = v; 1152 struct vnode *vp = ap->a_vp; 1153 struct uio *uio = ap->a_uio; 1154 struct proc *p = uio->uio_procp; 1155 struct ucred *cred = p->p_ucred; 1156 struct vattr vattr; 1157 int ioflag = ap->a_ioflag; 1158 struct fusefs_node *ip; 1159 struct fusefs_mnt *fmp; 1160 struct fusebuf *fbuf = NULL; 1161 size_t len, diff; 1162 int error=0; 1163 1164 ip = VTOI(vp); 1165 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1166 1167 if (!fmp->sess_init) 1168 return (ENXIO); 1169 if (uio->uio_resid == 0) 1170 return (error); 1171 1172 if (ioflag & IO_APPEND) { 1173 if ((error = VOP_GETATTR(vp, &vattr, cred, p)) != 0) 1174 return (error); 1175 1176 uio->uio_offset = vattr.va_size; 1177 } 1178 1179 while (uio->uio_resid > 0) { 1180 len = MIN(uio->uio_resid, fmp->max_read); 1181 fbuf = fb_setup(len, ip->ufs_ino.i_number, FBT_WRITE, p); 1182 1183 fbuf->fb_io_fd = fusefs_fd_get(ip, FUFH_WRONLY); 1184 fbuf->fb_io_off = uio->uio_offset; 1185 fbuf->fb_io_len = len; 1186 1187 if ((error = uiomove(fbuf->fb_dat, len, uio))) { 1188 printf("fusefs: uio error %i\n", error); 1189 break; 1190 } 1191 1192 error = fb_queue(fmp->dev, fbuf); 1193 1194 if (error) 1195 break; 1196 1197 diff = len - fbuf->fb_io_len; 1198 if (fbuf->fb_io_len > len) { 1199 error = EINVAL; 1200 break; 1201 } 1202 1203 uio->uio_resid += diff; 1204 uio->uio_offset -= diff; 1205 1206 if (uio->uio_offset > ip->filesize) { 1207 ip->filesize = uio->uio_offset; 1208 uvm_vnp_setsize(vp, uio->uio_offset); 1209 } 1210 uvm_vnp_uncache(vp); 1211 1212 fb_delete(fbuf); 1213 fbuf = NULL; 1214 } 1215 1216 fb_delete(fbuf); 1217 return (error); 1218 } 1219 1220 int 1221 fusefs_poll(void *v) 1222 { 1223 struct vop_poll_args *ap = v; 1224 1225 /* 1226 * We should really check to see if I/O is possible. 1227 */ 1228 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 1229 } 1230 1231 int 1232 fusefs_rename(void *v) 1233 { 1234 struct vop_rename_args *ap = v; 1235 struct vnode *tvp = ap->a_tvp; 1236 struct vnode *tdvp = ap->a_tdvp; 1237 struct vnode *fvp = ap->a_fvp; 1238 struct vnode *fdvp = ap->a_fdvp; 1239 struct componentname *tcnp = ap->a_tcnp; 1240 struct componentname *fcnp = ap->a_fcnp; 1241 struct proc *p = fcnp->cn_proc; 1242 struct fusefs_node *ip, *dp; 1243 struct fusefs_mnt *fmp; 1244 struct fusebuf *fbuf; 1245 int error = 0; 1246 1247 #ifdef DIAGNOSTIC 1248 if ((tcnp->cn_flags & HASBUF) == 0 || 1249 (fcnp->cn_flags & HASBUF) == 0) 1250 panic("fusefs_rename: no name"); 1251 #endif 1252 /* 1253 * Check for cross-device rename. 1254 */ 1255 if ((fvp->v_mount != tdvp->v_mount) || 1256 (tvp && (fvp->v_mount != tvp->v_mount))) { 1257 error = EXDEV; 1258 abortit: 1259 VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */ 1260 if (tdvp == tvp) 1261 vrele(tdvp); 1262 else 1263 vput(tdvp); 1264 if (tvp) 1265 vput(tvp); 1266 VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */ 1267 vrele(fdvp); 1268 vrele(fvp); 1269 return (error); 1270 } 1271 1272 /* 1273 * If source and dest are the same, do nothing. 1274 */ 1275 if (tvp == fvp) { 1276 error = 0; 1277 goto abortit; 1278 } 1279 1280 if ((error = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY)) != 0) 1281 goto abortit; 1282 dp = VTOI(fdvp); 1283 ip = VTOI(fvp); 1284 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1285 1286 /* 1287 * Be sure we are not renaming ".", "..", or an alias of ".". This 1288 * leads to a crippled directory tree. It's pretty tough to do a 1289 * "ls" or "pwd" with the "." directory entry missing, and "cd .." 1290 * doesn't work if the ".." entry is missing. 1291 */ 1292 if (fvp->v_type == VDIR) { 1293 /* 1294 * Avoid ".", "..", and aliases of "." for obvious reasons. 1295 */ 1296 if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || 1297 dp == ip || 1298 (fcnp->cn_flags & ISDOTDOT) || 1299 (tcnp->cn_flags & ISDOTDOT)) { 1300 VOP_UNLOCK(fvp); 1301 error = EINVAL; 1302 goto abortit; 1303 } 1304 } 1305 VN_KNOTE(fdvp, NOTE_WRITE); /* XXX right place? */ 1306 1307 if (!fmp->sess_init) { 1308 error = ENXIO; 1309 VOP_UNLOCK(fvp); 1310 goto abortit; 1311 } 1312 1313 if (fmp->undef_op & UNDEF_RENAME) { 1314 error = ENOSYS; 1315 VOP_UNLOCK(fvp); 1316 goto abortit; 1317 } 1318 1319 fbuf = fb_setup(fcnp->cn_namelen + tcnp->cn_namelen + 2, 1320 dp->ufs_ino.i_number, FBT_RENAME, p); 1321 1322 memcpy(fbuf->fb_dat, fcnp->cn_nameptr, fcnp->cn_namelen); 1323 fbuf->fb_dat[fcnp->cn_namelen] = '\0'; 1324 memcpy(fbuf->fb_dat + fcnp->cn_namelen + 1, tcnp->cn_nameptr, 1325 tcnp->cn_namelen); 1326 fbuf->fb_dat[fcnp->cn_namelen + tcnp->cn_namelen + 1] = '\0'; 1327 fbuf->fb_io_ino = VTOI(tdvp)->ufs_ino.i_number; 1328 1329 error = fb_queue(fmp->dev, fbuf); 1330 1331 if (error) { 1332 if (error == ENOSYS) { 1333 fmp->undef_op |= UNDEF_RENAME; 1334 } 1335 1336 fb_delete(fbuf); 1337 VOP_UNLOCK(fvp); 1338 goto abortit; 1339 } 1340 1341 fb_delete(fbuf); 1342 VN_KNOTE(fvp, NOTE_RENAME); 1343 1344 VOP_UNLOCK(fvp); 1345 if (tdvp == tvp) 1346 vrele(tdvp); 1347 else 1348 vput(tdvp); 1349 if (tvp) 1350 vput(tvp); 1351 vrele(fdvp); 1352 vrele(fvp); 1353 1354 return (error); 1355 } 1356 1357 int 1358 fusefs_mkdir(void *v) 1359 { 1360 struct vop_mkdir_args *ap = v; 1361 struct vnode *dvp = ap->a_dvp; 1362 struct vnode **vpp = ap->a_vpp; 1363 struct componentname *cnp = ap->a_cnp; 1364 struct vattr *vap = ap->a_vap; 1365 struct proc *p = cnp->cn_proc; 1366 struct vnode *tdp = NULL; 1367 struct fusefs_node *ip; 1368 struct fusefs_mnt *fmp; 1369 struct fusebuf *fbuf; 1370 int error = 0; 1371 1372 ip = VTOI(dvp); 1373 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1374 1375 1376 if (!fmp->sess_init) { 1377 error = ENXIO; 1378 goto out; 1379 } 1380 1381 if (fmp->undef_op & UNDEF_MKDIR) { 1382 error = ENOSYS; 1383 goto out; 1384 } 1385 1386 fbuf = fb_setup(cnp->cn_namelen + 1, ip->ufs_ino.i_number, 1387 FBT_MKDIR, p); 1388 1389 fbuf->fb_io_mode = MAKEIMODE(vap->va_type, vap->va_mode); 1390 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1391 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1392 1393 error = fb_queue(fmp->dev, fbuf); 1394 if (error) { 1395 if (error == ENOSYS) 1396 fmp->undef_op |= UNDEF_MKDIR; 1397 1398 fb_delete(fbuf); 1399 goto out; 1400 } 1401 1402 if ((error = VFS_VGET(fmp->mp, fbuf->fb_ino, &tdp))) { 1403 fb_delete(fbuf); 1404 goto out; 1405 } 1406 1407 tdp->v_type = IFTOVT(fbuf->fb_io_mode); 1408 1409 *vpp = tdp; 1410 VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK); 1411 fb_delete(fbuf); 1412 out: 1413 vput(dvp); 1414 return (error); 1415 } 1416 1417 int 1418 fusefs_rmdir(void *v) 1419 { 1420 struct vop_rmdir_args *ap = v; 1421 struct vnode *vp = ap->a_vp; 1422 struct vnode *dvp = ap->a_dvp; 1423 struct componentname *cnp = ap->a_cnp; 1424 struct proc *p = cnp->cn_proc; 1425 struct fusefs_node *ip, *dp; 1426 struct fusefs_mnt *fmp; 1427 struct fusebuf *fbuf; 1428 int error; 1429 1430 ip = VTOI(vp); 1431 dp = VTOI(dvp); 1432 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1433 1434 if (!fmp->sess_init) { 1435 error = ENXIO; 1436 goto out; 1437 } 1438 1439 if (fmp->undef_op & UNDEF_RMDIR) { 1440 error = ENOSYS; 1441 goto out; 1442 } 1443 1444 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); 1445 1446 fbuf = fb_setup(cnp->cn_namelen + 1, dp->ufs_ino.i_number, 1447 FBT_RMDIR, p); 1448 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1449 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1450 1451 error = fb_queue(fmp->dev, fbuf); 1452 1453 if (error) { 1454 if (error == ENOSYS) 1455 fmp->undef_op |= UNDEF_RMDIR; 1456 if (error != ENOTEMPTY) 1457 VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK); 1458 1459 fb_delete(fbuf); 1460 goto out; 1461 } 1462 1463 vput(dvp); 1464 dvp = NULL; 1465 1466 fb_delete(fbuf); 1467 out: 1468 if (dvp) 1469 vput(dvp); 1470 VN_KNOTE(vp, NOTE_DELETE); 1471 vput(vp); 1472 return (error); 1473 } 1474 1475 int 1476 fusefs_remove(void *v) 1477 { 1478 struct vop_remove_args *ap = v; 1479 struct vnode *vp = ap->a_vp; 1480 struct vnode *dvp = ap->a_dvp; 1481 struct componentname *cnp = ap->a_cnp; 1482 struct proc *p = cnp->cn_proc; 1483 struct fusefs_node *ip; 1484 struct fusefs_node *dp; 1485 struct fusefs_mnt *fmp; 1486 struct fusebuf *fbuf; 1487 int error = 0; 1488 1489 ip = VTOI(vp); 1490 dp = VTOI(dvp); 1491 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1492 1493 if (!fmp->sess_init) { 1494 error = ENXIO; 1495 goto out; 1496 } 1497 1498 if (fmp->undef_op & UNDEF_REMOVE) { 1499 error = ENOSYS; 1500 goto out; 1501 } 1502 1503 fbuf = fb_setup(cnp->cn_namelen + 1, dp->ufs_ino.i_number, 1504 FBT_UNLINK, p); 1505 memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen); 1506 fbuf->fb_dat[cnp->cn_namelen] = '\0'; 1507 1508 error = fb_queue(fmp->dev, fbuf); 1509 if (error) { 1510 if (error == ENOSYS) 1511 fmp->undef_op |= UNDEF_REMOVE; 1512 1513 fb_delete(fbuf); 1514 goto out; 1515 } 1516 1517 VN_KNOTE(vp, NOTE_DELETE); 1518 VN_KNOTE(dvp, NOTE_WRITE); 1519 fb_delete(fbuf); 1520 out: 1521 if (dvp == vp) 1522 vrele(vp); 1523 else 1524 vput(vp); 1525 vput(dvp); 1526 return (error); 1527 } 1528 1529 int 1530 fusefs_strategy(void *v) 1531 { 1532 return (0); 1533 } 1534 1535 int 1536 fusefs_lock(void *v) 1537 { 1538 struct vop_lock_args *ap = v; 1539 struct vnode *vp = ap->a_vp; 1540 1541 return rrw_enter(&VTOI(vp)->ufs_ino.i_lock, ap->a_flags & LK_RWFLAGS); 1542 } 1543 1544 int 1545 fusefs_unlock(void *v) 1546 { 1547 struct vop_unlock_args *ap = v; 1548 struct vnode *vp = ap->a_vp; 1549 1550 rrw_exit(&VTOI(vp)->ufs_ino.i_lock); 1551 return 0; 1552 } 1553 1554 int 1555 fusefs_islocked(void *v) 1556 { 1557 struct vop_islocked_args *ap = v; 1558 1559 return rrw_status(&VTOI(ap->a_vp)->ufs_ino.i_lock); 1560 } 1561 1562 int 1563 fusefs_advlock(void *v) 1564 { 1565 struct vop_advlock_args *ap = v; 1566 struct fusefs_node *ip = VTOI(ap->a_vp); 1567 1568 return (lf_advlock(&ip->ufs_ino.i_lockf, ip->filesize, ap->a_id, 1569 ap->a_op, ap->a_fl, ap->a_flags)); 1570 } 1571 1572 int 1573 fusefs_fsync(void *v) 1574 { 1575 struct vop_fsync_args *ap = v; 1576 struct vnode *vp = ap->a_vp; 1577 struct proc *p = ap->a_p; 1578 struct fusefs_node *ip; 1579 struct fusefs_mnt *fmp; 1580 struct fusefs_filehandle *fufh; 1581 struct fusebuf *fbuf; 1582 int type, error = 0; 1583 1584 /* 1585 * Can't write to directory file handles so no need to fsync. 1586 * FUSE has fsyncdir but it doesn't make sense on OpenBSD. 1587 */ 1588 if (vp->v_type == VDIR) 1589 return (0); 1590 1591 ip = VTOI(vp); 1592 fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump; 1593 1594 if (!fmp->sess_init) 1595 return (ENXIO); 1596 1597 /* Implementing fsync is optional so don't error. */ 1598 if (fmp->undef_op & UNDEF_FSYNC) 1599 return (0); 1600 1601 /* Sync all writeable file descriptors. */ 1602 for (type = 0; type < FUFH_MAXTYPE; type++) { 1603 fufh = &(ip->fufh[type]); 1604 if (fufh->fh_type == FUFH_WRONLY || 1605 fufh->fh_type == FUFH_RDWR) { 1606 1607 fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_FSYNC, p); 1608 fbuf->fb_io_fd = fufh->fh_id; 1609 1610 /* Always behave as if ap->a_waitfor = MNT_WAIT. */ 1611 error = fb_queue(fmp->dev, fbuf); 1612 fb_delete(fbuf); 1613 if (error) 1614 break; 1615 } 1616 } 1617 1618 if (error == ENOSYS) { 1619 fmp->undef_op |= UNDEF_FSYNC; 1620 1621 /* Implementing fsync is optional so don't error. */ 1622 return (0); 1623 } 1624 1625 return (error); 1626 } 1627