1 /* $NetBSD: p2k.c,v 1.2 2008/07/30 18:10:38 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Antti Kantee. All Rights Reserved. 5 * 6 * Development of this software was supported by Google Summer of Code. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * puffs 2k, i.e. puffs 2 kernel. Converts the puffs protocol to 32 * the kernel vfs protocol and vice versa. 33 * 34 * A word about reference counting: puffs in the kernel is the king of 35 * reference counting. We must maintain a vnode alive and kicking 36 * until the kernel tells us to reclaim it. Therefore we make sure 37 * we never accidentally lose a vnode. Before calling operations which 38 * decrease the refcount we always bump the refcount up to compensate. 39 * Come inactive, if the file system thinks that the vnode should be 40 * put out of its misery, it will set the recycle flag. We use this 41 * to tell the kernel to reclaim the vnode. Only in reclaim do we 42 * really nuke the last reference. 43 */ 44 45 #include <sys/mount.h> 46 #include <sys/param.h> 47 #include <sys/vnode.h> 48 #include <sys/lock.h> 49 #include <sys/namei.h> 50 #include <sys/dirent.h> 51 52 #include <assert.h> 53 #include <errno.h> 54 #include <puffs.h> 55 #include <stdlib.h> 56 57 #include <rump/rump.h> 58 #include <rump/p2k.h> 59 #include <rump/ukfs.h> 60 61 PUFFSOP_PROTOS(p2k) 62 63 static kauth_cred_t 64 cred_create(const struct puffs_cred *pcr) 65 { 66 gid_t groups[NGROUPS]; 67 uid_t uid; 68 gid_t gid; 69 short ngroups = 0; 70 71 if (puffs_cred_getuid(pcr, &uid) == -1) 72 uid = 0; 73 if (puffs_cred_getgid(pcr, &gid) == -1) 74 gid = 0; 75 puffs_cred_getgroups(pcr, groups, &ngroups); 76 77 /* LINTED: ngroups is ok */ 78 return rump_cred_create(uid, gid, ngroups, groups); 79 } 80 81 static __inline void 82 cred_destroy(kauth_cred_t cred) 83 { 84 85 rump_cred_destroy(cred); 86 } 87 88 static struct componentname * 89 makecn(const struct puffs_cn *pcn) 90 { 91 kauth_cred_t cred; 92 93 cred = cred_create(pcn->pcn_cred); 94 /* LINTED: prehistoric types in first two args */ 95 return rump_makecn(pcn->pcn_nameiop, pcn->pcn_flags, pcn->pcn_name, 96 pcn->pcn_namelen, cred, curlwp); 97 } 98 99 static __inline void 100 freecn(struct componentname *cnp, int flags) 101 { 102 103 rump_freecn(cnp, flags | RUMPCN_FREECRED); 104 } 105 106 static void 107 makelwp(struct puffs_usermount *pu) 108 { 109 pid_t pid; 110 lwpid_t lid; 111 112 puffs_cc_getcaller(puffs_cc_getcc(pu), &pid, &lid); 113 rump_setup_curlwp(pid, lid, 1); 114 } 115 116 /*ARGSUSED*/ 117 static void 118 clearlwp(struct puffs_usermount *pu) 119 { 120 121 rump_clear_curlwp(); 122 } 123 124 int 125 p2k_run_fs(const char *vfsname, const char *devpath, const char *mountpath, 126 int mntflags, void *arg, size_t alen, uint32_t puffs_flags) 127 { 128 char typebuf[PUFFS_TYPELEN]; 129 struct puffs_ops *pops; 130 struct puffs_usermount *pu; 131 struct puffs_node *pn_root; 132 struct vnode *rvp; 133 struct ukfs *ukfs; 134 extern int puffs_fakecc; 135 int rv, sverrno; 136 137 rv = -1; 138 ukfs_init(); 139 ukfs = ukfs_mount(vfsname, devpath, mountpath, mntflags, arg, alen); 140 if (ukfs == NULL) 141 return -1; 142 143 PUFFSOP_INIT(pops); 144 145 PUFFSOP_SET(pops, p2k, fs, statvfs); 146 PUFFSOP_SET(pops, p2k, fs, unmount); 147 PUFFSOP_SET(pops, p2k, fs, sync); 148 PUFFSOP_SET(pops, p2k, fs, fhtonode); 149 PUFFSOP_SET(pops, p2k, fs, nodetofh); 150 151 PUFFSOP_SET(pops, p2k, node, lookup); 152 PUFFSOP_SET(pops, p2k, node, create); 153 PUFFSOP_SET(pops, p2k, node, mknod); 154 PUFFSOP_SET(pops, p2k, node, open); 155 PUFFSOP_SET(pops, p2k, node, close); 156 PUFFSOP_SET(pops, p2k, node, access); 157 PUFFSOP_SET(pops, p2k, node, getattr); 158 PUFFSOP_SET(pops, p2k, node, setattr); 159 #if 0 160 PUFFSOP_SET(pops, p2k, node, poll); 161 #endif 162 PUFFSOP_SET(pops, p2k, node, mmap); 163 PUFFSOP_SET(pops, p2k, node, fsync); 164 PUFFSOP_SET(pops, p2k, node, seek); 165 PUFFSOP_SET(pops, p2k, node, remove); 166 PUFFSOP_SET(pops, p2k, node, link); 167 PUFFSOP_SET(pops, p2k, node, rename); 168 PUFFSOP_SET(pops, p2k, node, mkdir); 169 PUFFSOP_SET(pops, p2k, node, rmdir); 170 PUFFSOP_SET(pops, p2k, node, symlink); 171 PUFFSOP_SET(pops, p2k, node, readdir); 172 PUFFSOP_SET(pops, p2k, node, readlink); 173 PUFFSOP_SET(pops, p2k, node, read); 174 PUFFSOP_SET(pops, p2k, node, write); 175 176 PUFFSOP_SET(pops, p2k, node, inactive); 177 PUFFSOP_SET(pops, p2k, node, reclaim); 178 179 strcpy(typebuf, "p2k|"); 180 if (strcmp(vfsname, "puffs") == 0) { /* XXX */ 181 struct puffs_kargs *args = arg; 182 strlcat(typebuf, args->pa_typename, sizeof(typebuf)); 183 } else { 184 strlcat(typebuf, vfsname, sizeof(typebuf)); 185 } 186 187 pu = puffs_init(pops, devpath, typebuf, ukfs_getmp(ukfs), puffs_flags); 188 if (pu == NULL) 189 goto out; 190 191 rvp = ukfs_getrvp(ukfs); 192 pn_root = puffs_pn_new(pu, rvp); 193 puffs_setroot(pu, pn_root); 194 puffs_setfhsize(pu, 0, PUFFS_FHFLAG_PASSTHROUGH); 195 puffs_setstacksize(pu, PUFFS_STACKSIZE_MIN); 196 puffs_fakecc = 1; 197 198 puffs_set_prepost(pu, makelwp, clearlwp); 199 200 if ((rv = puffs_mount(pu, mountpath, mntflags, rvp))== -1) 201 goto out; 202 rv = puffs_mainloop(pu); 203 204 out: 205 sverrno = errno; 206 ukfs_release(ukfs, UKFS_RELFLAG_NOUNMOUNT); 207 if (rv) { 208 errno = sverrno; 209 rv = -1; 210 } 211 212 return rv; 213 } 214 215 /* XXX: vn_lock() */ 216 #define VLE(a) RUMP_VOP_LOCK(a, LK_EXCLUSIVE) 217 #define VLS(a) RUMP_VOP_LOCK(a, LK_SHARED) 218 #define VUL(a) RUMP_VOP_UNLOCK(a, 0); 219 #define AUL(a) assert(RUMP_VOP_ISLOCKED(a) == 0) 220 221 int 222 p2k_fs_statvfs(struct puffs_usermount *pu, struct statvfs *sbp) 223 { 224 struct mount *mp = puffs_getspecific(pu); 225 226 return rump_vfs_statvfs(mp, sbp); 227 } 228 229 int 230 p2k_fs_unmount(struct puffs_usermount *pu, int flags) 231 { 232 struct mount *mp = puffs_getspecific(pu); 233 struct puffs_node *pn_root = puffs_getroot(pu); 234 struct vnode *rvp = pn_root->pn_data, *rvp2; 235 int rv; 236 237 /* 238 * We recycle the root node already here (god knows how 239 * many references it has due to lookup). This is good 240 * because VFS_UNMOUNT would do it anyway. But it is 241 * very bad if VFS_UNMOUNT fails for a reason or another 242 * (puffs guards against busy fs, but there might be other 243 * reasons). 244 * 245 * Theoretically we're going south, sinking fast & dying 246 * out here because the old vnode will be freed and we are 247 * unlikely to get a vnode at the same address. But try 248 * anyway. 249 * 250 * XXX: reallyfixmesomeday. either introduce VFS_ROOT to 251 * puffs (blah) or check the cookie in every routine 252 * against the root cookie, which might change (blah2). 253 */ 254 rump_vp_recycle_nokidding(rvp); 255 rv = rump_vfs_unmount(mp, flags); 256 if (rv) { 257 int rv2; 258 259 rv2 = rump_vfs_root(mp, &rvp2, 0); 260 assert(rv2 == 0 && rvp == rvp2); 261 } 262 return rv; 263 } 264 265 int 266 p2k_fs_sync(struct puffs_usermount *pu, int waitfor, 267 const struct puffs_cred *pcr) 268 { 269 struct mount *mp = puffs_getspecific(pu); 270 kauth_cred_t cred; 271 int rv; 272 273 cred = cred_create(pcr); 274 rv = rump_vfs_sync(mp, waitfor, (kauth_cred_t)cred); 275 cred_destroy(cred); 276 277 rump_bioops_sync(); 278 279 return rv; 280 } 281 282 /*ARGSUSED*/ 283 int 284 p2k_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize, 285 struct puffs_newinfo *pni) 286 { 287 struct mount *mp = puffs_getspecific(pu); 288 struct vnode *vp; 289 enum vtype vtype; 290 voff_t vsize; 291 dev_t rdev; 292 int rv; 293 294 rv = rump_vfs_fhtovp(mp, fid, &vp); 295 if (rv) 296 return rv; 297 298 puffs_newinfo_setcookie(pni, vp); 299 rump_getvninfo(vp, &vtype, &vsize, &rdev); 300 puffs_newinfo_setvtype(pni, vtype); 301 puffs_newinfo_setsize(pni, vsize); 302 puffs_newinfo_setrdev(pni, rdev); 303 304 return 0; 305 } 306 307 /*ARGSUSED*/ 308 int 309 p2k_fs_nodetofh(struct puffs_usermount *pu, void *cookie, void *fid, 310 size_t *fidsize) 311 { 312 struct vnode *vp = cookie; 313 314 return rump_vfs_vptofh(vp, fid, fidsize); 315 } 316 317 /*ARGSUSED*/ 318 int 319 p2k_node_lookup(struct puffs_usermount *pu, void *opc, 320 struct puffs_newinfo *pni, const struct puffs_cn *pcn) 321 { 322 struct componentname *cn; 323 struct vnode *vp; 324 enum vtype vtype; 325 voff_t vsize; 326 dev_t rdev; 327 int rv; 328 329 cn = makecn(pcn); 330 VLE(opc); 331 rv = RUMP_VOP_LOOKUP(opc, &vp, cn); 332 VUL(opc); 333 freecn(cn, RUMPCN_ISLOOKUP); 334 if (rv) { 335 if (rv == EJUSTRETURN) 336 rv = ENOENT; 337 return rv; 338 } 339 VUL(vp); 340 341 puffs_newinfo_setcookie(pni, vp); 342 rump_getvninfo(vp, &vtype, &vsize, &rdev); 343 puffs_newinfo_setvtype(pni, vtype); 344 puffs_newinfo_setsize(pni, vsize); 345 puffs_newinfo_setrdev(pni, rdev); 346 347 return 0; 348 } 349 350 /*ARGSUSED*/ 351 int 352 p2k_node_create(struct puffs_usermount *pu, void *opc, 353 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 354 const struct vattr *vap) 355 { 356 struct componentname *cn; 357 struct vnode *vp; 358 int rv; 359 360 cn = makecn(pcn); 361 VLE(opc); 362 rump_vp_incref(opc); 363 rv = RUMP_VOP_CREATE(opc, &vp, cn, __UNCONST(vap)); 364 AUL(opc); 365 freecn(cn, 0); 366 if (rv == 0) { 367 VUL(vp); 368 puffs_newinfo_setcookie(pni, vp); 369 } 370 371 return rv; 372 } 373 374 /*ARGSUSED*/ 375 int 376 p2k_node_mknod(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni, 377 const struct puffs_cn *pcn, const struct vattr *vap) 378 { 379 struct componentname *cn; 380 struct vnode *vp; 381 int rv; 382 383 cn = makecn(pcn); 384 VLE(opc); 385 rump_vp_incref(opc); 386 rv = RUMP_VOP_MKNOD(opc, &vp, cn, __UNCONST(vap)); 387 AUL(opc); 388 freecn(cn, 0); 389 if (rv == 0) { 390 VUL(vp); 391 puffs_newinfo_setcookie(pni, vp); 392 } 393 394 return rv; 395 } 396 397 /*ARGSUSED*/ 398 int 399 p2k_node_open(struct puffs_usermount *pu, void *opc, int mode, 400 const struct puffs_cred *pcr) 401 { 402 kauth_cred_t cred; 403 int rv; 404 405 cred = cred_create(pcr); 406 VLE(opc); 407 rv = RUMP_VOP_OPEN(opc, mode, cred); 408 VUL(opc); 409 cred_destroy(cred); 410 411 return rv; 412 } 413 414 /*ARGSUSED*/ 415 int 416 p2k_node_close(struct puffs_usermount *pu, void *opc, int flags, 417 const struct puffs_cred *pcr) 418 { 419 kauth_cred_t cred; 420 421 cred = cred_create(pcr); 422 VLE(opc); 423 RUMP_VOP_CLOSE(opc, flags, cred); 424 VUL(opc); 425 cred_destroy(cred); 426 427 return 0; 428 } 429 430 /*ARGSUSED*/ 431 int 432 p2k_node_access(struct puffs_usermount *pu, void *opc, int mode, 433 const struct puffs_cred *pcr) 434 { 435 kauth_cred_t cred; 436 int rv; 437 438 cred = cred_create(pcr); 439 VLE(opc); 440 rv = RUMP_VOP_ACCESS(opc, mode, cred); 441 VUL(opc); 442 cred_destroy(cred); 443 444 return rv; 445 } 446 447 /*ARGSUSED*/ 448 int 449 p2k_node_getattr(struct puffs_usermount *pu, void *opc, struct vattr *vap, 450 const struct puffs_cred *pcr) 451 { 452 kauth_cred_t cred; 453 int rv; 454 455 cred = cred_create(pcr); 456 VLE(opc); 457 rv = RUMP_VOP_GETATTR(opc, vap, cred); 458 VUL(opc); 459 cred_destroy(cred); 460 461 return rv; 462 } 463 464 /*ARGSUSED*/ 465 int 466 p2k_node_setattr(struct puffs_usermount *pu, void *opc, const struct vattr *vap, 467 const struct puffs_cred *pcr) 468 { 469 kauth_cred_t cred; 470 int rv; 471 472 cred = cred_create(pcr); 473 VLE(opc); 474 rv = RUMP_VOP_SETATTR(opc, __UNCONST(vap), cred); 475 VUL(opc); 476 cred_destroy(cred); 477 478 return rv; 479 } 480 481 /*ARGSUSED*/ 482 int 483 p2k_node_fsync(struct puffs_usermount *pu, void *opc, 484 const struct puffs_cred *pcr, int flags, off_t offlo, off_t offhi) 485 { 486 kauth_cred_t cred; 487 int rv; 488 489 cred = cred_create(pcr); 490 VLE(opc); 491 rv = RUMP_VOP_FSYNC(opc, cred, flags, offlo, offhi); 492 VUL(opc); 493 cred_destroy(cred); 494 495 return rv; 496 } 497 498 /*ARGSUSED*/ 499 int 500 p2k_node_mmap(struct puffs_usermount *pu, void *opc, vm_prot_t flags, 501 const struct puffs_cred *pcr) 502 { 503 kauth_cred_t cred; 504 int rv; 505 506 cred = cred_create(pcr); 507 rv = RUMP_VOP_MMAP(opc, flags, cred); 508 cred_destroy(cred); 509 510 return rv; 511 } 512 513 /*ARGSUSED*/ 514 int 515 p2k_node_seek(struct puffs_usermount *pu, void *opc, off_t oldoff, off_t newoff, 516 const struct puffs_cred *pcr) 517 { 518 kauth_cred_t cred; 519 int rv; 520 521 cred = cred_create(pcr); 522 VLE(opc); 523 rv = RUMP_VOP_SEEK(opc, oldoff, newoff, cred); 524 VUL(opc); 525 cred_destroy(cred); 526 527 return rv; 528 } 529 530 /*ARGSUSED*/ 531 int 532 p2k_node_remove(struct puffs_usermount *pu, void *opc, void *targ, 533 const struct puffs_cn *pcn) 534 { 535 struct componentname *cn; 536 int rv; 537 538 cn = makecn(pcn); 539 VLE(opc); 540 rump_vp_incref(opc); 541 VLE(targ); 542 rump_vp_incref(targ); 543 rv = RUMP_VOP_REMOVE(opc, targ, cn); 544 AUL(opc); 545 AUL(targ); 546 freecn(cn, 0); 547 548 return rv; 549 } 550 551 /*ARGSUSED*/ 552 int 553 p2k_node_link(struct puffs_usermount *pu, void *opc, void *targ, 554 const struct puffs_cn *pcn) 555 { 556 struct componentname *cn; 557 int rv; 558 559 cn = makecn(pcn); 560 VLE(opc); 561 rump_vp_incref(opc); 562 rv = RUMP_VOP_LINK(opc, targ, cn); 563 freecn(cn, 0); 564 565 return rv; 566 } 567 568 /*ARGSUSED*/ 569 int 570 p2k_node_rename(struct puffs_usermount *pu, void *src_dir, void *src, 571 const struct puffs_cn *pcn_src, void *targ_dir, void *targ, 572 const struct puffs_cn *pcn_targ) 573 { 574 struct componentname *cn_src, *cn_targ; 575 int rv; 576 577 cn_src = makecn(pcn_src); 578 cn_targ = makecn(pcn_targ); 579 rump_vp_incref(src_dir); 580 rump_vp_incref(src); 581 VLE(targ_dir); 582 rump_vp_incref(targ_dir); 583 if (targ) { 584 VLE(targ); 585 rump_vp_incref(targ); 586 } 587 rv = RUMP_VOP_RENAME(src_dir, src, cn_src, targ_dir, targ, cn_targ); 588 AUL(targ_dir); 589 if (targ) 590 AUL(targ); 591 freecn(cn_src, 0); 592 freecn(cn_targ, 0); 593 594 return rv; 595 } 596 597 /*ARGSUSED*/ 598 int 599 p2k_node_mkdir(struct puffs_usermount *pu, void *opc, struct puffs_newinfo *pni, 600 const struct puffs_cn *pcn, const struct vattr *vap) 601 { 602 struct componentname *cn; 603 struct vnode *vp; 604 int rv; 605 606 cn = makecn(pcn); 607 VLE(opc); 608 rump_vp_incref(opc); 609 rv = RUMP_VOP_MKDIR(opc, &vp, cn, __UNCONST(vap)); 610 AUL(opc); 611 freecn(cn, 0); 612 if (rv == 0) { 613 VUL(vp); 614 puffs_newinfo_setcookie(pni, vp); 615 } 616 617 return rv; 618 } 619 620 /*ARGSUSED*/ 621 int 622 p2k_node_rmdir(struct puffs_usermount *pu, void *opc, void *targ, 623 const struct puffs_cn *pcn) 624 { 625 struct componentname *cn; 626 int rv; 627 628 cn = makecn(pcn); 629 VLE(opc); 630 rump_vp_incref(opc); 631 VLE(targ); 632 rump_vp_incref(targ); 633 rv = RUMP_VOP_RMDIR(opc, targ, cn); 634 AUL(targ); 635 AUL(opc); 636 freecn(cn, 0); 637 638 return rv; 639 } 640 641 /*ARGSUSED*/ 642 int 643 p2k_node_symlink(struct puffs_usermount *pu, void *opc, 644 struct puffs_newinfo *pni, const struct puffs_cn *pcn_src, 645 const struct vattr *vap, const char *link_target) 646 { 647 struct componentname *cn; 648 struct vnode *vp; 649 int rv; 650 651 cn = makecn(pcn_src); 652 VLE(opc); 653 rump_vp_incref(opc); 654 rv = RUMP_VOP_SYMLINK(opc, &vp, cn, 655 __UNCONST(vap), __UNCONST(link_target)); 656 AUL(opc); 657 freecn(cn, 0); 658 if (rv == 0) { 659 VUL(vp); 660 puffs_newinfo_setcookie(pni, vp); 661 } 662 663 return rv; 664 } 665 666 /*ARGSUSED*/ 667 int 668 p2k_node_readdir(struct puffs_usermount *pu, void *opc, struct dirent *dent, 669 off_t *readoff, size_t *reslen, const struct puffs_cred *pcr, 670 int *eofflag, off_t *cookies, size_t *ncookies) 671 { 672 kauth_cred_t cred; 673 struct uio *uio; 674 off_t *vop_cookies; 675 int vop_ncookies; 676 int rv; 677 678 cred = cred_create(pcr); 679 uio = rump_uio_setup(dent, *reslen, *readoff, RUMPUIO_READ); 680 VLS(opc); 681 if (cookies) { 682 rv = RUMP_VOP_READDIR(opc, uio, cred, eofflag, 683 &vop_cookies, &vop_ncookies); 684 memcpy(cookies, vop_cookies, vop_ncookies * sizeof(*cookies)); 685 *ncookies = vop_ncookies; 686 free(vop_cookies); 687 } else { 688 rv = RUMP_VOP_READDIR(opc, uio, cred, eofflag, NULL, NULL); 689 } 690 VUL(opc); 691 if (rv == 0) { 692 *reslen = rump_uio_getresid(uio); 693 *readoff = rump_uio_getoff(uio); 694 } 695 rump_uio_free(uio); 696 cred_destroy(cred); 697 698 return rv; 699 } 700 701 /*ARGSUSED*/ 702 int 703 p2k_node_readlink(struct puffs_usermount *pu, void *opc, 704 const struct puffs_cred *pcr, char *linkname, size_t *linklen) 705 { 706 kauth_cred_t cred; 707 struct uio *uio; 708 int rv; 709 710 cred = cred_create(pcr); 711 uio = rump_uio_setup(linkname, *linklen, 0, RUMPUIO_READ); 712 VLE(opc); 713 rv = RUMP_VOP_READLINK(opc, uio, cred); 714 VUL(opc); 715 *linklen -= rump_uio_free(uio); 716 cred_destroy(cred); 717 718 return rv; 719 } 720 721 /*ARGSUSED*/ 722 int 723 p2k_node_read(struct puffs_usermount *pu, void *opc, 724 uint8_t *buf, off_t offset, size_t *resid, 725 const struct puffs_cred *pcr, int ioflag) 726 { 727 kauth_cred_t cred; 728 struct uio *uio; 729 int rv; 730 731 cred = cred_create(pcr); 732 uio = rump_uio_setup(buf, *resid, offset, RUMPUIO_READ); 733 VLS(opc); 734 rv = RUMP_VOP_READ(opc, uio, ioflag, cred); 735 VUL(opc); 736 *resid = rump_uio_free(uio); 737 cred_destroy(cred); 738 739 return rv; 740 } 741 742 /*ARGSUSED*/ 743 int 744 p2k_node_write(struct puffs_usermount *pu, void *opc, 745 uint8_t *buf, off_t offset, size_t *resid, 746 const struct puffs_cred *pcr, int ioflag) 747 { 748 kauth_cred_t cred; 749 struct uio *uio; 750 int rv; 751 752 cred = cred_create(pcr); 753 uio = rump_uio_setup(buf, *resid, offset, RUMPUIO_WRITE); 754 VLE(opc); 755 rv = RUMP_VOP_WRITE(opc, uio, ioflag, cred); 756 VUL(opc); 757 *resid = rump_uio_free(uio); 758 cred_destroy(cred); 759 760 return rv; 761 } 762 763 int 764 p2k_node_inactive(struct puffs_usermount *pu, void *opc) 765 { 766 struct vnode *vp = opc; 767 bool recycle; 768 int rv; 769 770 rump_vp_interlock(vp); 771 (void) RUMP_VOP_PUTPAGES(vp, 0, 0, PGO_ALLPAGES); 772 VLE(vp); 773 rv = RUMP_VOP_INACTIVE(vp, &recycle); 774 if (recycle) 775 puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N1); 776 777 return rv; 778 } 779 780 /*ARGSUSED*/ 781 int 782 p2k_node_reclaim(struct puffs_usermount *pu, void *opc) 783 { 784 785 rump_vp_recycle_nokidding(opc); 786 return 0; 787 } 788