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