1 /*- 2 * Copyright (c) 2019 Tomohiro Kusumi <tkusumi@netbsd.org> 3 * Copyright (c) 2019 The DragonFly Project 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include "fuse.h" 29 30 #include <sys/fcntl.h> 31 #include <sys/dirent.h> 32 #include <sys/uio.h> 33 #include <sys/mountctl.h> 34 #include <vm/vm_pager.h> 35 #include <vm/vnode_pager.h> 36 37 static int 38 fuse_set_attr(struct fuse_node *fnp, struct fuse_attr *fat) 39 { 40 struct vattr *vap = &fnp->attr; 41 int error = 0; 42 43 vattr_null(vap); 44 45 vap->va_type = IFTOVT(fat->mode); 46 vap->va_size = fat->size; 47 vap->va_bytes = fat->blocks * S_BLKSIZE; 48 vap->va_mode = fat->mode & ~S_IFMT; 49 if (!fat->nlink) /* XXX .fuse_hidden* has 0 link */ 50 vap->va_nlink = 1; 51 else 52 vap->va_nlink = fat->nlink; 53 vap->va_uid = fat->uid; 54 vap->va_gid = fat->gid; 55 vap->va_fsid = fnp->fmp->mp->mnt_stat.f_fsid.val[0]; 56 vap->va_fileid = fat->ino; 57 vap->va_blocksize = FUSE_BLKSIZE; 58 vap->va_rmajor = VNOVAL; 59 vap->va_rminor = VNOVAL; 60 vap->va_atime.tv_sec = fat->atime; 61 vap->va_atime.tv_nsec = fat->atimensec; 62 vap->va_mtime.tv_sec = fat->mtime; 63 vap->va_mtime.tv_nsec = fat->mtimensec; 64 vap->va_ctime.tv_sec = fat->ctime; 65 vap->va_ctime.tv_nsec = fat->ctimensec; 66 vap->va_flags = 0; 67 vap->va_gen = VNOVAL; 68 vap->va_vaflags = 0; 69 70 KKASSERT(vap->va_type == fnp->type); 71 72 if (fnp->nlink != vap->va_nlink) { 73 fuse_dbg("ino=%ju update nlink %d -> %ju\n", 74 fnp->ino, fnp->nlink, vap->va_nlink); 75 fnp->nlink = vap->va_nlink; 76 } 77 78 if (fnp->vp->v_object && fnp->size != vap->va_size) 79 error = fuse_node_truncate(fnp, fnp->size, vap->va_size); 80 81 return error; 82 } 83 84 static int 85 fuse_vop_access(struct vop_access_args *ap) 86 { 87 struct vnode *vp = ap->a_vp; 88 mode_t mode = ap->a_mode; 89 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount); 90 struct fuse_ipc *fip; 91 struct fuse_access_in *fai; 92 uint32_t mask; 93 int error; 94 95 if (fuse_test_dead(fmp)) 96 return 0; 97 98 if (fuse_test_nosys(fmp, FUSE_ACCESS)) 99 return 0; 100 101 switch (vp->v_type) { 102 case VDIR: 103 case VLNK: 104 case VREG: 105 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) 106 return EROFS; 107 break; 108 case VBLK: 109 case VCHR: 110 case VSOCK: 111 case VFIFO: 112 break; 113 default: 114 return EINVAL; 115 } 116 117 mask = F_OK; 118 if (mode & VEXEC) 119 mask |= X_OK; 120 if (mode & VWRITE) 121 mask |= W_OK; 122 if (mode & VREAD) 123 mask |= R_OK; 124 125 fip = fuse_ipc_get(fmp, sizeof(*fai)); 126 fai = fuse_ipc_fill(fip, FUSE_ACCESS, VTOI(vp)->ino, ap->a_cred); 127 fai->mask = mask; 128 129 error = fuse_ipc_tx(fip); 130 if (error) { 131 if (error == ENOSYS) 132 error = 0; 133 if (error == ENOTCONN && (vp->v_flag & VROOT)) 134 error = 0; 135 return error; 136 } 137 138 fuse_ipc_put(fip); 139 140 return 0; 141 } 142 143 static int 144 fuse_vop_open(struct vop_open_args *ap) 145 { 146 struct vnode *vp = ap->a_vp; 147 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount); 148 struct fuse_node *fnp = VTOI(vp); 149 struct fuse_ipc *fip; 150 struct fuse_open_in *foi; 151 struct fuse_open_out *foo; 152 struct file *fp; 153 int error, op; 154 155 if (fuse_test_dead(fmp)) 156 return ENOTCONN; 157 158 if (fuse_test_nosys(fmp, FUSE_OPEN)) 159 return EOPNOTSUPP; 160 161 if (vp->v_type == VDIR) 162 op = FUSE_OPENDIR; 163 else 164 op = FUSE_OPEN; 165 166 fip = fuse_ipc_get(fmp, sizeof(*foi)); 167 foi = fuse_ipc_fill(fip, op, fnp->ino, ap->a_cred); 168 foi->flags = OFLAGS(ap->a_mode); 169 fuse_dbg("flags=%X\n", foi->flags); 170 if (foi->flags & O_CREAT) { 171 fuse_dbg("drop O_CREAT\n"); 172 foi->flags &= ~O_CREAT; 173 } 174 175 error = fuse_ipc_tx(fip); 176 if (error) 177 return error; 178 179 /* XXX unused */ 180 foo = fuse_out_data(fip); 181 if (foo->open_flags & FOPEN_DIRECT_IO) 182 ; 183 else if (foo->open_flags & FOPEN_KEEP_CACHE) 184 ; 185 else if (foo->open_flags & FOPEN_NONSEEKABLE) 186 ; 187 else if (foo->open_flags & FOPEN_CACHE_DIR) 188 ; 189 190 fnp->closed = false; 191 fuse_get_nfh(VTOI(vp), foo->fh); 192 fp = ap->a_fpp ? *ap->a_fpp : NULL; 193 194 if (fp) { 195 #if 1 196 fuse_get_fh(fp, foo->fh); 197 #else 198 /* see #if0'd code in fuse_vop_setattr() */ 199 if (!fp->private_data) 200 fuse_get_fh(fp, foo->fh); 201 else { 202 uint64_t *fhp = fp->private_data; 203 *fhp = foo->fh; 204 } 205 #endif 206 } 207 208 fuse_ipc_put(fip); 209 210 return vop_stdopen(ap); 211 } 212 213 static int 214 fuse_vop_close(struct vop_close_args *ap) 215 { 216 struct vnode *vp = ap->a_vp; 217 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount); 218 struct fuse_node *fnp = VTOI(vp); 219 struct fuse_ipc *fip; 220 struct fuse_release_in *fri; 221 int error, op; 222 223 if (fuse_test_dead(fmp)) 224 return 0; 225 226 if (fuse_test_nosys(fmp, FUSE_RELEASE) || 227 fuse_test_nosys(fmp, FUSE_RELEASEDIR)) 228 return EOPNOTSUPP; 229 230 if (vp->v_type == VDIR) 231 op = FUSE_RELEASEDIR; 232 else 233 op = FUSE_RELEASE; 234 235 fip = fuse_ipc_get(fmp, sizeof(*fri)); 236 fri = fuse_ipc_fill(fip, op, fnp->ino, NULL); 237 /* unused */ 238 //fri->flags = ...; 239 //fri->release_flags = ...; 240 //fri->lock_owner = ...; 241 fri->fh = fuse_nfh(VTOI(vp)); 242 if (ap->a_fp) 243 fri->fh = fuse_fh(ap->a_fp); 244 245 error = fuse_ipc_tx(fip); 246 if (error) 247 return error; 248 249 fuse_ipc_put(fip); 250 251 fnp->closed = true; 252 fuse_put_nfh(VTOI(vp)); 253 if (ap->a_fp) 254 fuse_put_fh(ap->a_fp); 255 256 return vop_stdclose(ap); 257 } 258 259 static int 260 fuse_vop_fsync(struct vop_fsync_args *ap) 261 { 262 struct vnode *vp = ap->a_vp; 263 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount); 264 struct fuse_ipc *fip; 265 struct fuse_fsync_in *fsi; 266 int error, op; 267 268 if (fuse_test_dead(fmp)) 269 return 0; 270 271 if (fuse_test_nosys(fmp, FUSE_FSYNC)) 272 return 0; 273 274 if (vp->v_type == VDIR) 275 op = FUSE_FSYNCDIR; 276 else 277 op = FUSE_FSYNC; 278 279 fip = fuse_ipc_get(fmp, sizeof(*fsi)); 280 fsi = fuse_ipc_fill(fip, op, VTOI(vp)->ino, NULL); 281 fsi->fh = fuse_nfh(VTOI(vp)); 282 if (ap->a_fp) 283 fsi->fh = fuse_fh(ap->a_fp); 284 fsi->fsync_flags = 1; /* datasync */ 285 286 error = fuse_ipc_tx(fip); 287 if (error) 288 return error; 289 fuse_ipc_put(fip); 290 291 vn_syncer_remove(vp, 1); 292 vfsync(ap->a_vp, ap->a_waitfor, 1, NULL, NULL); 293 vclrisdirty(vp); 294 295 return 0; 296 } 297 298 static int 299 fuse_vop_getattr(struct vop_getattr_args *ap) 300 { 301 struct vnode *vp = ap->a_vp; 302 struct vattr *vap = ap->a_vap; 303 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount); 304 struct fuse_node *fnp = VTOI(vp); 305 struct fuse_ipc *fip; 306 struct fuse_getattr_in *fgi; 307 struct fuse_attr_out *fao; 308 int error; 309 310 if (fuse_test_dead(fmp)) 311 return 0; 312 313 if (fuse_test_nosys(fmp, FUSE_GETATTR)) 314 return 0; 315 316 fip = fuse_ipc_get(fmp, sizeof(*fgi)); 317 fgi = fuse_ipc_fill(fip, FUSE_GETATTR, fnp->ino, NULL); 318 #if 0 319 /* this may be called before open when fh is 0 */ 320 fgi->getattr_flags |= FUSE_GETATTR_FH; 321 fgi->fh = fuse_nfh(fnp); 322 if (ap->a_fp) 323 fgi->fh = fuse_fh(ap->a_fp); 324 #endif 325 error = fuse_ipc_tx(fip); 326 if (error) { 327 if (error == ENOSYS) 328 error = 0; 329 if (error == ENOTCONN && (vp->v_flag & VROOT)) { 330 memset(vap, 0, sizeof(*vap)); 331 vap->va_type = vp->v_type; 332 error = 0; 333 } 334 return error; 335 } 336 337 fao = fuse_out_data(fip); 338 mtx_lock(&fnp->node_lock); 339 fuse_set_attr(fnp, &fao->attr); 340 memcpy(vap, &fnp->attr, sizeof(*vap)); 341 /* unused */ 342 //fao->attr_valid; 343 //fao->attr_valid_nsec; 344 mtx_unlock(&fnp->node_lock); 345 346 fuse_ipc_put(fip); 347 348 if (vap->va_type != vp->v_type) 349 return EINVAL; 350 351 return 0; 352 } 353 354 static int 355 fuse_vop_setattr(struct vop_setattr_args *ap) 356 { 357 struct vnode *vp = ap->a_vp; 358 struct vattr *vap = ap->a_vap; 359 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount); 360 struct fuse_node *fnp = VTOI(vp); 361 struct fuse_ipc *fip; 362 struct fuse_setattr_in *fsi, arg; 363 struct fuse_attr_out *fao; 364 int kflags = 0; 365 int error = 0; 366 367 if (fuse_test_dead(fmp)) 368 return 0; 369 370 if (fuse_test_nosys(fmp, FUSE_SETATTR)) 371 return 0; 372 373 if (vp->v_mount->mnt_flag & MNT_RDONLY) 374 return EROFS; 375 376 memset(&arg, 0, sizeof(arg)); 377 mtx_lock(&fnp->node_lock); 378 379 if (!error && (vap->va_flags != VNOVAL)) { 380 mtx_unlock(&fnp->node_lock); 381 kflags |= NOTE_ATTRIB; 382 return EOPNOTSUPP; /* XXX */ 383 } 384 385 if (!error && (vap->va_size != VNOVAL)) { 386 if (vp->v_type == VDIR) { 387 mtx_unlock(&fnp->node_lock); 388 return EISDIR; 389 } 390 if (vp->v_type == VREG && 391 (vp->v_mount->mnt_flag & MNT_RDONLY)) { 392 mtx_unlock(&fnp->node_lock); 393 return EROFS; 394 } 395 arg.size = vap->va_size; 396 arg.valid |= FATTR_SIZE; 397 if (vap->va_size > fnp->size) 398 kflags |= NOTE_WRITE | NOTE_EXTEND; 399 else 400 kflags |= NOTE_WRITE; 401 } 402 403 if (!error && (vap->va_uid != (uid_t)VNOVAL || 404 vap->va_gid != (gid_t)VNOVAL)) { 405 mode_t mode; 406 error = vop_helper_chown(vp, vap->va_uid, vap->va_gid, 407 ap->a_cred, &arg.uid, &arg.gid, &mode); 408 arg.valid |= FATTR_UID; 409 arg.valid |= FATTR_GID; 410 kflags |= NOTE_ATTRIB; 411 } 412 413 if (!error && (vap->va_mode != (mode_t)VNOVAL)) { 414 error = vop_helper_chmod(vp, vap->va_mode, ap->a_cred, 415 vap->va_uid, vap->va_gid, (mode_t*)&arg.mode); 416 arg.valid |= FATTR_MODE; 417 kflags |= NOTE_ATTRIB; 418 } 419 420 if (!error && (vap->va_atime.tv_sec != VNOVAL && 421 vap->va_atime.tv_nsec != VNOVAL)) { 422 arg.atime = vap->va_atime.tv_sec; 423 arg.atimensec = vap->va_atime.tv_nsec; 424 arg.valid |= FATTR_ATIME; 425 kflags |= NOTE_ATTRIB; 426 } 427 428 if (!error && (vap->va_mtime.tv_sec != VNOVAL && 429 vap->va_mtime.tv_nsec != VNOVAL)) { 430 arg.mtime = vap->va_mtime.tv_sec; 431 arg.mtimensec = vap->va_mtime.tv_nsec; 432 arg.valid |= FATTR_MTIME; 433 kflags |= NOTE_ATTRIB; 434 } 435 436 if (!error && (vap->va_ctime.tv_sec != VNOVAL && 437 vap->va_ctime.tv_nsec != VNOVAL)) { 438 arg.ctime = vap->va_ctime.tv_sec; 439 arg.ctimensec = vap->va_ctime.tv_nsec; 440 arg.valid |= FATTR_CTIME; 441 kflags |= NOTE_ATTRIB; 442 } 443 444 mtx_unlock(&fnp->node_lock); 445 446 if (error) 447 return error; 448 if (!arg.valid) 449 return 0; 450 451 fip = fuse_ipc_get(fmp, sizeof(*fsi)); 452 fsi = fuse_ipc_fill(fip, FUSE_SETATTR, fnp->ino, ap->a_cred); 453 memcpy(fsi, &arg, sizeof(arg)); 454 #if 0 455 fsi->valid |= FATTR_FH; 456 fsi->fh = fuse_nfh(fnp); 457 if (ap->a_fp) { 458 /* vn_open() may call VOP_SETATTR_FP() prior to VOP_OPEN(). */ 459 if (!ap->a_fp->private_data) 460 fuse_get_fh(ap->a_fp, 0); /* XXX */ 461 fsi->fh = fuse_fh(ap->a_fp); 462 } 463 #endif 464 error = fuse_ipc_tx(fip); 465 if (error) 466 return error; 467 468 fao = fuse_out_data(fip); 469 if (IFTOVT(fao->attr.mode) != vp->v_type) { 470 fuse_ipc_put(fip); 471 return EINVAL; 472 } 473 mtx_lock(&fnp->node_lock); 474 fuse_set_attr(fnp, &fao->attr); 475 /* unused */ 476 //fao->attr_valid; 477 //fao->attr_valid_nsec; 478 mtx_unlock(&fnp->node_lock); 479 480 fuse_ipc_put(fip); 481 fuse_knote(vp, kflags); 482 483 return 0; 484 } 485 486 static int 487 fuse_vop_nresolve(struct vop_nresolve_args *ap) 488 { 489 struct vnode *dvp = ap->a_dvp; 490 struct vnode *vp; 491 struct namecache *ncp = ap->a_nch->ncp; 492 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount); 493 struct fuse_node *dfnp = VTOI(dvp); 494 struct fuse_ipc *fip; 495 struct fuse_entry_out *feo; 496 char *p, tmp[1024]; 497 uint32_t mode; 498 enum vtype vtyp; 499 int error; 500 501 if (fuse_test_dead(fmp)) 502 return ENOTCONN; 503 504 if (fuse_test_nosys(fmp, FUSE_LOOKUP)) 505 return EOPNOTSUPP; 506 507 fip = fuse_ipc_get(fmp, ncp->nc_nlen + 1); 508 p = fuse_ipc_fill(fip, FUSE_LOOKUP, dfnp->ino, ap->a_cred); 509 510 memcpy(p, ncp->nc_name, ncp->nc_nlen); 511 p[ncp->nc_nlen] = '\0'; 512 strlcpy(tmp, p, sizeof(tmp)); 513 514 error = fuse_ipc_tx(fip); 515 if (error == ENOENT) { 516 cache_setvp(ap->a_nch, NULL); 517 fuse_dbg("lookup \"%s\" ENOENT\n", tmp); 518 return ENOENT; 519 } else if (error) { 520 fuse_dbg("lookup \"%s\" error=%d\n", tmp, error); 521 return error; 522 } 523 524 feo = fuse_out_data(fip); 525 fuse_dbg("lookup \"%s\" ino=%ju/%ju\n", p, feo->nodeid, feo->attr.ino); 526 527 mode = feo->attr.mode; 528 if (S_ISREG(mode)) 529 vtyp = VREG; 530 else if (S_ISDIR(mode)) 531 vtyp = VDIR; 532 else if (S_ISBLK(mode)) 533 vtyp = VBLK; 534 else if (S_ISCHR(mode)) 535 vtyp = VCHR; 536 else if (S_ISLNK(mode)) 537 vtyp = VLNK; 538 else if (S_ISSOCK(mode)) 539 vtyp = VSOCK; 540 else if (S_ISFIFO(mode)) 541 vtyp = VFIFO; 542 else 543 vtyp = VBAD; 544 545 error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), vtyp, &vp); 546 if (error) { 547 fuse_ipc_put(fip); 548 return error; 549 } 550 KKASSERT(vp); 551 KKASSERT(vn_islocked(vp)); 552 553 vn_unlock(vp); 554 cache_setvp(ap->a_nch, vp); 555 vrele(vp); 556 557 /* unused */ 558 //feo->generation; 559 //feo->entry_valid; 560 //feo->attr_valid; 561 //feo->entry_valid_nsec; 562 //feo->attr_valid_nsec; 563 564 fuse_ipc_put(fip); 565 566 return 0; 567 } 568 569 static int 570 fuse_vop_nlink(struct vop_nlink_args *ap) 571 { 572 struct vnode *dvp = ap->a_dvp; 573 struct vnode *vp = ap->a_vp; 574 struct namecache *ncp = ap->a_nch->ncp; 575 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount); 576 struct fuse_node *dfnp = VTOI(dvp); 577 struct fuse_node *fnp = VTOI(vp); 578 struct fuse_dent *fep; 579 struct fuse_ipc *fip; 580 struct fuse_link_in *fli; 581 struct fuse_entry_out *feo; 582 char *p; 583 int error; 584 585 if (fuse_test_dead(fmp)) 586 return ENOTCONN; 587 588 if (fuse_test_nosys(fmp, FUSE_LINK)) 589 return EOPNOTSUPP; 590 591 if (vp->v_type == VDIR) 592 return EPERM; 593 if (dvp->v_mount != vp->v_mount) 594 return EXDEV; 595 if (fnp->nlink >= LINK_MAX) 596 return EMLINK; 597 598 fip = fuse_ipc_get(fmp, sizeof(fli) + ncp->nc_nlen + 1); 599 fli = fuse_ipc_fill(fip, FUSE_LINK, dfnp->ino, ap->a_cred); 600 fli->oldnodeid = fnp->ino; 601 602 p = (char*)(fli + 1); 603 memcpy(p, ncp->nc_name, ncp->nc_nlen); 604 p[ncp->nc_nlen] = '\0'; 605 606 error = fuse_ipc_tx(fip); 607 if (error) 608 return error; 609 610 feo = fuse_out_data(fip); 611 if (IFTOVT(feo->attr.mode) != vp->v_type) { 612 fuse_ipc_put(fip); 613 return EINVAL; 614 } 615 616 mtx_lock(&dfnp->node_lock); 617 mtx_lock(&fnp->node_lock); 618 fuse_dent_new(fnp, p, strlen(p), &fep); 619 fuse_dent_attach(dfnp, fep); 620 fuse_set_attr(fnp, &feo->attr); 621 mtx_unlock(&fnp->node_lock); 622 mtx_unlock(&dfnp->node_lock); 623 624 cache_setunresolved(ap->a_nch); 625 cache_setvp(ap->a_nch, vp); 626 fuse_knote(dvp, NOTE_WRITE); 627 fuse_knote(vp, NOTE_LINK); 628 629 /* unused */ 630 //feo->nodeid; 631 //feo->generation; 632 //feo->entry_valid; 633 //feo->attr_valid; 634 //feo->entry_valid_nsec; 635 //feo->attr_valid_nsec; 636 637 fuse_ipc_put(fip); 638 639 return 0; 640 } 641 642 static int 643 fuse_vop_ncreate(struct vop_ncreate_args *ap) 644 { 645 struct vnode *dvp = ap->a_dvp; 646 struct vnode *vp; 647 struct namecache *ncp = ap->a_nch->ncp; 648 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount); 649 struct fuse_node *dfnp = VTOI(dvp); 650 struct fuse_node *fnp; 651 struct fuse_ipc *fip; 652 struct fuse_create_in *fci; 653 struct fuse_entry_out *feo; 654 struct fuse_open_out *foo; 655 enum vtype vtyp; 656 char *p; 657 int error; 658 659 if (fuse_test_dead(fmp)) 660 return ENOTCONN; 661 662 if (fuse_test_nosys(fmp, FUSE_CREATE)) 663 return EOPNOTSUPP; 664 665 fip = fuse_ipc_get(fmp, sizeof(*fci) + ncp->nc_nlen + 1); 666 fci = fuse_ipc_fill(fip, FUSE_CREATE, dfnp->ino, ap->a_cred); 667 fci->flags = OFLAGS(ap->a_vap->va_fuseflags); 668 fci->mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode); 669 /* unused */ 670 //fci->umask = ...; 671 fuse_dbg("flags=%X mode=%X\n", fci->flags, fci->mode); 672 673 p = (char*)(fci + 1); 674 memcpy(p, ncp->nc_name, ncp->nc_nlen); 675 p[ncp->nc_nlen] = '\0'; 676 677 error = fuse_ipc_tx(fip); 678 if (error) 679 return error; 680 681 feo = fuse_out_data(fip); 682 foo = (struct fuse_open_out*)(feo + 1); 683 vtyp = IFTOVT(feo->attr.mode); 684 if (vtyp != VREG && vtyp != VSOCK) { 685 fuse_ipc_put(fip); 686 return EINVAL; 687 } 688 689 error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), VREG, &vp); 690 if (error) { 691 fuse_ipc_put(fip); 692 return error; 693 } 694 KKASSERT(vp); 695 KKASSERT(vn_islocked(vp)); 696 697 fnp = VTOI(vp); 698 mtx_lock(&fnp->node_lock); 699 fuse_set_attr(fnp, &feo->attr); 700 mtx_unlock(&fnp->node_lock); 701 702 cache_setunresolved(ap->a_nch); 703 cache_setvp(ap->a_nch, vp); 704 *(ap->a_vpp) = vp; 705 fuse_knote(dvp, NOTE_WRITE); 706 707 /* unused */ 708 //feo->generation; 709 //feo->entry_valid; 710 //feo->attr_valid; 711 //feo->entry_valid_nsec; 712 //feo->attr_valid_nsec; 713 /* unused */ 714 //foo->open_flags; 715 716 fuse_ipc_put(fip); 717 718 return 0; 719 } 720 721 static int 722 fuse_vop_nmknod(struct vop_nmknod_args *ap) 723 { 724 struct vnode *dvp = ap->a_dvp; 725 struct vnode *vp; 726 struct namecache *ncp = ap->a_nch->ncp; 727 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount); 728 struct fuse_node *dfnp = VTOI(dvp); 729 struct fuse_node *fnp; 730 struct fuse_ipc *fip; 731 struct fuse_mknod_in *fmi; 732 struct fuse_entry_out *feo; 733 enum vtype vtyp; 734 char *p; 735 int error; 736 737 if (fuse_test_dead(fmp)) 738 return ENOTCONN; 739 740 if (fuse_test_nosys(fmp, FUSE_MKNOD)) 741 return EOPNOTSUPP; 742 743 fip = fuse_ipc_get(fmp, sizeof(*fmi) + ncp->nc_nlen + 1); 744 fmi = fuse_ipc_fill(fip, FUSE_MKNOD, dfnp->ino, ap->a_cred); 745 fmi->mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode); 746 /* unused */ 747 //fmi->rdev = ...; 748 //fmi->umask = ...; 749 750 p = (char*)(fmi + 1); 751 memcpy(p, ncp->nc_name, ncp->nc_nlen); 752 p[ncp->nc_nlen] = '\0'; 753 754 error = fuse_ipc_tx(fip); 755 if (error) 756 return error; 757 758 feo = fuse_out_data(fip); 759 vtyp = IFTOVT(feo->attr.mode); 760 if (vtyp != VBLK && vtyp != VCHR && vtyp != VFIFO) { 761 fuse_ipc_put(fip); 762 return EINVAL; 763 } 764 765 error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), 766 ap->a_vap->va_type, &vp); 767 if (error) { 768 fuse_ipc_put(fip); 769 return error; 770 } 771 KKASSERT(vp); 772 KKASSERT(vn_islocked(vp)); 773 774 fnp = VTOI(vp); 775 mtx_lock(&fnp->node_lock); 776 fuse_set_attr(fnp, &feo->attr); 777 mtx_unlock(&fnp->node_lock); 778 779 cache_setunresolved(ap->a_nch); 780 cache_setvp(ap->a_nch, vp); 781 *(ap->a_vpp) = vp; 782 fuse_knote(dvp, NOTE_WRITE); 783 784 /* unused */ 785 //feo->generation; 786 //feo->entry_valid; 787 //feo->attr_valid; 788 //feo->entry_valid_nsec; 789 //feo->attr_valid_nsec; 790 791 fuse_ipc_put(fip); 792 793 return 0; 794 } 795 796 static int 797 fuse_vop_nremove(struct vop_nremove_args *ap) 798 { 799 struct vnode *dvp = ap->a_dvp; 800 struct vnode *vp; 801 struct namecache *ncp = ap->a_nch->ncp; 802 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount); 803 struct fuse_node *dfnp = VTOI(dvp); 804 struct fuse_node *fnp; 805 struct fuse_dent *fep; 806 struct fuse_ipc *fip; 807 char *p; 808 int error; 809 810 if (fuse_test_dead(fmp)) 811 return ENOTCONN; 812 813 if (fuse_test_nosys(fmp, FUSE_UNLINK)) 814 return EOPNOTSUPP; 815 816 error = cache_vget(ap->a_nch, ap->a_cred, LK_SHARED, &vp); 817 KKASSERT(vp->v_mount == dvp->v_mount); 818 KKASSERT(!error); /* from tmpfs */ 819 vn_unlock(vp); 820 821 fip = fuse_ipc_get(fmp, ncp->nc_nlen + 1); 822 p = fuse_ipc_fill(fip, FUSE_UNLINK, dfnp->ino, ap->a_cred); 823 824 memcpy(p, ncp->nc_name, ncp->nc_nlen); 825 p[ncp->nc_nlen] = '\0'; 826 827 error = fuse_ipc_tx(fip); 828 if (error) { 829 vrele(vp); 830 return error; 831 } 832 833 fnp = VTOI(vp); 834 mtx_lock(&dfnp->node_lock); 835 mtx_lock(&fnp->node_lock); 836 error = fuse_dent_find(dfnp, p, strlen(p), &fep); 837 if (error == ENOENT) { 838 mtx_unlock(&fnp->node_lock); 839 mtx_unlock(&dfnp->node_lock); 840 fuse_ipc_put(fip); 841 vrele(vp); 842 return error; 843 } 844 fuse_dent_detach(dfnp, fep); 845 fuse_dent_free(fep); 846 mtx_unlock(&fnp->node_lock); 847 mtx_unlock(&dfnp->node_lock); 848 849 cache_unlink(ap->a_nch); 850 fuse_knote(dvp, NOTE_WRITE); 851 fuse_knote(vp, NOTE_DELETE); 852 853 fuse_ipc_put(fip); 854 vrele(vp); 855 856 return 0; 857 } 858 859 static int 860 fuse_vop_nmkdir(struct vop_nmkdir_args *ap) 861 { 862 struct vnode *dvp = ap->a_dvp; 863 struct vnode *vp; 864 struct namecache *ncp = ap->a_nch->ncp; 865 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount); 866 struct fuse_node *dfnp = VTOI(dvp); 867 struct fuse_node *fnp; 868 struct fuse_ipc *fip; 869 struct fuse_mkdir_in *fmi; 870 struct fuse_entry_out *feo; 871 char *p; 872 int error; 873 874 if (fuse_test_dead(fmp)) 875 return ENOTCONN; 876 877 if (fuse_test_nosys(fmp, FUSE_MKDIR)) 878 return EOPNOTSUPP; 879 880 fip = fuse_ipc_get(fmp, sizeof(*fmi) + ncp->nc_nlen + 1); 881 fmi = fuse_ipc_fill(fip, FUSE_MKDIR, dfnp->ino, ap->a_cred); 882 fmi->mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode); 883 884 p = (char*)(fmi + 1); 885 memcpy(p, ncp->nc_name, ncp->nc_nlen); 886 p[ncp->nc_nlen] = '\0'; 887 888 error = fuse_ipc_tx(fip); 889 if (error) 890 return error; 891 892 feo = fuse_out_data(fip); 893 if (IFTOVT(feo->attr.mode) != VDIR) { 894 fuse_ipc_put(fip); 895 return EINVAL; 896 } 897 898 error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), VDIR, &vp); 899 if (error) { 900 fuse_ipc_put(fip); 901 return error; 902 } 903 KKASSERT(vp); 904 KKASSERT(vn_islocked(vp)); 905 906 fnp = VTOI(vp); 907 mtx_lock(&fnp->node_lock); 908 fuse_set_attr(fnp, &feo->attr); 909 mtx_unlock(&fnp->node_lock); 910 911 cache_setunresolved(ap->a_nch); 912 cache_setvp(ap->a_nch, vp); 913 *(ap->a_vpp) = vp; 914 fuse_knote(dvp, NOTE_WRITE | NOTE_LINK); 915 916 /* unused */ 917 //feo->generation; 918 //feo->entry_valid; 919 //feo->attr_valid; 920 //feo->entry_valid_nsec; 921 //feo->attr_valid_nsec; 922 923 fuse_ipc_put(fip); 924 925 return 0; 926 } 927 928 static int 929 fuse_vop_nrmdir(struct vop_nrmdir_args *ap) 930 { 931 struct vnode *dvp = ap->a_dvp; 932 struct vnode *vp; 933 struct namecache *ncp = ap->a_nch->ncp; 934 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount); 935 struct fuse_node *dfnp = VTOI(dvp); 936 struct fuse_node *fnp; 937 struct fuse_dent *fep; 938 struct fuse_ipc *fip; 939 char *p; 940 int error; 941 942 if (fuse_test_dead(fmp)) 943 return ENOTCONN; 944 945 if (fuse_test_nosys(fmp, FUSE_RMDIR)) 946 return EOPNOTSUPP; 947 948 error = cache_vget(ap->a_nch, ap->a_cred, LK_SHARED, &vp); 949 KKASSERT(vp->v_mount == dvp->v_mount); 950 KKASSERT(!error); /* from tmpfs */ 951 vn_unlock(vp); 952 953 fip = fuse_ipc_get(fmp, ncp->nc_nlen + 1); 954 p = fuse_ipc_fill(fip, FUSE_RMDIR, dfnp->ino, ap->a_cred); 955 956 memcpy(p, ncp->nc_name, ncp->nc_nlen); 957 p[ncp->nc_nlen] = '\0'; 958 959 error = fuse_ipc_tx(fip); 960 if (error) { 961 vrele(vp); 962 return error; 963 } 964 965 fnp = VTOI(vp); 966 mtx_lock(&dfnp->node_lock); 967 mtx_lock(&fnp->node_lock); 968 error = fuse_dent_find(dfnp, p, strlen(p), &fep); 969 if (error == ENOENT) { 970 mtx_unlock(&fnp->node_lock); 971 mtx_unlock(&dfnp->node_lock); 972 fuse_ipc_put(fip); 973 vrele(vp); 974 return error; 975 } 976 fuse_dent_detach(dfnp, fep); 977 fuse_dent_free(fep); 978 mtx_unlock(&fnp->node_lock); 979 mtx_unlock(&dfnp->node_lock); 980 981 cache_unlink(ap->a_nch); 982 fuse_knote(dvp, NOTE_WRITE | NOTE_LINK); 983 984 fuse_ipc_put(fip); 985 vrele(vp); 986 987 return 0; 988 } 989 990 static int 991 fuse_vop_pathconf(struct vop_pathconf_args *ap) 992 { 993 switch (ap->a_name) { 994 case _PC_FILESIZEBITS: 995 *ap->a_retval = 64; 996 break; 997 case _PC_NO_TRUNC: 998 *ap->a_retval = 1; 999 break; 1000 default: 1001 return vop_stdpathconf(ap); 1002 } 1003 1004 return 0; 1005 } 1006 1007 static int 1008 fuse_vop_readdir(struct vop_readdir_args *ap) 1009 { 1010 struct vnode *vp = ap->a_vp; 1011 struct uio *uio = ap->a_uio; 1012 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount); 1013 struct fuse_ipc *fip; 1014 struct fuse_read_in *fri; 1015 const char *buf; 1016 size_t len; 1017 off_t cur_offset = 0; 1018 int error; 1019 1020 if (fuse_test_dead(fmp)) 1021 return ENOTCONN; 1022 1023 if (fuse_test_nosys(fmp, FUSE_READDIR)) 1024 return EOPNOTSUPP; 1025 1026 fip = fuse_ipc_get(fmp, sizeof(*fri)); 1027 fri = fuse_ipc_fill(fip, FUSE_READDIR, VTOI(vp)->ino, ap->a_cred); 1028 fri->fh = fuse_nfh(VTOI(vp)); 1029 if (ap->a_fp) 1030 fri->fh = fuse_fh(ap->a_fp); 1031 fri->offset = 0; 1032 /* 1033 * XXX This needs to be large enough to read all entries at once. 1034 * FUSE filesystems typically just opendir/readdir and return entries. 1035 */ 1036 fri->size = FUSE_BLKSIZE * 10; 1037 /* unused */ 1038 //fri->read_flags = ...; 1039 //fri->lock_owner = ...; 1040 //fri->flags = ...; 1041 1042 error = fuse_ipc_tx(fip); 1043 if (error) 1044 return error; 1045 1046 buf = fuse_out_data(fip); 1047 len = fuse_out_data_size(fip); 1048 1049 while (1) { 1050 const struct fuse_dirent *fde; 1051 size_t freclen; 1052 1053 fuse_dbg("uio_offset=%ju uio_resid=%ju\n", 1054 uio->uio_offset, uio->uio_resid); 1055 1056 if (len < FUSE_NAME_OFFSET) { 1057 if (ap->a_eofflag) 1058 *ap->a_eofflag = 1; 1059 break; 1060 } 1061 if (uio->uio_resid < FUSE_NAME_OFFSET) 1062 break; 1063 1064 fde = (const struct fuse_dirent*)buf; 1065 if (!fde->namelen) { 1066 error = EINVAL; 1067 break; 1068 } 1069 freclen = FUSE_DIRENT_SIZE(fde); 1070 1071 /* 1072 * Also see 1073 * getdirentries(2) in sys/kern/vfs_syscalls.c 1074 * readdir(3) in lib/libc/gen/readdir.c 1075 */ 1076 if (cur_offset >= uio->uio_offset) { 1077 error = 0; 1078 if (vop_write_dirent(&error, uio, fde->ino, fde->type, 1079 fde->namelen, fde->name)) 1080 break; 1081 if (error) 1082 break; 1083 fuse_dbg("ino=%ju type=%d name=%s len=%u\n", 1084 fde->ino, fde->type, fde->name, fde->namelen); 1085 } 1086 1087 cur_offset += _DIRENT_RECLEN(fde->namelen); 1088 buf += freclen; 1089 len -= freclen; 1090 } 1091 fuse_ipc_put(fip); 1092 1093 return error; 1094 } 1095 1096 static int 1097 fuse_vop_readlink(struct vop_readlink_args *ap) 1098 { 1099 struct vnode *vp = ap->a_vp; 1100 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount); 1101 struct fuse_ipc *fip; 1102 int error; 1103 1104 if (fuse_test_dead(fmp)) 1105 return ENOTCONN; 1106 1107 if (fuse_test_nosys(fmp, FUSE_READLINK)) 1108 return EOPNOTSUPP; 1109 1110 if (vp->v_type != VLNK) 1111 return EINVAL; 1112 1113 fip = fuse_ipc_get(fmp, 0); 1114 fuse_ipc_fill(fip, FUSE_READLINK, VTOI(vp)->ino, ap->a_cred); 1115 1116 error = fuse_ipc_tx(fip); 1117 if (error) 1118 return error; 1119 1120 error = uiomove(fuse_out_data(fip), fuse_out_data_size(fip), ap->a_uio); 1121 1122 fuse_ipc_put(fip); 1123 1124 return error; 1125 } 1126 1127 static int 1128 fuse_vop_nrename(struct vop_nrename_args *ap) 1129 { 1130 struct namecache *fncp = ap->a_fnch->ncp; 1131 struct namecache *tncp = ap->a_tnch->ncp; 1132 struct vnode *fdvp = ap->a_fdvp; 1133 struct vnode *fvp = fncp->nc_vp; 1134 struct vnode *tdvp = ap->a_tdvp; 1135 struct vnode *tvp; 1136 struct fuse_mount *fmp = VFSTOFUSE(fdvp->v_mount); 1137 struct fuse_node *fdfnp = VTOI(fdvp); 1138 struct fuse_node *ffnp = VTOI(fvp); 1139 struct fuse_node *tdfnp = VTOI(tdvp); 1140 struct fuse_node *tfnp; 1141 struct fuse_dent *ffep; 1142 struct fuse_dent *tfep; 1143 struct fuse_ipc *fip; 1144 struct fuse_rename_in *fri; 1145 char *p, *newname, *oldname; 1146 int error; 1147 1148 KKASSERT(fdvp->v_mount == fvp->v_mount); 1149 1150 if (fuse_test_dead(fmp)) 1151 return ENOTCONN; 1152 1153 if (fuse_test_nosys(fmp, FUSE_RENAME)) 1154 return EOPNOTSUPP; 1155 1156 error = cache_vget(ap->a_tnch, ap->a_cred, LK_SHARED, &tvp); 1157 if (!error) { 1158 tfnp = VTOI(tvp); 1159 vn_unlock(tvp); 1160 } else 1161 tfnp = NULL; 1162 1163 /* Disallow cross-device renames. 1164 * Why isn't this done by the caller? */ 1165 if (fvp->v_mount != tdvp->v_mount || 1166 (tvp && fvp->v_mount != tvp->v_mount)) { 1167 error = EXDEV; 1168 goto out; 1169 } 1170 1171 if (fvp == tvp) { 1172 error = 0; 1173 goto out; 1174 } 1175 error = fuse_dent_find(fdfnp, fncp->nc_name, fncp->nc_nlen, &ffep); 1176 if (error == ENOENT) 1177 goto out; 1178 KKASSERT(ffep->fnp == ffnp); 1179 1180 if (tvp) { 1181 KKASSERT(tfnp); 1182 if (ffnp->type == VDIR && tfnp->type == VDIR) { 1183 if (!RB_EMPTY(&tfnp->dent_head)) { 1184 error = ENOTEMPTY; 1185 goto out; 1186 } 1187 } else if (ffnp->type == VDIR && tfnp->type != VDIR) { 1188 error = ENOTDIR; 1189 goto out; 1190 } else if (ffnp->type != VDIR && tfnp->type == VDIR) { 1191 error = EISDIR; 1192 goto out; 1193 } else 1194 KKASSERT(ffnp->type != VDIR && tfnp->type != VDIR); 1195 } 1196 1197 fip = fuse_ipc_get(fmp, 1198 sizeof(*fri) + fncp->nc_nlen + tncp->nc_nlen + 2); 1199 /* There is also fuse_rename2_in with flags. */ 1200 fri = fuse_ipc_fill(fip, FUSE_RENAME, fdfnp->ino, ap->a_cred); 1201 fri->newdir = tdfnp->ino; 1202 1203 p = (char*)(fri + 1); 1204 memcpy(p, fncp->nc_name, fncp->nc_nlen); 1205 p[fncp->nc_nlen] = '\0'; 1206 memcpy(p + fncp->nc_nlen + 1, tncp->nc_name, tncp->nc_nlen); 1207 p[fncp->nc_nlen + 1 + tncp->nc_nlen] = '\0'; 1208 1209 error = fuse_ipc_tx(fip); 1210 if (error) 1211 goto out; 1212 fuse_ipc_put(fip); 1213 1214 if (fncp->nc_nlen != tncp->nc_nlen || 1215 memcmp(fncp->nc_name, tncp->nc_name, fncp->nc_nlen)) { 1216 newname = kmalloc(tncp->nc_nlen + 1, M_TEMP, M_WAITOK | M_ZERO); 1217 KKASSERT(newname); 1218 memcpy(newname, tncp->nc_name, tncp->nc_nlen); 1219 newname[tncp->nc_nlen] = '\0'; 1220 fuse_dbg("newname=\"%s\"\n", newname); 1221 } else 1222 newname = NULL; 1223 1224 mtx_lock(&tdfnp->node_lock); 1225 mtx_lock(&fdfnp->node_lock); 1226 mtx_lock(&ffnp->node_lock); 1227 1228 fuse_dbg("detach from_dent=\"%s\"\n", ffep->name); 1229 fuse_dent_detach(fdfnp, ffep); 1230 1231 if (newname) { 1232 oldname = ffep->name; 1233 ffep->name = newname; 1234 newname = oldname; 1235 } 1236 1237 if (tvp) { 1238 mtx_lock(&tfnp->node_lock); 1239 error = fuse_dent_find(tdfnp, tncp->nc_name, tncp->nc_nlen, 1240 &tfep); 1241 KKASSERT(!error); 1242 fuse_dbg("detach/free to_dent=\"%s\"\n", tfep->name); 1243 fuse_dent_detach(tdfnp, tfep); 1244 fuse_dent_free(tfep); 1245 mtx_unlock(&tfnp->node_lock); 1246 fuse_knote(tdvp, NOTE_DELETE); 1247 } 1248 1249 fuse_dbg("attach from_dent=\"%s\"\n", ffep->name); 1250 fuse_dent_attach(tdfnp, ffep); 1251 1252 mtx_unlock(&ffnp->node_lock); 1253 mtx_unlock(&fdfnp->node_lock); 1254 mtx_unlock(&tdfnp->node_lock); 1255 1256 if (newname) 1257 kfree(newname, M_TEMP); 1258 1259 cache_rename(ap->a_fnch, ap->a_tnch); 1260 fuse_knote(fdvp, NOTE_WRITE); 1261 fuse_knote(tdvp, NOTE_WRITE); 1262 fuse_knote(fvp, NOTE_RENAME); 1263 out: 1264 if (tvp) 1265 vrele(tvp); 1266 1267 return error; 1268 } 1269 1270 static int 1271 fuse_vop_nsymlink(struct vop_nsymlink_args *ap) 1272 { 1273 struct vnode *dvp = ap->a_dvp; 1274 struct vnode *vp; 1275 struct namecache *ncp = ap->a_nch->ncp; 1276 struct fuse_mount *fmp = VFSTOFUSE(dvp->v_mount); 1277 struct fuse_node *dfnp = VTOI(dvp); 1278 struct fuse_node *fnp; 1279 struct fuse_ipc *fip; 1280 struct fuse_entry_out *feo; 1281 char *p; 1282 int error; 1283 1284 if (fuse_test_dead(fmp)) 1285 return ENOTCONN; 1286 1287 if (fuse_test_nosys(fmp, FUSE_SYMLINK)) 1288 return EOPNOTSUPP; 1289 1290 fip = fuse_ipc_get(fmp, strlen(ap->a_target) + 1 + ncp->nc_nlen + 1); 1291 p = fuse_ipc_fill(fip, FUSE_SYMLINK, dfnp->ino, ap->a_cred); 1292 1293 memcpy(p, ncp->nc_name, ncp->nc_nlen); 1294 p[ncp->nc_nlen] = '\0'; 1295 memcpy(p + ncp->nc_nlen + 1, ap->a_target, strlen(ap->a_target) + 1); 1296 1297 error = fuse_ipc_tx(fip); 1298 if (error) 1299 return error; 1300 1301 feo = fuse_out_data(fip); 1302 if (IFTOVT(feo->attr.mode) != VLNK) { 1303 fuse_ipc_put(fip); 1304 return EINVAL; 1305 } 1306 1307 error = fuse_alloc_node(dfnp, feo->nodeid, p, strlen(p), VLNK, &vp); 1308 if (error) { 1309 fuse_ipc_put(fip); 1310 return error; 1311 } 1312 KKASSERT(vp); 1313 KKASSERT(vn_islocked(vp)); 1314 1315 fnp = VTOI(vp); 1316 mtx_lock(&fnp->node_lock); 1317 fuse_set_attr(fnp, &feo->attr); 1318 mtx_unlock(&fnp->node_lock); 1319 1320 cache_setunresolved(ap->a_nch); 1321 cache_setvp(ap->a_nch, vp); 1322 *(ap->a_vpp) = vp; 1323 fuse_knote(vp, NOTE_WRITE); 1324 1325 /* unused */ 1326 //feo->generation; 1327 //feo->entry_valid; 1328 //feo->attr_valid; 1329 //feo->entry_valid_nsec; 1330 //feo->attr_valid_nsec; 1331 1332 fuse_ipc_put(fip); 1333 1334 return 0; 1335 } 1336 1337 static int 1338 fuse_vop_read(struct vop_read_args *ap) 1339 { 1340 struct vnode *vp = ap->a_vp; 1341 struct uio *uio = ap->a_uio; 1342 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount); 1343 1344 fuse_dbg("ino=%ju ioflag=%x\n", VTOI(vp)->ino, ap->a_ioflag); 1345 1346 if (fuse_test_dead(fmp)) 1347 return ENOTCONN; 1348 1349 if (fuse_test_nosys(fmp, FUSE_READ)) 1350 return EOPNOTSUPP; 1351 1352 if (!uio->uio_resid) 1353 return 0; 1354 1355 return fuse_read(ap); 1356 } 1357 1358 static int 1359 fuse_vop_write(struct vop_write_args *ap) 1360 { 1361 struct vnode *vp = ap->a_vp; 1362 struct uio *uio = ap->a_uio; 1363 struct fuse_mount *fmp = VFSTOFUSE(vp->v_mount); 1364 1365 fuse_dbg("ino=%ju ioflag=%x\n", VTOI(vp)->ino, ap->a_ioflag); 1366 return EOPNOTSUPP; /* XXX disabled */ 1367 1368 if (fuse_test_dead(fmp)) 1369 return ENOTCONN; 1370 1371 if (fuse_test_nosys(fmp, FUSE_WRITE)) 1372 return EOPNOTSUPP; 1373 1374 if (!uio->uio_resid) 1375 return 0; 1376 1377 if (ap->a_ioflag & IO_DIRECT) 1378 return fuse_dio_write(ap); 1379 else 1380 return fuse_write(ap); 1381 } 1382 1383 static int 1384 fuse_vop_strategy(struct vop_strategy_args *ap) 1385 { 1386 struct bio *bio = ap->a_bio; 1387 struct buf *bp = bio->bio_buf; 1388 1389 fuse_dbg("ino=%ju b_cmd=%d\n", VTOI(ap->a_vp)->ino, bp->b_cmd); 1390 1391 bp->b_resid = 0; 1392 bp->b_error = 0; 1393 biodone(bio); 1394 1395 return 0; 1396 } 1397 1398 static int 1399 fuse_bmap(struct vop_bmap_args *ap) 1400 { 1401 fuse_dbg("ino=%ju a_cmd=%d a_loffset=%ju\n", 1402 VTOI(ap->a_vp)->ino, ap->a_cmd, ap->a_loffset); 1403 1404 return EOPNOTSUPP; 1405 } 1406 1407 static int 1408 fuse_vop_print(struct vop_print_args *ap) 1409 { 1410 struct fuse_node *fnp = VTOI(ap->a_vp); 1411 1412 fuse_print("tag VT_FUSE, node %p, ino %ju, parent ino %ju\n", 1413 fnp, VTOI(ap->a_vp)->ino, VTOI(fnp->pfnp->vp)->ino); 1414 1415 return 0; 1416 } 1417 1418 static int 1419 fuse_vop_inactive(struct vop_inactive_args *ap) 1420 { 1421 struct vnode *vp = ap->a_vp; 1422 struct mount *mp = vp->v_mount; 1423 struct fuse_node *fnp = VTOI(vp); 1424 1425 lwkt_gettoken(&mp->mnt_token); 1426 if (!fnp) { 1427 vrecycle(ap->a_vp); 1428 lwkt_reltoken(&mp->mnt_token); 1429 return 0; 1430 } 1431 1432 fuse_dbg("ino=%ju nlink=%d\n", fnp->ino, fnp->nlink); 1433 vinvalbuf(vp, V_SAVE, 0, 0); 1434 lwkt_reltoken(&mp->mnt_token); 1435 1436 return 0; 1437 } 1438 1439 static int 1440 fuse_vop_reclaim(struct vop_reclaim_args *ap) 1441 { 1442 struct vnode *vp = ap->a_vp; 1443 struct mount *mp = vp->v_mount; 1444 struct fuse_node *fnp = VTOI(vp); 1445 1446 lwkt_gettoken(&mp->mnt_token); 1447 if (fnp) { 1448 fuse_dbg("ino=%ju\n", fnp->ino); 1449 fuse_node_free(fnp); 1450 vclrisdirty(vp); 1451 } 1452 lwkt_reltoken(&mp->mnt_token); 1453 1454 return 0; 1455 } 1456 1457 static int 1458 fuse_vop_mountctl(struct vop_mountctl_args *ap) 1459 { 1460 struct mount *mp; 1461 int res = 0; 1462 1463 mp = ap->a_head.a_ops->head.vv_mount; 1464 lwkt_gettoken(&mp->mnt_token); 1465 1466 switch (ap->a_op) { 1467 //case MOUNTCTL_MOUNTFLAGS: 1468 // ... 1469 // break; 1470 default: 1471 res = vop_stdmountctl(ap); 1472 break; 1473 } 1474 1475 lwkt_reltoken(&mp->mnt_token); 1476 return res; 1477 } 1478 1479 static void filt_fusedetach(struct knote*); 1480 static int filt_fuseread(struct knote*, long); 1481 static int filt_fusewrite(struct knote*, long); 1482 static int filt_fusevnode(struct knote*, long); 1483 1484 static struct filterops fuseread_filtops = 1485 { FILTEROP_ISFD | FILTEROP_MPSAFE, 1486 NULL, filt_fusedetach, filt_fuseread }; 1487 static struct filterops fusewrite_filtops = 1488 { FILTEROP_ISFD | FILTEROP_MPSAFE, 1489 NULL, filt_fusedetach, filt_fusewrite }; 1490 static struct filterops fusevnode_filtops = 1491 { FILTEROP_ISFD | FILTEROP_MPSAFE, 1492 NULL, filt_fusedetach, filt_fusevnode }; 1493 1494 static int 1495 fuse_kqfilter(struct vop_kqfilter_args *ap) 1496 { 1497 struct vnode *vp = ap->a_vp; 1498 struct knote *kn = ap->a_kn; 1499 1500 switch (kn->kn_filter) { 1501 case EVFILT_READ: 1502 kn->kn_fop = &fuseread_filtops; 1503 break; 1504 case EVFILT_WRITE: 1505 kn->kn_fop = &fusewrite_filtops; 1506 break; 1507 case EVFILT_VNODE: 1508 kn->kn_fop = &fusevnode_filtops; 1509 break; 1510 default: 1511 return EOPNOTSUPP; 1512 } 1513 1514 kn->kn_hook = (caddr_t)vp; 1515 knote_insert(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn); 1516 1517 return 0; 1518 } 1519 1520 static void 1521 filt_fusedetach(struct knote *kn) 1522 { 1523 struct vnode *vp = (void*)kn->kn_hook; 1524 1525 knote_remove(&vp->v_pollinfo.vpi_kqinfo.ki_note, kn); 1526 } 1527 1528 static int 1529 filt_fuseread(struct knote *kn, long hint) 1530 { 1531 struct vnode *vp = (void*)kn->kn_hook; 1532 struct fuse_node *fnp = VTOI(vp); 1533 off_t off; 1534 1535 if (hint == NOTE_REVOKE) { 1536 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); 1537 return 1; 1538 } 1539 1540 /* 1541 * Interlock against MP races when performing this function. 1542 */ 1543 mtx_lock(&fnp->node_lock); 1544 off = fnp->size - kn->kn_fp->f_offset; 1545 kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX; 1546 if (kn->kn_sfflags & NOTE_OLDAPI) { 1547 mtx_unlock(&fnp->node_lock); 1548 return 1; 1549 } 1550 if (!kn->kn_data) 1551 kn->kn_data = (off < INTPTR_MAX) ? off : INTPTR_MAX; 1552 mtx_unlock(&fnp->node_lock); 1553 1554 return kn->kn_data != 0; 1555 } 1556 1557 static int 1558 filt_fusewrite(struct knote *kn, long hint) 1559 { 1560 if (hint == NOTE_REVOKE) 1561 kn->kn_flags |= (EV_EOF | EV_NODATA | EV_ONESHOT); 1562 kn->kn_data = 0; 1563 1564 return 1; 1565 } 1566 1567 static int 1568 filt_fusevnode(struct knote *kn, long hint) 1569 { 1570 if (kn->kn_sfflags & hint) 1571 kn->kn_fflags |= hint; 1572 if (hint == NOTE_REVOKE) { 1573 kn->kn_flags |= (EV_EOF | EV_NODATA); 1574 return 1; 1575 } 1576 1577 return kn->kn_fflags != 0; 1578 } 1579 1580 static int 1581 fuse_vop_getpages(struct vop_getpages_args *ap) 1582 { 1583 if (!ap->a_vp->v_mount) 1584 return VM_PAGER_BAD; 1585 1586 return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, ap->a_count, 1587 ap->a_reqpage, ap->a_seqaccess); 1588 } 1589 1590 static int 1591 fuse_vop_putpages(struct vop_putpages_args *ap) 1592 { 1593 if (!ap->a_vp->v_mount) 1594 return VM_PAGER_BAD; 1595 1596 return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count, 1597 ap->a_flags, ap->a_rtvals); 1598 } 1599 1600 struct vop_ops fuse_vnode_vops = { 1601 .vop_default = vop_defaultop, 1602 .vop_access = fuse_vop_access, 1603 .vop_open = fuse_vop_open, 1604 .vop_close = fuse_vop_close, 1605 .vop_fsync = fuse_vop_fsync, 1606 .vop_getattr = fuse_vop_getattr, 1607 .vop_setattr = fuse_vop_setattr, 1608 .vop_nresolve = fuse_vop_nresolve, 1609 //.vop_nlookupdotdot = fuse_nlookupdotdot, 1610 .vop_nlink = fuse_vop_nlink, 1611 .vop_ncreate = fuse_vop_ncreate, 1612 .vop_nmknod = fuse_vop_nmknod, 1613 .vop_nremove = fuse_vop_nremove, 1614 .vop_nmkdir = fuse_vop_nmkdir, 1615 .vop_nrmdir = fuse_vop_nrmdir, 1616 .vop_pathconf = fuse_vop_pathconf, 1617 .vop_readdir = fuse_vop_readdir, 1618 .vop_readlink = fuse_vop_readlink, 1619 .vop_nrename = fuse_vop_nrename, 1620 .vop_nsymlink = fuse_vop_nsymlink, 1621 .vop_read = fuse_vop_read, 1622 .vop_write = fuse_vop_write, 1623 .vop_strategy = fuse_vop_strategy, 1624 .vop_bmap = fuse_bmap, 1625 //.vop_advlock = fuse_advlock, 1626 .vop_print = fuse_vop_print, 1627 .vop_inactive = fuse_vop_inactive, 1628 .vop_reclaim = fuse_vop_reclaim, 1629 .vop_mountctl = fuse_vop_mountctl, 1630 .vop_kqfilter = fuse_kqfilter, 1631 .vop_getpages = fuse_vop_getpages, 1632 .vop_putpages = fuse_vop_putpages, 1633 }; 1634 1635 struct vop_ops fuse_spec_vops = { 1636 .vop_default = vop_defaultop, 1637 .vop_access = fuse_vop_access, 1638 .vop_close = fuse_vop_close, 1639 .vop_fsync = fuse_vop_fsync, 1640 .vop_getattr = fuse_vop_getattr, 1641 .vop_setattr = fuse_vop_setattr, 1642 .vop_read = vop_stdnoread, 1643 .vop_write = vop_stdnowrite, 1644 //.vop_markatime = fuse_vop_markatime, 1645 .vop_print = fuse_vop_print, 1646 .vop_inactive = fuse_vop_inactive, 1647 .vop_reclaim = fuse_vop_reclaim, 1648 }; 1649