1 /* $NetBSD: dispatcher.c,v 1.30 2008/01/28 18:35:50 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved. 5 * 6 * Development of this software was supported by the 7 * Ulla Tuominen Foundation, the Finnish Cultural Foundation and 8 * Research Foundation of Helsinki University of Technology. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #if !defined(lint) 34 __RCSID("$NetBSD: dispatcher.c,v 1.30 2008/01/28 18:35:50 pooka Exp $"); 35 #endif /* !lint */ 36 37 #include <sys/types.h> 38 #include <sys/poll.h> 39 40 #include <assert.h> 41 #include <errno.h> 42 #ifdef PUFFS_WITH_THREADS 43 #include <pthread.h> 44 #endif 45 #include <puffs.h> 46 #include <puffsdump.h> 47 #include <stdio.h> 48 #include <stdlib.h> 49 #include <unistd.h> 50 51 #include "puffs_priv.h" 52 53 #if 0 /* me not worka now */ 54 /* 55 * Set the following to 1 to handle each request in a separate pthread. 56 * This is not exported as it should not be used yet unless having a 57 * very good knowledge of what you're signing up for (libpuffs is not 58 * threadsafe). 59 */ 60 int puffs_usethreads; 61 #endif 62 63 static void dispatch(struct puffs_cc *); 64 65 /* for our eyes only */ 66 void 67 puffs__ml_dispatch(struct puffs_usermount *pu, struct puffs_framebuf *pb) 68 { 69 struct puffs_cc *pcc = puffs_cc_getcc(pu); 70 struct puffs_req *preq; 71 72 pcc->pcc_pb = pb; 73 pcc->pcc_flags |= PCC_MLCONT; 74 dispatch(pcc); 75 76 /* Put result to kernel sendqueue if necessary */ 77 preq = puffs__framebuf_getdataptr(pcc->pcc_pb); 78 if (PUFFSOP_WANTREPLY(preq->preq_opclass)) { 79 if (pu->pu_flags & PUFFS_FLAG_OPDUMP) 80 puffsdump_rv(preq); 81 82 puffs_framev_enqueue_justsend(pu, pu->pu_fd, 83 pcc->pcc_pb, 0, 0); 84 } else { 85 puffs_framebuf_destroy(pcc->pcc_pb); 86 } 87 88 /* who needs information when you're living on borrowed time? */ 89 if (pcc->pcc_flags & PCC_BORROWED) { 90 puffs_cc_yield(pcc); /* back to borrow source */ 91 } 92 pcc->pcc_flags = 0; 93 } 94 95 /* public, but not really tested and only semi-supported */ 96 int 97 puffs_dispatch_create(struct puffs_usermount *pu, struct puffs_framebuf *pb, 98 struct puffs_cc **pccp) 99 { 100 struct puffs_cc *pcc; 101 102 if (puffs__cc_create(pu, dispatch, &pcc) == -1) 103 return -1; 104 105 pcc->pcc_pb = pb; 106 *pccp = pcc; 107 108 return 0; 109 } 110 111 int 112 puffs_dispatch_exec(struct puffs_cc *pcc, struct puffs_framebuf **pbp) 113 { 114 int rv; 115 116 puffs_cc_continue(pcc); 117 118 if (pcc->pcc_flags & PCC_DONE) { 119 rv = 1; 120 *pbp = pcc->pcc_pb; 121 pcc->pcc_flags = 0; 122 puffs__cc_destroy(pcc, 0); 123 } else { 124 rv = 0; 125 } 126 127 return rv; 128 } 129 130 static void 131 dispatch(struct puffs_cc *pcc) 132 { 133 struct puffs_usermount *pu = pcc->pcc_pu; 134 struct puffs_ops *pops = &pu->pu_ops; 135 struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb); 136 void *auxbuf = preq; /* help with typecasting */ 137 void *opcookie = preq->preq_cookie; 138 int error, buildpath; 139 140 assert((pcc->pcc_flags & PCC_DONE) == 0); 141 142 buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH; 143 preq->preq_setbacks = 0; 144 145 if (pu->pu_flags & PUFFS_FLAG_OPDUMP) 146 puffsdump_req(preq); 147 148 puffs__cc_setcaller(pcc, preq->preq_pid, preq->preq_lid); 149 150 /* pre-operation */ 151 if (pu->pu_oppre) 152 pu->pu_oppre(pu); 153 154 /* Execute actual operation */ 155 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) { 156 switch (preq->preq_optype) { 157 case PUFFS_VFS_UNMOUNT: 158 { 159 struct puffs_vfsmsg_unmount *auxt = auxbuf; 160 161 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTING); 162 error = pops->puffs_fs_unmount(pu, auxt->pvfsr_flags); 163 if (!error) 164 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED); 165 else 166 PU_SETSTATE(pu, PUFFS_STATE_RUNNING); 167 break; 168 } 169 170 case PUFFS_VFS_STATVFS: 171 { 172 struct puffs_vfsmsg_statvfs *auxt = auxbuf; 173 174 error = pops->puffs_fs_statvfs(pu, &auxt->pvfsr_sb); 175 break; 176 } 177 178 case PUFFS_VFS_SYNC: 179 { 180 struct puffs_vfsmsg_sync *auxt = auxbuf; 181 PUFFS_MAKECRED(pcr, &auxt->pvfsr_cred); 182 183 error = pops->puffs_fs_sync(pu, 184 auxt->pvfsr_waitfor, pcr); 185 break; 186 } 187 188 case PUFFS_VFS_FHTOVP: 189 { 190 struct puffs_vfsmsg_fhtonode *auxt = auxbuf; 191 struct puffs_newinfo pni; 192 193 pni.pni_cookie = &auxt->pvfsr_fhcookie; 194 pni.pni_vtype = &auxt->pvfsr_vtype; 195 pni.pni_size = &auxt->pvfsr_size; 196 pni.pni_rdev = &auxt->pvfsr_rdev; 197 198 error = pops->puffs_fs_fhtonode(pu, auxt->pvfsr_data, 199 auxt->pvfsr_dsize, &pni); 200 201 break; 202 } 203 204 case PUFFS_VFS_VPTOFH: 205 { 206 struct puffs_vfsmsg_nodetofh *auxt = auxbuf; 207 208 error = pops->puffs_fs_nodetofh(pu, 209 auxt->pvfsr_fhcookie, auxt->pvfsr_data, 210 &auxt->pvfsr_dsize); 211 212 break; 213 } 214 215 case PUFFS_VFS_SUSPEND: 216 { 217 struct puffs_vfsmsg_suspend *auxt = auxbuf; 218 219 error = 0; 220 if (pops->puffs_fs_suspend == NULL) 221 break; 222 223 pops->puffs_fs_suspend(pu, auxt->pvfsr_status); 224 break; 225 } 226 227 default: 228 /* 229 * I guess the kernel sees this one coming 230 */ 231 error = EINVAL; 232 break; 233 } 234 235 /* XXX: audit return values */ 236 /* XXX: sync with kernel */ 237 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) { 238 switch (preq->preq_optype) { 239 case PUFFS_VN_LOOKUP: 240 { 241 struct puffs_vnmsg_lookup *auxt = auxbuf; 242 struct puffs_newinfo pni; 243 struct puffs_cn pcn; 244 245 pcn.pcn_pkcnp = &auxt->pvnr_cn; 246 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 247 pni.pni_cookie = &auxt->pvnr_newnode; 248 pni.pni_vtype = &auxt->pvnr_vtype; 249 pni.pni_size = &auxt->pvnr_size; 250 pni.pni_rdev = &auxt->pvnr_rdev; 251 252 if (buildpath) { 253 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 254 if (error) 255 break; 256 } 257 258 /* lookup *must* be present */ 259 error = pops->puffs_node_lookup(pu, opcookie, 260 &pni, &pcn); 261 262 if (buildpath) { 263 if (error) { 264 pu->pu_pathfree(pu, &pcn.pcn_po_full); 265 } else { 266 struct puffs_node *pn; 267 268 /* 269 * did we get a new node or a 270 * recycled node? 271 */ 272 pn = PU_CMAP(pu, auxt->pvnr_newnode); 273 if (pn->pn_po.po_path == NULL) 274 pn->pn_po = pcn.pcn_po_full; 275 else 276 pu->pu_pathfree(pu, 277 &pcn.pcn_po_full); 278 } 279 } 280 281 break; 282 } 283 284 case PUFFS_VN_CREATE: 285 { 286 struct puffs_vnmsg_create *auxt = auxbuf; 287 struct puffs_newinfo pni; 288 struct puffs_cn pcn; 289 290 if (pops->puffs_node_create == NULL) { 291 error = 0; 292 break; 293 } 294 295 pcn.pcn_pkcnp = &auxt->pvnr_cn; 296 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 297 298 memset(&pni, 0, sizeof(pni)); 299 pni.pni_cookie = &auxt->pvnr_newnode; 300 301 if (buildpath) { 302 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 303 if (error) 304 break; 305 } 306 307 error = pops->puffs_node_create(pu, 308 opcookie, &pni, &pcn, &auxt->pvnr_va); 309 310 if (buildpath) { 311 if (error) { 312 pu->pu_pathfree(pu, &pcn.pcn_po_full); 313 } else { 314 struct puffs_node *pn; 315 316 pn = PU_CMAP(pu, auxt->pvnr_newnode); 317 pn->pn_po = pcn.pcn_po_full; 318 } 319 } 320 321 break; 322 } 323 324 case PUFFS_VN_MKNOD: 325 { 326 struct puffs_vnmsg_mknod *auxt = auxbuf; 327 struct puffs_newinfo pni; 328 struct puffs_cn pcn; 329 330 if (pops->puffs_node_mknod == NULL) { 331 error = 0; 332 break; 333 } 334 335 pcn.pcn_pkcnp = &auxt->pvnr_cn; 336 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 337 338 memset(&pni, 0, sizeof(pni)); 339 pni.pni_cookie = &auxt->pvnr_newnode; 340 341 if (buildpath) { 342 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 343 if (error) 344 break; 345 } 346 347 error = pops->puffs_node_mknod(pu, 348 opcookie, &pni, &pcn, &auxt->pvnr_va); 349 350 if (buildpath) { 351 if (error) { 352 pu->pu_pathfree(pu, &pcn.pcn_po_full); 353 } else { 354 struct puffs_node *pn; 355 356 pn = PU_CMAP(pu, auxt->pvnr_newnode); 357 pn->pn_po = pcn.pcn_po_full; 358 } 359 } 360 361 break; 362 } 363 364 case PUFFS_VN_OPEN: 365 { 366 struct puffs_vnmsg_open *auxt = auxbuf; 367 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 368 369 if (pops->puffs_node_open == NULL) { 370 error = 0; 371 break; 372 } 373 374 error = pops->puffs_node_open(pu, 375 opcookie, auxt->pvnr_mode, pcr); 376 break; 377 } 378 379 case PUFFS_VN_CLOSE: 380 { 381 struct puffs_vnmsg_close *auxt = auxbuf; 382 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 383 384 if (pops->puffs_node_close == NULL) { 385 error = 0; 386 break; 387 } 388 389 error = pops->puffs_node_close(pu, 390 opcookie, auxt->pvnr_fflag, pcr); 391 break; 392 } 393 394 case PUFFS_VN_ACCESS: 395 { 396 struct puffs_vnmsg_access *auxt = auxbuf; 397 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 398 399 if (pops->puffs_node_access == NULL) { 400 error = 0; 401 break; 402 } 403 404 error = pops->puffs_node_access(pu, 405 opcookie, auxt->pvnr_mode, pcr); 406 break; 407 } 408 409 case PUFFS_VN_GETATTR: 410 { 411 struct puffs_vnmsg_getattr *auxt = auxbuf; 412 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 413 414 if (pops->puffs_node_getattr == NULL) { 415 error = EOPNOTSUPP; 416 break; 417 } 418 419 error = pops->puffs_node_getattr(pu, 420 opcookie, &auxt->pvnr_va, pcr); 421 break; 422 } 423 424 case PUFFS_VN_SETATTR: 425 { 426 struct puffs_vnmsg_setattr *auxt = auxbuf; 427 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 428 429 if (pops->puffs_node_setattr == NULL) { 430 error = EOPNOTSUPP; 431 break; 432 } 433 434 error = pops->puffs_node_setattr(pu, 435 opcookie, &auxt->pvnr_va, pcr); 436 break; 437 } 438 439 case PUFFS_VN_MMAP: 440 { 441 struct puffs_vnmsg_mmap *auxt = auxbuf; 442 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 443 444 if (pops->puffs_node_mmap == NULL) { 445 error = 0; 446 break; 447 } 448 449 error = pops->puffs_node_mmap(pu, 450 opcookie, auxt->pvnr_prot, pcr); 451 break; 452 } 453 454 case PUFFS_VN_FSYNC: 455 { 456 struct puffs_vnmsg_fsync *auxt = auxbuf; 457 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 458 459 if (pops->puffs_node_fsync == NULL) { 460 error = 0; 461 break; 462 } 463 464 error = pops->puffs_node_fsync(pu, opcookie, pcr, 465 auxt->pvnr_flags, auxt->pvnr_offlo, 466 auxt->pvnr_offhi); 467 break; 468 } 469 470 case PUFFS_VN_SEEK: 471 { 472 struct puffs_vnmsg_seek *auxt = auxbuf; 473 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 474 475 if (pops->puffs_node_seek == NULL) { 476 error = 0; 477 break; 478 } 479 480 error = pops->puffs_node_seek(pu, 481 opcookie, auxt->pvnr_oldoff, 482 auxt->pvnr_newoff, pcr); 483 break; 484 } 485 486 case PUFFS_VN_REMOVE: 487 { 488 struct puffs_vnmsg_remove *auxt = auxbuf; 489 struct puffs_cn pcn; 490 if (pops->puffs_node_remove == NULL) { 491 error = 0; 492 break; 493 } 494 495 pcn.pcn_pkcnp = &auxt->pvnr_cn; 496 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 497 498 error = pops->puffs_node_remove(pu, 499 opcookie, auxt->pvnr_cookie_targ, &pcn); 500 break; 501 } 502 503 case PUFFS_VN_LINK: 504 { 505 struct puffs_vnmsg_link *auxt = auxbuf; 506 struct puffs_cn pcn; 507 if (pops->puffs_node_link == NULL) { 508 error = 0; 509 break; 510 } 511 512 pcn.pcn_pkcnp = &auxt->pvnr_cn; 513 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 514 515 if (buildpath) { 516 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 517 if (error) 518 break; 519 } 520 521 error = pops->puffs_node_link(pu, 522 opcookie, auxt->pvnr_cookie_targ, &pcn); 523 if (buildpath) 524 pu->pu_pathfree(pu, &pcn.pcn_po_full); 525 526 break; 527 } 528 529 case PUFFS_VN_RENAME: 530 { 531 struct puffs_vnmsg_rename *auxt = auxbuf; 532 struct puffs_cn pcn_src, pcn_targ; 533 struct puffs_node *pn_src; 534 535 if (pops->puffs_node_rename == NULL) { 536 error = 0; 537 break; 538 } 539 540 pcn_src.pcn_pkcnp = &auxt->pvnr_cn_src; 541 PUFFS_KCREDTOCRED(pcn_src.pcn_cred, 542 &auxt->pvnr_cn_src_cred); 543 544 pcn_targ.pcn_pkcnp = &auxt->pvnr_cn_targ; 545 PUFFS_KCREDTOCRED(pcn_targ.pcn_cred, 546 &auxt->pvnr_cn_targ_cred); 547 548 if (buildpath) { 549 pn_src = auxt->pvnr_cookie_src; 550 pcn_src.pcn_po_full = pn_src->pn_po; 551 552 error = puffs_path_pcnbuild(pu, &pcn_targ, 553 auxt->pvnr_cookie_targdir); 554 if (error) 555 break; 556 } 557 558 error = pops->puffs_node_rename(pu, 559 opcookie, auxt->pvnr_cookie_src, 560 &pcn_src, auxt->pvnr_cookie_targdir, 561 auxt->pvnr_cookie_targ, &pcn_targ); 562 563 if (buildpath) { 564 if (error) { 565 pu->pu_pathfree(pu, 566 &pcn_targ.pcn_po_full); 567 } else { 568 struct puffs_pathinfo pi; 569 struct puffs_pathobj po_old; 570 571 /* handle this node */ 572 po_old = pn_src->pn_po; 573 pn_src->pn_po = pcn_targ.pcn_po_full; 574 575 if (pn_src->pn_va.va_type != VDIR) { 576 pu->pu_pathfree(pu, &po_old); 577 break; 578 } 579 580 /* handle all child nodes for DIRs */ 581 pi.pi_old = &pcn_src.pcn_po_full; 582 pi.pi_new = &pcn_targ.pcn_po_full; 583 584 PU_LOCK(); 585 if (puffs_pn_nodewalk(pu, 586 puffs_path_prefixadj, &pi) != NULL) 587 error = ENOMEM; 588 PU_UNLOCK(); 589 pu->pu_pathfree(pu, &po_old); 590 } 591 } 592 break; 593 } 594 595 case PUFFS_VN_MKDIR: 596 { 597 struct puffs_vnmsg_mkdir *auxt = auxbuf; 598 struct puffs_newinfo pni; 599 struct puffs_cn pcn; 600 601 if (pops->puffs_node_mkdir == NULL) { 602 error = 0; 603 break; 604 } 605 606 pcn.pcn_pkcnp = &auxt->pvnr_cn; 607 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 608 609 memset(&pni, 0, sizeof(pni)); 610 pni.pni_cookie = &auxt->pvnr_newnode; 611 612 if (buildpath) { 613 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 614 if (error) 615 break; 616 } 617 618 error = pops->puffs_node_mkdir(pu, 619 opcookie, &pni, &pcn, &auxt->pvnr_va); 620 621 if (buildpath) { 622 if (error) { 623 pu->pu_pathfree(pu, &pcn.pcn_po_full); 624 } else { 625 struct puffs_node *pn; 626 627 pn = PU_CMAP(pu, auxt->pvnr_newnode); 628 pn->pn_po = pcn.pcn_po_full; 629 } 630 } 631 632 break; 633 } 634 635 case PUFFS_VN_RMDIR: 636 { 637 struct puffs_vnmsg_rmdir *auxt = auxbuf; 638 struct puffs_cn pcn; 639 if (pops->puffs_node_rmdir == NULL) { 640 error = 0; 641 break; 642 } 643 644 pcn.pcn_pkcnp = &auxt->pvnr_cn; 645 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 646 647 error = pops->puffs_node_rmdir(pu, 648 opcookie, auxt->pvnr_cookie_targ, &pcn); 649 break; 650 } 651 652 case PUFFS_VN_SYMLINK: 653 { 654 struct puffs_vnmsg_symlink *auxt = auxbuf; 655 struct puffs_newinfo pni; 656 struct puffs_cn pcn; 657 658 if (pops->puffs_node_symlink == NULL) { 659 error = 0; 660 break; 661 } 662 663 pcn.pcn_pkcnp = &auxt->pvnr_cn; 664 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred); 665 666 memset(&pni, 0, sizeof(pni)); 667 pni.pni_cookie = &auxt->pvnr_newnode; 668 669 if (buildpath) { 670 error = puffs_path_pcnbuild(pu, &pcn, opcookie); 671 if (error) 672 break; 673 } 674 675 error = pops->puffs_node_symlink(pu, 676 opcookie, &pni, &pcn, 677 &auxt->pvnr_va, auxt->pvnr_link); 678 679 if (buildpath) { 680 if (error) { 681 pu->pu_pathfree(pu, &pcn.pcn_po_full); 682 } else { 683 struct puffs_node *pn; 684 685 pn = PU_CMAP(pu, auxt->pvnr_newnode); 686 pn->pn_po = pcn.pcn_po_full; 687 } 688 } 689 690 break; 691 } 692 693 case PUFFS_VN_READDIR: 694 { 695 struct puffs_vnmsg_readdir *auxt = auxbuf; 696 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 697 struct dirent *dent; 698 off_t *cookies; 699 size_t res, origcookies; 700 701 if (pops->puffs_node_readdir == NULL) { 702 error = 0; 703 break; 704 } 705 706 if (auxt->pvnr_ncookies) { 707 /* LINTED: pvnr_data is __aligned() */ 708 cookies = (off_t *)auxt->pvnr_data; 709 origcookies = auxt->pvnr_ncookies; 710 } else { 711 cookies = NULL; 712 origcookies = 0; 713 } 714 /* LINTED: dentoff is aligned in the kernel */ 715 dent = (struct dirent *) 716 (auxt->pvnr_data + auxt->pvnr_dentoff); 717 718 res = auxt->pvnr_resid; 719 error = pops->puffs_node_readdir(pu, 720 opcookie, dent, &auxt->pvnr_offset, 721 &auxt->pvnr_resid, pcr, &auxt->pvnr_eofflag, 722 cookies, &auxt->pvnr_ncookies); 723 724 /* much easier to track non-working NFS */ 725 assert(auxt->pvnr_ncookies <= origcookies); 726 727 /* need to move a bit more */ 728 preq->preq_buflen = sizeof(struct puffs_vnmsg_readdir) 729 + auxt->pvnr_dentoff + (res - auxt->pvnr_resid); 730 break; 731 } 732 733 case PUFFS_VN_READLINK: 734 { 735 struct puffs_vnmsg_readlink *auxt = auxbuf; 736 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 737 738 if (pops->puffs_node_readlink == NULL) { 739 error = EOPNOTSUPP; 740 break; 741 } 742 743 /*LINTED*/ 744 error = pops->puffs_node_readlink(pu, opcookie, pcr, 745 auxt->pvnr_link, &auxt->pvnr_linklen); 746 break; 747 } 748 749 case PUFFS_VN_RECLAIM: 750 { 751 752 if (pops->puffs_node_reclaim == NULL) { 753 error = 0; 754 break; 755 } 756 757 error = pops->puffs_node_reclaim(pu, opcookie); 758 break; 759 } 760 761 case PUFFS_VN_INACTIVE: 762 { 763 764 if (pops->puffs_node_inactive == NULL) { 765 error = EOPNOTSUPP; 766 break; 767 } 768 769 error = pops->puffs_node_inactive(pu, opcookie); 770 break; 771 } 772 773 case PUFFS_VN_PATHCONF: 774 { 775 struct puffs_vnmsg_pathconf *auxt = auxbuf; 776 if (pops->puffs_node_pathconf == NULL) { 777 error = 0; 778 break; 779 } 780 781 error = pops->puffs_node_pathconf(pu, 782 opcookie, auxt->pvnr_name, 783 &auxt->pvnr_retval); 784 break; 785 } 786 787 case PUFFS_VN_ADVLOCK: 788 { 789 struct puffs_vnmsg_advlock *auxt = auxbuf; 790 if (pops->puffs_node_advlock == NULL) { 791 error = 0; 792 break; 793 } 794 795 error = pops->puffs_node_advlock(pu, 796 opcookie, auxt->pvnr_id, auxt->pvnr_op, 797 &auxt->pvnr_fl, auxt->pvnr_flags); 798 break; 799 } 800 801 case PUFFS_VN_PRINT: 802 { 803 if (pops->puffs_node_print == NULL) { 804 error = 0; 805 break; 806 } 807 808 error = pops->puffs_node_print(pu, 809 opcookie); 810 break; 811 } 812 813 case PUFFS_VN_READ: 814 { 815 struct puffs_vnmsg_read *auxt = auxbuf; 816 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 817 size_t res; 818 819 if (pops->puffs_node_read == NULL) { 820 error = EIO; 821 break; 822 } 823 824 res = auxt->pvnr_resid; 825 error = pops->puffs_node_read(pu, 826 opcookie, auxt->pvnr_data, 827 auxt->pvnr_offset, &auxt->pvnr_resid, 828 pcr, auxt->pvnr_ioflag); 829 830 /* need to move a bit more */ 831 preq->preq_buflen = sizeof(struct puffs_vnmsg_read) 832 + (res - auxt->pvnr_resid); 833 break; 834 } 835 836 case PUFFS_VN_WRITE: 837 { 838 struct puffs_vnmsg_write *auxt = auxbuf; 839 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred); 840 841 if (pops->puffs_node_write == NULL) { 842 error = EIO; 843 break; 844 } 845 846 error = pops->puffs_node_write(pu, 847 opcookie, auxt->pvnr_data, 848 auxt->pvnr_offset, &auxt->pvnr_resid, 849 pcr, auxt->pvnr_ioflag); 850 851 /* don't need to move data back to the kernel */ 852 preq->preq_buflen = sizeof(struct puffs_vnmsg_write); 853 break; 854 } 855 856 case PUFFS_VN_POLL: 857 { 858 struct puffs_vnmsg_poll *auxt = auxbuf; 859 860 if (pops->puffs_node_poll == NULL) { 861 error = 0; 862 863 /* emulate genfs_poll() */ 864 auxt->pvnr_events &= (POLLIN | POLLOUT 865 | POLLRDNORM | POLLWRNORM); 866 867 break; 868 } 869 870 error = pops->puffs_node_poll(pu, 871 opcookie, &auxt->pvnr_events); 872 break; 873 } 874 875 default: 876 printf("inval op %d\n", preq->preq_optype); 877 error = EINVAL; 878 break; 879 } 880 881 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_CACHE) { 882 struct puffs_cacheinfo *pci = (void *)preq; 883 884 if (pu->pu_ops.puffs_cache_write) { 885 pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie, 886 pci->pcache_nruns, pci->pcache_runs); 887 } 888 error = 0; 889 890 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_ERROR) { 891 struct puffs_error *perr = (void *)preq; 892 893 pu->pu_errnotify(pu, preq->preq_optype, 894 perr->perr_error, perr->perr_str, preq->preq_cookie); 895 error = 0; 896 } else { 897 /* 898 * I guess the kernel sees this one coming also 899 */ 900 error = EINVAL; 901 } 902 preq->preq_rv = error; 903 904 if (pu->pu_oppost) 905 pu->pu_oppost(pu); 906 907 pcc->pcc_flags |= PCC_DONE; 908 } 909