dispatcher.c revision 1.1 1 /* $NetBSD: dispatcher.c,v 1.1 2007/05/11 21:42:42 pooka Exp $ */
2
3 /*
4 * Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
5 *
6 * Development of this software was supported by the
7 * Google Summer of Code program and the Ulla Tuominen Foundation.
8 * The Google SoC project was mentored by Bill Studenmund.
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 * 3. The name of the company nor the name of the author may be used to
19 * endorse or promote products derived from this software without specific
20 * prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 #if !defined(lint)
37 __RCSID("$NetBSD: dispatcher.c,v 1.1 2007/05/11 21:42:42 pooka Exp $");
38 #endif /* !lint */
39
40 #include <sys/types.h>
41
42 #include <assert.h>
43 #include <errno.h>
44 #include <puffs.h>
45 #include <puffsdump.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49
50 #include "puffs_priv.h"
51
52 /*
53 * Set the following to 1 to not handle each request on a separate
54 * stack. This is highly volatile kludge, therefore no external
55 * interface.
56 */
57 int puffs_fakecc;
58
59 int
60 puffs_dopreq(struct puffs_usermount *pu, struct puffs_req *preq,
61 struct puffs_putreq *ppr)
62 {
63 struct puffs_cc fakecc;
64 struct puffs_cc *pcc;
65 int rv;
66
67 /*
68 * XXX: the structure is currently a mess. anyway, trap
69 * the cacheops here already, since they don't need a cc.
70 * I really should get around to revamping the operation
71 * dispatching code one of these days.
72 */
73 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_CACHE) {
74 struct puffs_cacheinfo *pci = (void *)preq;
75
76 if (pu->pu_ops.puffs_cache_write == NULL)
77 return 0;
78
79 pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie,
80 pci->pcache_nruns, pci->pcache_runs);
81 }
82
83 if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
84 puffsdump_req(preq);
85
86 if (puffs_fakecc) {
87 pcc = &fakecc;
88 pcc_init_local(pcc);
89
90 pcc->pcc_pu = pu;
91 pcc->pcc_preq = preq;
92 pcc->pcc_flags = PCC_FAKECC;
93 } else {
94 pcc = puffs_cc_create(pu);
95
96 /* XXX: temporary kludging */
97 pcc->pcc_preq = malloc(preq->preq_buflen);
98 if (pcc->pcc_preq == NULL)
99 return -1;
100 (void) memcpy(pcc->pcc_preq, preq, preq->preq_buflen);
101 }
102
103 rv = puffs_docc(pcc, ppr);
104
105 if ((pcc->pcc_flags & PCC_DONE) == 0)
106 return 0;
107
108 return rv;
109 }
110
111 enum {PUFFCALL_ANSWER, PUFFCALL_IGNORE, PUFFCALL_AGAIN};
112
113 int
114 puffs_docc(struct puffs_cc *pcc, struct puffs_putreq *ppr)
115 {
116 struct puffs_usermount *pu = pcc->pcc_pu;
117 int rv;
118
119 assert((pcc->pcc_flags & PCC_DONE) == 0);
120
121 if (pcc->pcc_flags & PCC_REALCC)
122 puffs_cc_continue(pcc);
123 else
124 puffs_calldispatcher(pcc);
125 rv = pcc->pcc_rv;
126
127 if ((pcc->pcc_flags & PCC_DONE) == 0)
128 rv = PUFFCALL_AGAIN;
129
130 /* check if we need to store this reply */
131 switch (rv) {
132 case PUFFCALL_ANSWER:
133 if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
134 puffsdump_rv(pcc->pcc_preq);
135
136 if (pcc->pcc_flags & PCC_REALCC)
137 puffs_req_putcc(ppr, pcc);
138 else
139 puffs_req_put(ppr, pcc->pcc_preq);
140 break;
141 case PUFFCALL_IGNORE:
142 if (pcc->pcc_flags & PCC_REALCC)
143 puffs_cc_destroy(pcc);
144 break;
145 case PUFFCALL_AGAIN:
146 if (pcc->pcc_flags & PCC_FAKECC)
147 assert(pcc->pcc_flags & PCC_DONE);
148 break;
149 default:
150 assert(/*CONSTCOND*/0);
151 }
152
153 return 0;
154 }
155
156 /* library private, but linked from callcontext.c */
157
158 void
159 puffs_calldispatcher(struct puffs_cc *pcc)
160 {
161 struct puffs_usermount *pu = pcc->pcc_pu;
162 struct puffs_ops *pops = &pu->pu_ops;
163 struct puffs_req *preq = pcc->pcc_preq;
164 void *auxbuf = preq; /* help with typecasting */
165 void *opcookie = preq->preq_cookie;
166 int error, rv, buildpath;
167
168 assert(pcc->pcc_flags & (PCC_FAKECC | PCC_REALCC));
169
170 if (PUFFSOP_WANTREPLY(preq->preq_opclass))
171 rv = PUFFCALL_ANSWER;
172 else
173 rv = PUFFCALL_IGNORE;
174
175 buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH;
176 preq->preq_setbacks = 0;
177
178 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
179 switch (preq->preq_optype) {
180 case PUFFS_VFS_UNMOUNT:
181 {
182 struct puffs_vfsreq_unmount *auxt = auxbuf;
183
184 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTING);
185 error = pops->puffs_fs_unmount(pcc,
186 auxt->pvfsr_flags, auxt->pvfsr_pid);
187 if (!error)
188 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED);
189 else
190 PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
191 break;
192 }
193
194 case PUFFS_VFS_STATVFS:
195 {
196 struct puffs_vfsreq_statvfs *auxt = auxbuf;
197
198 error = pops->puffs_fs_statvfs(pcc,
199 &auxt->pvfsr_sb, auxt->pvfsr_pid);
200 break;
201 }
202
203 case PUFFS_VFS_SYNC:
204 {
205 struct puffs_vfsreq_sync *auxt = auxbuf;
206
207 error = pops->puffs_fs_sync(pcc,
208 auxt->pvfsr_waitfor, &auxt->pvfsr_cred,
209 auxt->pvfsr_pid);
210 break;
211 }
212
213 case PUFFS_VFS_FHTOVP:
214 {
215 struct puffs_vfsreq_fhtonode *auxt = auxbuf;
216
217 error = pops->puffs_fs_fhtonode(pcc, auxt->pvfsr_data,
218 auxt->pvfsr_dsize, &auxt->pvfsr_fhcookie,
219 &auxt->pvfsr_vtype, &auxt->pvfsr_size,
220 &auxt->pvfsr_rdev);
221
222 break;
223 }
224
225 case PUFFS_VFS_VPTOFH:
226 {
227 struct puffs_vfsreq_nodetofh *auxt = auxbuf;
228
229 error = pops->puffs_fs_nodetofh(pcc,
230 auxt->pvfsr_fhcookie, auxt->pvfsr_data,
231 &auxt->pvfsr_dsize);
232
233 break;
234 }
235
236 case PUFFS_VFS_SUSPEND:
237 {
238 struct puffs_vfsreq_suspend *auxt = auxbuf;
239
240 error = 0;
241 if (pops->puffs_fs_suspend == NULL)
242 break;
243
244 pops->puffs_fs_suspend(pcc, auxt->pvfsr_status);
245 break;
246 }
247
248 default:
249 /*
250 * I guess the kernel sees this one coming
251 */
252 error = EINVAL;
253 break;
254 }
255
256 /* XXX: audit return values */
257 /* XXX: sync with kernel */
258 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
259 switch (preq->preq_optype) {
260 case PUFFS_VN_LOOKUP:
261 {
262 struct puffs_vnreq_lookup *auxt = auxbuf;
263 struct puffs_cn pcn;
264
265 pcn.pcn_pkcnp = &auxt->pvnr_cn;
266 if (buildpath) {
267 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
268 if (error)
269 break;
270 }
271
272 /* lookup *must* be present */
273 error = pops->puffs_node_lookup(pcc, opcookie,
274 &auxt->pvnr_newnode, &auxt->pvnr_vtype,
275 &auxt->pvnr_size, &auxt->pvnr_rdev, &pcn);
276
277 if (buildpath) {
278 if (error) {
279 pu->pu_pathfree(pu, &pcn.pcn_po_full);
280 } else {
281 struct puffs_node *pn;
282
283 /*
284 * did we get a new node or a
285 * recycled node?
286 */
287 pn = PU_CMAP(pu, auxt->pvnr_newnode);
288 if (pn->pn_po.po_path == NULL)
289 pn->pn_po = pcn.pcn_po_full;
290 else
291 pu->pu_pathfree(pu,
292 &pcn.pcn_po_full);
293 }
294 }
295
296 break;
297 }
298
299 case PUFFS_VN_CREATE:
300 {
301 struct puffs_vnreq_create *auxt = auxbuf;
302 struct puffs_cn pcn;
303 if (pops->puffs_node_create == NULL) {
304 error = 0;
305 break;
306 }
307
308 pcn.pcn_pkcnp = &auxt->pvnr_cn;
309 if (buildpath) {
310 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
311 if (error)
312 break;
313 }
314
315 error = pops->puffs_node_create(pcc,
316 opcookie, &auxt->pvnr_newnode,
317 &pcn, &auxt->pvnr_va);
318
319 if (buildpath) {
320 if (error) {
321 pu->pu_pathfree(pu, &pcn.pcn_po_full);
322 } else {
323 struct puffs_node *pn;
324
325 pn = PU_CMAP(pu, auxt->pvnr_newnode);
326 pn->pn_po = pcn.pcn_po_full;
327 }
328 }
329
330 break;
331 }
332
333 case PUFFS_VN_MKNOD:
334 {
335 struct puffs_vnreq_mknod *auxt = auxbuf;
336 struct puffs_cn pcn;
337 if (pops->puffs_node_mknod == NULL) {
338 error = 0;
339 break;
340 }
341
342 pcn.pcn_pkcnp = &auxt->pvnr_cn;
343 if (buildpath) {
344 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
345 if (error)
346 break;
347 }
348
349 error = pops->puffs_node_mknod(pcc,
350 opcookie, &auxt->pvnr_newnode,
351 &pcn, &auxt->pvnr_va);
352
353 if (buildpath) {
354 if (error) {
355 pu->pu_pathfree(pu, &pcn.pcn_po_full);
356 } else {
357 struct puffs_node *pn;
358
359 pn = PU_CMAP(pu, auxt->pvnr_newnode);
360 pn->pn_po = pcn.pcn_po_full;
361 }
362 }
363
364 break;
365 }
366
367 case PUFFS_VN_OPEN:
368 {
369 struct puffs_vnreq_open *auxt = auxbuf;
370 if (pops->puffs_node_open == NULL) {
371 error = 0;
372 break;
373 }
374
375 error = pops->puffs_node_open(pcc,
376 opcookie, auxt->pvnr_mode,
377 &auxt->pvnr_cred, auxt->pvnr_pid);
378 break;
379 }
380
381 case PUFFS_VN_CLOSE:
382 {
383 struct puffs_vnreq_close *auxt = auxbuf;
384 if (pops->puffs_node_close == NULL) {
385 error = 0;
386 break;
387 }
388
389 error = pops->puffs_node_close(pcc,
390 opcookie, auxt->pvnr_fflag,
391 &auxt->pvnr_cred, auxt->pvnr_pid);
392 break;
393 }
394
395 case PUFFS_VN_ACCESS:
396 {
397 struct puffs_vnreq_access *auxt = auxbuf;
398 if (pops->puffs_node_access == NULL) {
399 error = 0;
400 break;
401 }
402
403 error = pops->puffs_node_access(pcc,
404 opcookie, auxt->pvnr_mode,
405 &auxt->pvnr_cred, auxt->pvnr_pid);
406 break;
407 }
408
409 case PUFFS_VN_GETATTR:
410 {
411 struct puffs_vnreq_getattr *auxt = auxbuf;
412 if (pops->puffs_node_getattr == NULL) {
413 error = EOPNOTSUPP;
414 break;
415 }
416
417 error = pops->puffs_node_getattr(pcc,
418 opcookie, &auxt->pvnr_va,
419 &auxt->pvnr_cred, auxt->pvnr_pid);
420 break;
421 }
422
423 case PUFFS_VN_SETATTR:
424 {
425 struct puffs_vnreq_setattr *auxt = auxbuf;
426 if (pops->puffs_node_setattr == NULL) {
427 error = EOPNOTSUPP;
428 break;
429 }
430
431 error = pops->puffs_node_setattr(pcc,
432 opcookie, &auxt->pvnr_va,
433 &auxt->pvnr_cred, auxt->pvnr_pid);
434 break;
435 }
436
437 case PUFFS_VN_MMAP:
438 {
439 struct puffs_vnreq_mmap *auxt = auxbuf;
440 if (pops->puffs_node_mmap == NULL) {
441 error = 0;
442 break;
443 }
444
445 error = pops->puffs_node_mmap(pcc,
446 opcookie, auxt->pvnr_fflags,
447 &auxt->pvnr_cred, auxt->pvnr_pid);
448 break;
449 }
450
451 case PUFFS_VN_FSYNC:
452 {
453 struct puffs_vnreq_fsync *auxt = auxbuf;
454 if (pops->puffs_node_fsync == NULL) {
455 error = 0;
456 break;
457 }
458
459 error = pops->puffs_node_fsync(pcc,
460 opcookie, &auxt->pvnr_cred,
461 auxt->pvnr_flags, auxt->pvnr_offlo,
462 auxt->pvnr_offhi, auxt->pvnr_pid);
463 break;
464 }
465
466 case PUFFS_VN_SEEK:
467 {
468 struct puffs_vnreq_seek *auxt = auxbuf;
469 if (pops->puffs_node_seek == NULL) {
470 error = 0;
471 break;
472 }
473
474 error = pops->puffs_node_seek(pcc,
475 opcookie, auxt->pvnr_oldoff,
476 auxt->pvnr_newoff, &auxt->pvnr_cred);
477 break;
478 }
479
480 case PUFFS_VN_REMOVE:
481 {
482 struct puffs_vnreq_remove *auxt = auxbuf;
483 struct puffs_cn pcn;
484 if (pops->puffs_node_remove == NULL) {
485 error = 0;
486 break;
487 }
488
489 pcn.pcn_pkcnp = &auxt->pvnr_cn;
490
491 error = pops->puffs_node_remove(pcc,
492 opcookie, auxt->pvnr_cookie_targ, &pcn);
493 break;
494 }
495
496 case PUFFS_VN_LINK:
497 {
498 struct puffs_vnreq_link *auxt = auxbuf;
499 struct puffs_cn pcn;
500 if (pops->puffs_node_link == NULL) {
501 error = 0;
502 break;
503 }
504
505 pcn.pcn_pkcnp = &auxt->pvnr_cn;
506 if (buildpath) {
507 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
508 if (error)
509 break;
510 }
511
512 error = pops->puffs_node_link(pcc,
513 opcookie, auxt->pvnr_cookie_targ, &pcn);
514 if (buildpath)
515 pu->pu_pathfree(pu, &pcn.pcn_po_full);
516
517 break;
518 }
519
520 case PUFFS_VN_RENAME:
521 {
522 struct puffs_vnreq_rename *auxt = auxbuf;
523 struct puffs_cn pcn_src, pcn_targ;
524 struct puffs_node *pn_src;
525
526 if (pops->puffs_node_rename == NULL) {
527 error = 0;
528 break;
529 }
530
531 pcn_src.pcn_pkcnp = &auxt->pvnr_cn_src;
532 pcn_targ.pcn_pkcnp = &auxt->pvnr_cn_targ;
533 if (buildpath) {
534 pn_src = auxt->pvnr_cookie_src;
535 pcn_src.pcn_po_full = pn_src->pn_po;
536
537 error = puffs_path_pcnbuild(pu, &pcn_targ,
538 auxt->pvnr_cookie_targdir);
539 if (error)
540 break;
541 }
542
543 error = pops->puffs_node_rename(pcc,
544 opcookie, auxt->pvnr_cookie_src,
545 &pcn_src, auxt->pvnr_cookie_targdir,
546 auxt->pvnr_cookie_targ, &pcn_targ);
547
548 if (buildpath) {
549 if (error) {
550 pu->pu_pathfree(pu,
551 &pcn_targ.pcn_po_full);
552 } else {
553 struct puffs_pathinfo pi;
554 struct puffs_pathobj po_old;
555
556 /* handle this node */
557 po_old = pn_src->pn_po;
558 pn_src->pn_po = pcn_targ.pcn_po_full;
559
560 if (pn_src->pn_va.va_type != VDIR) {
561 pu->pu_pathfree(pu, &po_old);
562 break;
563 }
564
565 /* handle all child nodes for DIRs */
566 pi.pi_old = &pcn_src.pcn_po_full;
567 pi.pi_new = &pcn_targ.pcn_po_full;
568
569 if (puffs_pn_nodewalk(pu,
570 puffs_path_prefixadj, &pi) != NULL)
571 error = ENOMEM;
572 pu->pu_pathfree(pu, &po_old);
573 }
574 }
575 break;
576 }
577
578 case PUFFS_VN_MKDIR:
579 {
580 struct puffs_vnreq_mkdir *auxt = auxbuf;
581 struct puffs_cn pcn;
582 if (pops->puffs_node_mkdir == NULL) {
583 error = 0;
584 break;
585 }
586
587 pcn.pcn_pkcnp = &auxt->pvnr_cn;
588 if (buildpath) {
589 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
590 if (error)
591 break;
592 }
593
594 error = pops->puffs_node_mkdir(pcc,
595 opcookie, &auxt->pvnr_newnode,
596 &pcn, &auxt->pvnr_va);
597
598 if (buildpath) {
599 if (error) {
600 pu->pu_pathfree(pu, &pcn.pcn_po_full);
601 } else {
602 struct puffs_node *pn;
603
604 pn = PU_CMAP(pu, auxt->pvnr_newnode);
605 pn->pn_po = pcn.pcn_po_full;
606 }
607 }
608
609 break;
610 }
611
612 case PUFFS_VN_RMDIR:
613 {
614 struct puffs_vnreq_rmdir *auxt = auxbuf;
615 struct puffs_cn pcn;
616 if (pops->puffs_node_rmdir == NULL) {
617 error = 0;
618 break;
619 }
620
621 pcn.pcn_pkcnp = &auxt->pvnr_cn;
622
623 error = pops->puffs_node_rmdir(pcc,
624 opcookie, auxt->pvnr_cookie_targ, &pcn);
625 break;
626 }
627
628 case PUFFS_VN_SYMLINK:
629 {
630 struct puffs_vnreq_symlink *auxt = auxbuf;
631 struct puffs_cn pcn;
632 if (pops->puffs_node_symlink == NULL) {
633 error = 0;
634 break;
635 }
636
637 pcn.pcn_pkcnp = &auxt->pvnr_cn;
638 if (buildpath) {
639 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
640 if (error)
641 break;
642 }
643
644 error = pops->puffs_node_symlink(pcc,
645 opcookie, &auxt->pvnr_newnode,
646 &pcn, &auxt->pvnr_va, auxt->pvnr_link);
647
648 if (buildpath) {
649 if (error) {
650 pu->pu_pathfree(pu, &pcn.pcn_po_full);
651 } else {
652 struct puffs_node *pn;
653
654 pn = PU_CMAP(pu, auxt->pvnr_newnode);
655 pn->pn_po = pcn.pcn_po_full;
656 }
657 }
658
659 break;
660 }
661
662 case PUFFS_VN_READDIR:
663 {
664 struct puffs_vnreq_readdir *auxt = auxbuf;
665 struct dirent *dent;
666 off_t *cookies;
667 size_t res, origcookies;
668
669 if (pops->puffs_node_readdir == NULL) {
670 error = 0;
671 break;
672 }
673
674 if (auxt->pvnr_ncookies) {
675 /* LINTED: pvnr_data is __aligned() */
676 cookies = (off_t *)auxt->pvnr_data;
677 origcookies = auxt->pvnr_ncookies;
678 } else {
679 cookies = NULL;
680 origcookies = 0;
681 }
682 /* LINTED: dentoff is aligned in the kernel */
683 dent = (struct dirent *)
684 (auxt->pvnr_data + auxt->pvnr_dentoff);
685
686 res = auxt->pvnr_resid;
687 error = pops->puffs_node_readdir(pcc,
688 opcookie, dent, &auxt->pvnr_offset,
689 &auxt->pvnr_resid, &auxt->pvnr_cred,
690 &auxt->pvnr_eofflag, cookies, &auxt->pvnr_ncookies);
691
692 /* much easier to track non-working NFS */
693 assert(auxt->pvnr_ncookies <= origcookies);
694
695 /* need to move a bit more */
696 preq->preq_buflen = sizeof(struct puffs_vnreq_readdir)
697 + auxt->pvnr_dentoff + (res - auxt->pvnr_resid);
698 break;
699 }
700
701 case PUFFS_VN_READLINK:
702 {
703 struct puffs_vnreq_readlink *auxt = auxbuf;
704 if (pops->puffs_node_readlink == NULL) {
705 error = EOPNOTSUPP;
706 break;
707 }
708
709 error = pops->puffs_node_readlink(pcc,
710 opcookie, &auxt->pvnr_cred,
711 auxt->pvnr_link, &auxt->pvnr_linklen);
712 break;
713 }
714
715 case PUFFS_VN_RECLAIM:
716 {
717 struct puffs_vnreq_reclaim *auxt = auxbuf;
718 if (pops->puffs_node_reclaim == NULL) {
719 error = 0;
720 break;
721 }
722
723 error = pops->puffs_node_reclaim(pcc,
724 opcookie, auxt->pvnr_pid);
725 break;
726 }
727
728 case PUFFS_VN_INACTIVE:
729 {
730 struct puffs_vnreq_inactive *auxt = auxbuf;
731 if (pops->puffs_node_inactive == NULL) {
732 error = EOPNOTSUPP;
733 break;
734 }
735
736 error = pops->puffs_node_inactive(pcc,
737 opcookie, auxt->pvnr_pid,
738 &auxt->pvnr_backendrefs);
739 break;
740 }
741
742 case PUFFS_VN_PATHCONF:
743 {
744 struct puffs_vnreq_pathconf *auxt = auxbuf;
745 if (pops->puffs_node_pathconf == NULL) {
746 error = 0;
747 break;
748 }
749
750 error = pops->puffs_node_pathconf(pcc,
751 opcookie, auxt->pvnr_name,
752 &auxt->pvnr_retval);
753 break;
754 }
755
756 case PUFFS_VN_ADVLOCK:
757 {
758 struct puffs_vnreq_advlock *auxt = auxbuf;
759 if (pops->puffs_node_advlock == NULL) {
760 error = 0;
761 break;
762 }
763
764 error = pops->puffs_node_advlock(pcc,
765 opcookie, auxt->pvnr_id, auxt->pvnr_op,
766 &auxt->pvnr_fl, auxt->pvnr_flags);
767 break;
768 }
769
770 case PUFFS_VN_PRINT:
771 {
772 if (pops->puffs_node_print == NULL) {
773 error = 0;
774 break;
775 }
776
777 error = pops->puffs_node_print(pcc,
778 opcookie);
779 break;
780 }
781
782 case PUFFS_VN_READ:
783 {
784 struct puffs_vnreq_read *auxt = auxbuf;
785 size_t res;
786
787 if (pops->puffs_node_read == NULL) {
788 error = EIO;
789 break;
790 }
791
792 res = auxt->pvnr_resid;
793 error = pops->puffs_node_read(pcc,
794 opcookie, auxt->pvnr_data,
795 auxt->pvnr_offset, &auxt->pvnr_resid,
796 &auxt->pvnr_cred, auxt->pvnr_ioflag);
797
798 /* need to move a bit more */
799 preq->preq_buflen = sizeof(struct puffs_vnreq_read)
800 + (res - auxt->pvnr_resid);
801 break;
802 }
803
804 case PUFFS_VN_WRITE:
805 {
806 struct puffs_vnreq_write *auxt = auxbuf;
807
808 if (pops->puffs_node_write == NULL) {
809 error = EIO;
810 break;
811 }
812
813 error = pops->puffs_node_write(pcc,
814 opcookie, auxt->pvnr_data,
815 auxt->pvnr_offset, &auxt->pvnr_resid,
816 &auxt->pvnr_cred, auxt->pvnr_ioflag);
817
818 /* don't need to move data back to the kernel */
819 preq->preq_buflen = sizeof(struct puffs_vnreq_write);
820 break;
821 }
822
823 /* holy bitrot, ryydman! */
824 #if 0
825 case PUFFS_VN_IOCTL:
826 error = pops->puffs_node_ioctl1(pcc, opcookie,
827 (struct puffs_vnreq_ioctl *)auxbuf, &pop);
828 if (error != 0)
829 break;
830 pop.pso_reqid = preq->preq_id;
831
832 /* let the kernel do it's intermediate duty */
833 error = ioctl(pu->pu_kargs.pa_fd, PUFFSSIZEOP, &pop);
834 /*
835 * XXX: I don't actually know what the correct
836 * thing to do in case of an error is, so I'll
837 * just ignore it for the time being.
838 */
839 error = pops->puffs_node_ioctl2(pcc, opcookie,
840 (struct puffs_vnreq_ioctl *)auxbuf, &pop);
841 break;
842
843 case PUFFS_VN_FCNTL:
844 error = pops->puffs_node_fcntl1(pcc, opcookie,
845 (struct puffs_vnreq_fcntl *)auxbuf, &pop);
846 if (error != 0)
847 break;
848 pop.pso_reqid = preq->preq_id;
849
850 /* let the kernel do it's intermediate duty */
851 error = ioctl(pu->pu_kargs.pa_fd, PUFFSSIZEOP, &pop);
852 /*
853 * XXX: I don't actually know what the correct
854 * thing to do in case of an error is, so I'll
855 * just ignore it for the time being.
856 */
857 error = pops->puffs_node_fcntl2(pcc, opcookie,
858 (struct puffs_vnreq_fcntl *)auxbuf, &pop);
859 break;
860 #endif
861
862 default:
863 printf("inval op %d\n", preq->preq_optype);
864 error = EINVAL;
865 break;
866 }
867 } else {
868 /*
869 * this one also
870 */
871 error = EINVAL;
872 }
873
874 preq->preq_rv = error;
875
876 pcc->pcc_rv = rv;
877 pcc->pcc_flags |= PCC_DONE;
878 }
879
880
881 #if 0
882 case PUFFS_VN_POLL:
883 {
884 struct puffs_vnreq_poll *auxt = auxbuf;
885 if (pops->puffs_node_poll == NULL) {
886 error = 0;
887 break;
888 }
889
890 error = pops->puffs_node_poll(pcc,
891 opcookie, preq-);
892 break;
893 }
894
895 case PUFFS_VN_KQFILTER:
896 {
897 struct puffs_vnreq_kqfilter *auxt = auxbuf;
898 if (pops->puffs_node_kqfilter == NULL) {
899 error = 0;
900 break;
901 }
902
903 error = pops->puffs_node_kqfilter(pcc,
904 opcookie, );
905 break;
906 }
907
908 case PUFFS_VN_CLOSEEXTATTR:
909 {
910 struct puffs_vnreq_closeextattr *auxt = auxbuf;
911 if (pops->puffs_closeextattr == NULL) {
912 error = 0;
913 break;
914 }
915
916 error = pops->puffs_closeextattr(pcc,
917 opcookie, );
918 break;
919 }
920
921 case PUFFS_VN_GETEXTATTR:
922 {
923 struct puffs_vnreq_getextattr *auxt = auxbuf;
924 if (pops->puffs_getextattr == NULL) {
925 error = 0;
926 break;
927 }
928
929 error = pops->puffs_getextattr(pcc,
930 opcookie, );
931 break;
932 }
933
934 case PUFFS_VN_LISTEXTATTR:
935 {
936 struct puffs_vnreq_listextattr *auxt = auxbuf;
937 if (pops->puffs_listextattr == NULL) {
938 error = 0;
939 break;
940 }
941
942 error = pops->puffs_listextattr(pcc,
943 opcookie, );
944 break;
945 }
946
947 case PUFFS_VN_OPENEXTATTR:
948 {
949 struct puffs_vnreq_openextattr *auxt = auxbuf;
950 if (pops->puffs_openextattr == NULL) {
951 error = 0;
952 break;
953 }
954
955 error = pops->puffs_openextattr(pcc,
956 opcookie, );
957 break;
958 }
959
960 case PUFFS_VN_DELETEEXTATTR:
961 {
962 struct puffs_vnreq_deleteextattr *auxt = auxbuf;
963 if (pops->puffs_deleteextattr == NULL) {
964 error = 0;
965 break;
966 }
967
968 error = pops->puffs_deleteextattr(pcc,
969 opcookie, );
970 break;
971 }
972
973 case PUFFS_VN_SETEXTATTR:
974 {
975 struct puffs_vnreq_setextattr *auxt = auxbuf;
976 if (pops->puffs_setextattr == NULL) {
977 error = 0;
978 break;
979 }
980
981 error = pops->puffs_setextattr(pcc,
982 opcookie, );
983 break;
984 }
985
986 #endif
987