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