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