1 /* $NetBSD: p2k.c,v 1.7 2008/12/12 19:50:27 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/cdefs.h> 46 #include <sys/mount.h> 47 #include <sys/param.h> 48 #include <sys/vnode.h> 49 #include <sys/lock.h> 50 #include <sys/namei.h> 51 #include <sys/dirent.h> 52 53 #include <assert.h> 54 #include <errno.h> 55 #include <puffs.h> 56 #include <stdlib.h> 57 58 #include <rump/rump.h> 59 #include <rump/p2k.h> 60 #include <rump/ukfs.h> 61 62 PUFFSOP_PROTOS(p2k) 63 64 static kauth_cred_t 65 cred_create(const struct puffs_cred *pcr) 66 { 67 gid_t groups[NGROUPS]; 68 uid_t uid; 69 gid_t gid; 70 short ngroups = 0; 71 72 if (puffs_cred_getuid(pcr, &uid) == -1) 73 uid = 0; 74 if (puffs_cred_getgid(pcr, &gid) == -1) 75 gid = 0; 76 puffs_cred_getgroups(pcr, groups, &ngroups); 77 78 /* LINTED: ngroups is ok */ 79 return rump_cred_create(uid, gid, ngroups, groups); 80 } 81 82 static __inline void 83 cred_destroy(kauth_cred_t cred) 84 { 85 86 rump_cred_destroy(cred); 87 } 88 89 static struct componentname * 90 makecn(const struct puffs_cn *pcn) 91 { 92 kauth_cred_t cred; 93 94 cred = cred_create(pcn->pcn_cred); 95 /* LINTED: prehistoric types in first two args */ 96 return rump_makecn(pcn->pcn_nameiop, pcn->pcn_flags, pcn->pcn_name, 97 pcn->pcn_namelen, cred, curlwp); 98 } 99 100 static __inline void 101 freecn(struct componentname *cnp, int flags) 102 { 103 104 rump_freecn(cnp, flags | RUMPCN_FREECRED); 105 } 106 107 static void 108 makelwp(struct puffs_usermount *pu) 109 { 110 pid_t pid; 111 lwpid_t lid; 112 113 puffs_cc_getcaller(puffs_cc_getcc(pu), &pid, &lid); 114 rump_setup_curlwp(pid, lid, 1); 115 } 116 117 /*ARGSUSED*/ 118 static void 119 clearlwp(struct puffs_usermount *pu) 120 { 121 122 /* 123 * XXX: because of the vnode reference counting lossage, we 124 * can't clear the curlwp if we unmounted succesfully. 125 * Therefore, don't do it to avoid a diagnostic panic. 126 * So this currently leaks a process structure in that case, 127 * but since p2k is rarely used multiple times in a single 128 * process, it's more like a feature than a bug (yea, I'm 129 * good at lying to myself). 130 */ 131 if (__predict_false(puffs_getstate(pu) != PUFFS_STATE_UNMOUNTED)) 132 rump_clear_curlwp(); 133 } 134 135 int 136 p2k_run_fs(const char *vfsname, const char *devpath, const char *mountpath, 137 int mntflags, void *arg, size_t alen, uint32_t puffs_flags) 138 { 139 char typebuf[PUFFS_TYPELEN]; 140 struct puffs_ops *pops; 141 struct puffs_usermount *pu = NULL; 142 struct puffs_node *pn_root; 143 struct vnode *rvp; 144 struct ukfs *ukfs = NULL; 145 extern int puffs_fakecc; 146 int rv = -1, sverrno; 147 bool dodaemon; 148 149 PUFFSOP_INIT(pops); 150 151 PUFFSOP_SET(pops, p2k, fs, statvfs); 152 PUFFSOP_SET(pops, p2k, fs, unmount); 153 PUFFSOP_SET(pops, p2k, fs, sync); 154 PUFFSOP_SET(pops, p2k, fs, fhtonode); 155 PUFFSOP_SET(pops, p2k, fs, nodetofh); 156 157 PUFFSOP_SET(pops, p2k, node, lookup); 158 PUFFSOP_SET(pops, p2k, node, create); 159 PUFFSOP_SET(pops, p2k, node, mknod); 160 PUFFSOP_SET(pops, p2k, node, open); 161 PUFFSOP_SET(pops, p2k, node, close); 162 PUFFSOP_SET(pops, p2k, node, access); 163 PUFFSOP_SET(pops, p2k, node, getattr); 164 PUFFSOP_SET(pops, p2k, node, setattr); 165 #if 0 166 PUFFSOP_SET(pops, p2k, node, poll); 167 #endif 168 PUFFSOP_SET(pops, p2k, node, mmap); 169 PUFFSOP_SET(pops, p2k, node, fsync); 170 PUFFSOP_SET(pops, p2k, node, seek); 171 PUFFSOP_SET(pops, p2k, node, remove); 172 PUFFSOP_SET(pops, p2k, node, link); 173 PUFFSOP_SET(pops, p2k, node, rename); 174 PUFFSOP_SET(pops, p2k, node, mkdir); 175 PUFFSOP_SET(pops, p2k, node, rmdir); 176 PUFFSOP_SET(pops, p2k, node, symlink); 177 PUFFSOP_SET(pops, p2k, node, readdir); 178 PUFFSOP_SET(pops, p2k, node, readlink); 179 PUFFSOP_SET(pops, p2k, node, read); 180 PUFFSOP_SET(pops, p2k, node, write); 181 182 PUFFSOP_SET(pops, p2k, node, inactive); 183 PUFFSOP_SET(pops, p2k, node, reclaim); 184 185 dodaemon = true; 186 if (getenv("P2K_DEBUG") != NULL) { 187 puffs_flags |= PUFFS_FLAG_OPDUMP; 188 dodaemon = false; 189 } 190 191 strcpy(typebuf, "p2k|"); 192 if (strcmp(vfsname, "puffs") == 0) { /* XXX */ 193 struct puffs_kargs *args = arg; 194 strlcat(typebuf, args->pa_typename, sizeof(typebuf)); 195 dodaemon = false; 196 } else { 197 strlcat(typebuf, vfsname, sizeof(typebuf)); 198 } 199 200 pu = puffs_init(pops, devpath, typebuf, NULL, puffs_flags); 201 if (pu == NULL) 202 goto out; 203 204 if (dodaemon) 205 puffs_daemon(pu, 1, 1); 206 207 if (ukfs_init() == -1) 208 return -1; 209 ukfs = ukfs_mount(vfsname, devpath, mountpath, mntflags, arg, alen); 210 if (ukfs == NULL) 211 goto out; 212 213 rvp = ukfs_getrvp(ukfs); 214 pn_root = puffs_pn_new(pu, rvp); 215 puffs_setroot(pu, pn_root); 216 puffs_setfhsize(pu, 0, PUFFS_FHFLAG_PASSTHROUGH); 217 puffs_setstacksize(pu, PUFFS_STACKSIZE_MIN); 218 puffs_fakecc = 1; 219 220 puffs_set_prepost(pu, makelwp, clearlwp); 221 222 puffs_setspecific(pu, ukfs_getmp(ukfs)); 223 if ((rv = puffs_mount(pu, mountpath, mntflags, rvp))== -1) 224 goto out; 225 rv = puffs_mainloop(pu); 226 puffs_exit(pu, 1); 227 pu = NULL; 228 229 out: 230 sverrno = errno; 231 if (ukfs) 232 ukfs_release(ukfs, UKFS_RELFLAG_NOUNMOUNT); 233 if (pu) 234 puffs_cancel(pu, sverrno); 235 if (rv) { 236 errno = sverrno; 237 rv = -1; 238 } 239 240 return rv; 241 } 242 243 /* XXX: vn_lock() */ 244 #define VLE(a) RUMP_VOP_LOCK(a, LK_EXCLUSIVE) 245 #define VLS(a) RUMP_VOP_LOCK(a, LK_SHARED) 246 #define VUL(a) RUMP_VOP_UNLOCK(a, 0); 247 #define AUL(a) assert(RUMP_VOP_ISLOCKED(a) == 0) 248 249 int 250 p2k_fs_statvfs(struct puffs_usermount *pu, struct statvfs *sbp) 251 { 252 struct mount *mp = puffs_getspecific(pu); 253 254 return rump_vfs_statvfs(mp, sbp); 255 } 256 257 int 258 p2k_fs_unmount(struct puffs_usermount *pu, int flags) 259 { 260 struct mount *mp = puffs_getspecific(pu); 261 struct puffs_node *pn_root = puffs_getroot(pu); 262 struct vnode *rvp = pn_root->pn_data, *rvp2; 263 int rv; 264 265 /* 266 * We recycle the root node already here (god knows how 267 * many references it has due to lookup). This is good 268 * because VFS_UNMOUNT would do it anyway. But it is 269 * very bad if VFS_UNMOUNT fails for a reason or another 270 * (puffs guards against busy fs, but there might be other 271 * reasons). 272 * 273 * Theoretically we're going south, sinking fast & dying 274 * out here because the old vnode will be freed and we are 275 * unlikely to get a vnode at the same address. But try 276 * anyway. 277 * 278 * XXX: reallyfixmesomeday. either introduce VFS_ROOT to 279 * puffs (blah) or check the cookie in every routine 280 * against the root cookie, which might change (blah2). 281 */ 282 rump_vp_recycle_nokidding(rvp); 283 rv = rump_vfs_unmount(mp, flags); 284 if (rv) { 285 int rv2; 286 287 rv2 = rump_vfs_root(mp, &rvp2, 0); 288 assert(rv2 == 0 && rvp == rvp2); 289 } 290 return rv; 291 } 292 293 int 294 p2k_fs_sync(struct puffs_usermount *pu, int waitfor, 295 const struct puffs_cred *pcr) 296 { 297 struct mount *mp = puffs_getspecific(pu); 298 kauth_cred_t cred; 299 int rv; 300 301 cred = cred_create(pcr); 302 rv = rump_vfs_sync(mp, waitfor, (kauth_cred_t)cred); 303 cred_destroy(cred); 304 305 rump_bioops_sync(); 306 307 return rv; 308 } 309 310 /*ARGSUSED*/ 311 int 312 p2k_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize, 313 struct puffs_newinfo *pni) 314 { 315 struct mount *mp = puffs_getspecific(pu); 316 struct vnode *vp; 317 enum vtype vtype; 318 voff_t vsize; 319 dev_t rdev; 320 int rv; 321 322 rv = rump_vfs_fhtovp(mp, fid, &vp); 323 if (rv) 324 return rv; 325 326 puffs_newinfo_setcookie(pni, vp); 327 rump_getvninfo(vp, &vtype, &vsize, &rdev); 328 puffs_newinfo_setvtype(pni, vtype); 329 puffs_newinfo_setsize(pni, vsize); 330 puffs_newinfo_setrdev(pni, rdev); 331 332 return 0; 333 } 334 335 /*ARGSUSED*/ 336 int 337 p2k_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie, void *fid, 338 size_t *fidsize) 339 { 340 struct vnode *vp = cookie; 341 342 return rump_vfs_vptofh(vp, fid, fidsize); 343 } 344 345 /*ARGSUSED*/ 346 int 347 p2k_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc, 348 struct puffs_newinfo *pni, const struct puffs_cn *pcn) 349 { 350 struct componentname *cn; 351 struct vnode *vp; 352 enum vtype vtype; 353 voff_t vsize; 354 dev_t rdev; 355 int rv; 356 357 cn = makecn(pcn); 358 VLE(opc); 359 rv = RUMP_VOP_LOOKUP(opc, &vp, cn); 360 VUL(opc); 361 freecn(cn, RUMPCN_ISLOOKUP); 362 if (rv) { 363 if (rv == EJUSTRETURN) 364 rv = ENOENT; 365 return rv; 366 } 367 VUL(vp); 368 369 puffs_newinfo_setcookie(pni, vp); 370 rump_getvninfo(vp, &vtype, &vsize, &rdev); 371 puffs_newinfo_setvtype(pni, vtype); 372 puffs_newinfo_setsize(pni, vsize); 373 puffs_newinfo_setrdev(pni, rdev); 374 375 return 0; 376 } 377 378 /*ARGSUSED*/ 379 int 380 p2k_node_create(struct puffs_usermount *pu, puffs_cookie_t opc, 381 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 382 const struct vattr *vap) 383 { 384 struct componentname *cn; 385 struct vnode *vp; 386 int rv; 387 388 cn = makecn(pcn); 389 VLE(opc); 390 rump_vp_incref(opc); 391 rv = RUMP_VOP_CREATE(opc, &vp, cn, __UNCONST(vap)); 392 AUL(opc); 393 freecn(cn, 0); 394 if (rv == 0) { 395 VUL(vp); 396 puffs_newinfo_setcookie(pni, vp); 397 } 398 399 return rv; 400 } 401 402 /*ARGSUSED*/ 403 int 404 p2k_node_mknod(struct puffs_usermount *pu, puffs_cookie_t opc, 405 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 406 const struct vattr *vap) 407 { 408 struct componentname *cn; 409 struct vnode *vp; 410 int rv; 411 412 cn = makecn(pcn); 413 VLE(opc); 414 rump_vp_incref(opc); 415 rv = RUMP_VOP_MKNOD(opc, &vp, cn, __UNCONST(vap)); 416 AUL(opc); 417 freecn(cn, 0); 418 if (rv == 0) { 419 VUL(vp); 420 puffs_newinfo_setcookie(pni, vp); 421 } 422 423 return rv; 424 } 425 426 /*ARGSUSED*/ 427 int 428 p2k_node_open(struct puffs_usermount *pu, puffs_cookie_t opc, int mode, 429 const struct puffs_cred *pcr) 430 { 431 kauth_cred_t cred; 432 int rv; 433 434 cred = cred_create(pcr); 435 VLE(opc); 436 rv = RUMP_VOP_OPEN(opc, mode, cred); 437 VUL(opc); 438 cred_destroy(cred); 439 440 return rv; 441 } 442 443 /*ARGSUSED*/ 444 int 445 p2k_node_close(struct puffs_usermount *pu, puffs_cookie_t opc, int flags, 446 const struct puffs_cred *pcr) 447 { 448 kauth_cred_t cred; 449 450 cred = cred_create(pcr); 451 VLE(opc); 452 RUMP_VOP_CLOSE(opc, flags, cred); 453 VUL(opc); 454 cred_destroy(cred); 455 456 return 0; 457 } 458 459 /*ARGSUSED*/ 460 int 461 p2k_node_access(struct puffs_usermount *pu, puffs_cookie_t opc, int mode, 462 const struct puffs_cred *pcr) 463 { 464 kauth_cred_t cred; 465 int rv; 466 467 cred = cred_create(pcr); 468 VLE(opc); 469 rv = RUMP_VOP_ACCESS(opc, mode, cred); 470 VUL(opc); 471 cred_destroy(cred); 472 473 return rv; 474 } 475 476 /*ARGSUSED*/ 477 int 478 p2k_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc, 479 struct vattr *vap, const struct puffs_cred *pcr) 480 { 481 kauth_cred_t cred; 482 int rv; 483 484 cred = cred_create(pcr); 485 VLE(opc); 486 rv = RUMP_VOP_GETATTR(opc, vap, cred); 487 VUL(opc); 488 cred_destroy(cred); 489 490 return rv; 491 } 492 493 /*ARGSUSED*/ 494 int 495 p2k_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc, 496 const struct vattr *vap, const struct puffs_cred *pcr) 497 { 498 kauth_cred_t cred; 499 int rv; 500 501 cred = cred_create(pcr); 502 VLE(opc); 503 rv = RUMP_VOP_SETATTR(opc, __UNCONST(vap), cred); 504 VUL(opc); 505 cred_destroy(cred); 506 507 return rv; 508 } 509 510 /*ARGSUSED*/ 511 int 512 p2k_node_fsync(struct puffs_usermount *pu, puffs_cookie_t opc, 513 const struct puffs_cred *pcr, int flags, off_t offlo, off_t offhi) 514 { 515 kauth_cred_t cred; 516 int rv; 517 518 cred = cred_create(pcr); 519 VLE(opc); 520 rv = RUMP_VOP_FSYNC(opc, cred, flags, offlo, offhi); 521 VUL(opc); 522 cred_destroy(cred); 523 524 return rv; 525 } 526 527 /*ARGSUSED*/ 528 int 529 p2k_node_mmap(struct puffs_usermount *pu, puffs_cookie_t opc, vm_prot_t flags, 530 const struct puffs_cred *pcr) 531 { 532 kauth_cred_t cred; 533 int rv; 534 535 cred = cred_create(pcr); 536 rv = RUMP_VOP_MMAP(opc, flags, cred); 537 cred_destroy(cred); 538 539 return rv; 540 } 541 542 /*ARGSUSED*/ 543 int 544 p2k_node_seek(struct puffs_usermount *pu, puffs_cookie_t opc, 545 off_t oldoff, off_t newoff, const struct puffs_cred *pcr) 546 { 547 kauth_cred_t cred; 548 int rv; 549 550 cred = cred_create(pcr); 551 VLE(opc); 552 rv = RUMP_VOP_SEEK(opc, oldoff, newoff, cred); 553 VUL(opc); 554 cred_destroy(cred); 555 556 return rv; 557 } 558 559 /*ARGSUSED*/ 560 int 561 p2k_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc, 562 puffs_cookie_t targ, const struct puffs_cn *pcn) 563 { 564 struct componentname *cn; 565 int rv; 566 567 cn = makecn(pcn); 568 VLE(opc); 569 rump_vp_incref(opc); 570 VLE(targ); 571 rump_vp_incref(targ); 572 rv = RUMP_VOP_REMOVE(opc, targ, cn); 573 AUL(opc); 574 AUL(targ); 575 freecn(cn, 0); 576 577 return rv; 578 } 579 580 /*ARGSUSED*/ 581 int 582 p2k_node_link(struct puffs_usermount *pu, puffs_cookie_t opc, 583 puffs_cookie_t targ, const struct puffs_cn *pcn) 584 { 585 struct componentname *cn; 586 int rv; 587 588 cn = makecn(pcn); 589 VLE(opc); 590 rump_vp_incref(opc); 591 rv = RUMP_VOP_LINK(opc, targ, cn); 592 freecn(cn, 0); 593 594 return rv; 595 } 596 597 /*ARGSUSED*/ 598 int 599 p2k_node_rename(struct puffs_usermount *pu, 600 puffs_cookie_t src_dir, puffs_cookie_t src, 601 const struct puffs_cn *pcn_src, 602 puffs_cookie_t targ_dir, puffs_cookie_t targ, 603 const struct puffs_cn *pcn_targ) 604 { 605 struct componentname *cn_src, *cn_targ; 606 int rv; 607 608 cn_src = makecn(pcn_src); 609 cn_targ = makecn(pcn_targ); 610 rump_vp_incref(src_dir); 611 rump_vp_incref(src); 612 VLE(targ_dir); 613 rump_vp_incref(targ_dir); 614 if (targ) { 615 VLE(targ); 616 rump_vp_incref(targ); 617 } 618 rv = RUMP_VOP_RENAME(src_dir, src, cn_src, targ_dir, targ, cn_targ); 619 AUL(targ_dir); 620 if (targ) 621 AUL(targ); 622 freecn(cn_src, 0); 623 freecn(cn_targ, 0); 624 625 return rv; 626 } 627 628 /*ARGSUSED*/ 629 int 630 p2k_node_mkdir(struct puffs_usermount *pu, puffs_cookie_t opc, 631 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 632 const struct vattr *vap) 633 { 634 struct componentname *cn; 635 struct vnode *vp; 636 int rv; 637 638 cn = makecn(pcn); 639 VLE(opc); 640 rump_vp_incref(opc); 641 rv = RUMP_VOP_MKDIR(opc, &vp, cn, __UNCONST(vap)); 642 AUL(opc); 643 freecn(cn, 0); 644 if (rv == 0) { 645 VUL(vp); 646 puffs_newinfo_setcookie(pni, vp); 647 } 648 649 return rv; 650 } 651 652 /*ARGSUSED*/ 653 int 654 p2k_node_rmdir(struct puffs_usermount *pu, puffs_cookie_t opc, 655 puffs_cookie_t targ, const struct puffs_cn *pcn) 656 { 657 struct componentname *cn; 658 int rv; 659 660 cn = makecn(pcn); 661 VLE(opc); 662 rump_vp_incref(opc); 663 VLE(targ); 664 rump_vp_incref(targ); 665 rv = RUMP_VOP_RMDIR(opc, targ, cn); 666 AUL(targ); 667 AUL(opc); 668 freecn(cn, 0); 669 670 return rv; 671 } 672 673 /*ARGSUSED*/ 674 int 675 p2k_node_symlink(struct puffs_usermount *pu, puffs_cookie_t opc, 676 struct puffs_newinfo *pni, const struct puffs_cn *pcn_src, 677 const struct vattr *vap, const char *link_target) 678 { 679 struct componentname *cn; 680 struct vnode *vp; 681 int rv; 682 683 cn = makecn(pcn_src); 684 VLE(opc); 685 rump_vp_incref(opc); 686 rv = RUMP_VOP_SYMLINK(opc, &vp, cn, 687 __UNCONST(vap), __UNCONST(link_target)); 688 AUL(opc); 689 freecn(cn, 0); 690 if (rv == 0) { 691 VUL(vp); 692 puffs_newinfo_setcookie(pni, vp); 693 } 694 695 return rv; 696 } 697 698 /*ARGSUSED*/ 699 int 700 p2k_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc, 701 struct dirent *dent, off_t *readoff, size_t *reslen, 702 const struct puffs_cred *pcr, int *eofflag, 703 off_t *cookies, size_t *ncookies) 704 { 705 kauth_cred_t cred; 706 struct uio *uio; 707 off_t *vop_cookies; 708 int vop_ncookies; 709 int rv; 710 711 cred = cred_create(pcr); 712 uio = rump_uio_setup(dent, *reslen, *readoff, RUMPUIO_READ); 713 VLS(opc); 714 if (cookies) { 715 rv = RUMP_VOP_READDIR(opc, uio, cred, eofflag, 716 &vop_cookies, &vop_ncookies); 717 memcpy(cookies, vop_cookies, vop_ncookies * sizeof(*cookies)); 718 *ncookies = vop_ncookies; 719 free(vop_cookies); 720 } else { 721 rv = RUMP_VOP_READDIR(opc, uio, cred, eofflag, NULL, NULL); 722 } 723 VUL(opc); 724 if (rv == 0) { 725 *reslen = rump_uio_getresid(uio); 726 *readoff = rump_uio_getoff(uio); 727 } 728 rump_uio_free(uio); 729 cred_destroy(cred); 730 731 return rv; 732 } 733 734 /*ARGSUSED*/ 735 int 736 p2k_node_readlink(struct puffs_usermount *pu, puffs_cookie_t opc, 737 const struct puffs_cred *pcr, char *linkname, size_t *linklen) 738 { 739 kauth_cred_t cred; 740 struct uio *uio; 741 int rv; 742 743 cred = cred_create(pcr); 744 uio = rump_uio_setup(linkname, *linklen, 0, RUMPUIO_READ); 745 VLE(opc); 746 rv = RUMP_VOP_READLINK(opc, uio, cred); 747 VUL(opc); 748 *linklen -= rump_uio_free(uio); 749 cred_destroy(cred); 750 751 return rv; 752 } 753 754 /*ARGSUSED*/ 755 int 756 p2k_node_read(struct puffs_usermount *pu, puffs_cookie_t opc, 757 uint8_t *buf, off_t offset, size_t *resid, 758 const struct puffs_cred *pcr, int ioflag) 759 { 760 kauth_cred_t cred; 761 struct uio *uio; 762 int rv; 763 764 cred = cred_create(pcr); 765 uio = rump_uio_setup(buf, *resid, offset, RUMPUIO_READ); 766 VLS(opc); 767 rv = RUMP_VOP_READ(opc, uio, ioflag, cred); 768 VUL(opc); 769 *resid = rump_uio_free(uio); 770 cred_destroy(cred); 771 772 return rv; 773 } 774 775 /*ARGSUSED*/ 776 int 777 p2k_node_write(struct puffs_usermount *pu, puffs_cookie_t opc, 778 uint8_t *buf, off_t offset, size_t *resid, 779 const struct puffs_cred *pcr, int ioflag) 780 { 781 kauth_cred_t cred; 782 struct uio *uio; 783 int rv; 784 785 cred = cred_create(pcr); 786 uio = rump_uio_setup(buf, *resid, offset, RUMPUIO_WRITE); 787 VLE(opc); 788 rv = RUMP_VOP_WRITE(opc, uio, ioflag, cred); 789 VUL(opc); 790 *resid = rump_uio_free(uio); 791 cred_destroy(cred); 792 793 return rv; 794 } 795 796 int 797 p2k_node_inactive(struct puffs_usermount *pu, puffs_cookie_t opc) 798 { 799 struct vnode *vp = opc; 800 bool recycle; 801 int rv; 802 803 rump_vp_interlock(vp); 804 (void) RUMP_VOP_PUTPAGES(vp, 0, 0, PGO_ALLPAGES); 805 VLE(vp); 806 rv = RUMP_VOP_INACTIVE(vp, &recycle); 807 if (recycle) 808 puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N1); 809 810 return rv; 811 } 812 813 /*ARGSUSED*/ 814 int 815 p2k_node_reclaim(struct puffs_usermount *pu, puffs_croissant_t opc) 816 { 817 818 rump_vp_recycle_nokidding(opc); 819 return 0; 820 } 821