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