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