dispatcher.c revision 1.8 1 /* $NetBSD: dispatcher.c,v 1.8 2007/07/01 17:22:18 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.8 2007/07/01 17:22:18 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 PUFFS_MAKECID(pcid, &auxt->pvfsr_cid);
158
159 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTING);
160 error = pops->puffs_fs_unmount(pcc,
161 auxt->pvfsr_flags, pcid);
162 if (!error)
163 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED);
164 else
165 PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
166 break;
167 }
168
169 case PUFFS_VFS_STATVFS:
170 {
171 struct puffs_vfsreq_statvfs *auxt = auxbuf;
172 PUFFS_MAKECID(pcid, &auxt->pvfsr_cid);
173
174 error = pops->puffs_fs_statvfs(pcc,
175 &auxt->pvfsr_sb, pcid);
176 break;
177 }
178
179 case PUFFS_VFS_SYNC:
180 {
181 struct puffs_vfsreq_sync *auxt = auxbuf;
182 PUFFS_MAKECRED(pcr, &auxt->pvfsr_cred);
183 PUFFS_MAKECID(pcid, &auxt->pvfsr_cid);
184
185 error = pops->puffs_fs_sync(pcc,
186 auxt->pvfsr_waitfor, pcr, pcid);
187 break;
188 }
189
190 case PUFFS_VFS_FHTOVP:
191 {
192 struct puffs_vfsreq_fhtonode *auxt = auxbuf;
193
194 error = pops->puffs_fs_fhtonode(pcc, auxt->pvfsr_data,
195 auxt->pvfsr_dsize, &auxt->pvfsr_fhcookie,
196 &auxt->pvfsr_vtype, &auxt->pvfsr_size,
197 &auxt->pvfsr_rdev);
198
199 break;
200 }
201
202 case PUFFS_VFS_VPTOFH:
203 {
204 struct puffs_vfsreq_nodetofh *auxt = auxbuf;
205
206 error = pops->puffs_fs_nodetofh(pcc,
207 auxt->pvfsr_fhcookie, auxt->pvfsr_data,
208 &auxt->pvfsr_dsize);
209
210 break;
211 }
212
213 case PUFFS_VFS_SUSPEND:
214 {
215 struct puffs_vfsreq_suspend *auxt = auxbuf;
216
217 error = 0;
218 if (pops->puffs_fs_suspend == NULL)
219 break;
220
221 pops->puffs_fs_suspend(pcc, auxt->pvfsr_status);
222 break;
223 }
224
225 default:
226 /*
227 * I guess the kernel sees this one coming
228 */
229 error = EINVAL;
230 break;
231 }
232
233 /* XXX: audit return values */
234 /* XXX: sync with kernel */
235 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
236 switch (preq->preq_optype) {
237 case PUFFS_VN_LOOKUP:
238 {
239 struct puffs_vnreq_lookup *auxt = auxbuf;
240 struct puffs_cn pcn;
241
242 pcn.pcn_pkcnp = &auxt->pvnr_cn;
243 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
244 PUFFS_KCIDTOCID(pcn.pcn_cid, &auxt->pvnr_cn_cid);
245
246 if (buildpath) {
247 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
248 if (error)
249 break;
250 }
251
252 /* lookup *must* be present */
253 error = pops->puffs_node_lookup(pcc, opcookie,
254 &auxt->pvnr_newnode, &auxt->pvnr_vtype,
255 &auxt->pvnr_size, &auxt->pvnr_rdev, &pcn);
256
257 if (buildpath) {
258 if (error) {
259 pu->pu_pathfree(pu, &pcn.pcn_po_full);
260 } else {
261 struct puffs_node *pn;
262
263 /*
264 * did we get a new node or a
265 * recycled node?
266 */
267 pn = PU_CMAP(pu, auxt->pvnr_newnode);
268 if (pn->pn_po.po_path == NULL)
269 pn->pn_po = pcn.pcn_po_full;
270 else
271 pu->pu_pathfree(pu,
272 &pcn.pcn_po_full);
273 }
274 }
275
276 break;
277 }
278
279 case PUFFS_VN_CREATE:
280 {
281 struct puffs_vnreq_create *auxt = auxbuf;
282 struct puffs_cn pcn;
283 if (pops->puffs_node_create == NULL) {
284 error = 0;
285 break;
286 }
287
288 pcn.pcn_pkcnp = &auxt->pvnr_cn;
289 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
290 PUFFS_KCIDTOCID(pcn.pcn_cid, &auxt->pvnr_cn_cid);
291
292 if (buildpath) {
293 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
294 if (error)
295 break;
296 }
297
298 error = pops->puffs_node_create(pcc,
299 opcookie, &auxt->pvnr_newnode,
300 &pcn, &auxt->pvnr_va);
301
302 if (buildpath) {
303 if (error) {
304 pu->pu_pathfree(pu, &pcn.pcn_po_full);
305 } else {
306 struct puffs_node *pn;
307
308 pn = PU_CMAP(pu, auxt->pvnr_newnode);
309 pn->pn_po = pcn.pcn_po_full;
310 }
311 }
312
313 break;
314 }
315
316 case PUFFS_VN_MKNOD:
317 {
318 struct puffs_vnreq_mknod *auxt = auxbuf;
319 struct puffs_cn pcn;
320 if (pops->puffs_node_mknod == NULL) {
321 error = 0;
322 break;
323 }
324
325 pcn.pcn_pkcnp = &auxt->pvnr_cn;
326 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
327 PUFFS_KCIDTOCID(pcn.pcn_cid, &auxt->pvnr_cn_cid);
328
329 if (buildpath) {
330 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
331 if (error)
332 break;
333 }
334
335 error = pops->puffs_node_mknod(pcc,
336 opcookie, &auxt->pvnr_newnode,
337 &pcn, &auxt->pvnr_va);
338
339 if (buildpath) {
340 if (error) {
341 pu->pu_pathfree(pu, &pcn.pcn_po_full);
342 } else {
343 struct puffs_node *pn;
344
345 pn = PU_CMAP(pu, auxt->pvnr_newnode);
346 pn->pn_po = pcn.pcn_po_full;
347 }
348 }
349
350 break;
351 }
352
353 case PUFFS_VN_OPEN:
354 {
355 struct puffs_vnreq_open *auxt = auxbuf;
356 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
357 PUFFS_MAKECID(pcid, &auxt->pvnr_cid);
358
359 if (pops->puffs_node_open == NULL) {
360 error = 0;
361 break;
362 }
363
364 error = pops->puffs_node_open(pcc,
365 opcookie, auxt->pvnr_mode, pcr, pcid);
366 break;
367 }
368
369 case PUFFS_VN_CLOSE:
370 {
371 struct puffs_vnreq_close *auxt = auxbuf;
372 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
373 PUFFS_MAKECID(pcid, &auxt->pvnr_cid);
374
375
376 if (pops->puffs_node_close == NULL) {
377 error = 0;
378 break;
379 }
380
381 error = pops->puffs_node_close(pcc,
382 opcookie, auxt->pvnr_fflag, pcr, pcid);
383 break;
384 }
385
386 case PUFFS_VN_ACCESS:
387 {
388 struct puffs_vnreq_access *auxt = auxbuf;
389 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
390 PUFFS_MAKECID(pcid, &auxt->pvnr_cid);
391
392
393 if (pops->puffs_node_access == NULL) {
394 error = 0;
395 break;
396 }
397
398 error = pops->puffs_node_access(pcc,
399 opcookie, auxt->pvnr_mode, pcr, pcid);
400 break;
401 }
402
403 case PUFFS_VN_GETATTR:
404 {
405 struct puffs_vnreq_getattr *auxt = auxbuf;
406 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
407 PUFFS_MAKECID(pcid, &auxt->pvnr_cid);
408
409
410 if (pops->puffs_node_getattr == NULL) {
411 error = EOPNOTSUPP;
412 break;
413 }
414
415 error = pops->puffs_node_getattr(pcc,
416 opcookie, &auxt->pvnr_va, pcr, pcid);
417 break;
418 }
419
420 case PUFFS_VN_SETATTR:
421 {
422 struct puffs_vnreq_setattr *auxt = auxbuf;
423 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
424 PUFFS_MAKECID(pcid, &auxt->pvnr_cid);
425
426
427 if (pops->puffs_node_setattr == NULL) {
428 error = EOPNOTSUPP;
429 break;
430 }
431
432 error = pops->puffs_node_setattr(pcc,
433 opcookie, &auxt->pvnr_va, pcr, pcid);
434 break;
435 }
436
437 case PUFFS_VN_MMAP:
438 {
439 struct puffs_vnreq_mmap *auxt = auxbuf;
440 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
441 PUFFS_MAKECID(pcid, &auxt->pvnr_cid);
442
443
444 if (pops->puffs_node_mmap == NULL) {
445 error = 0;
446 break;
447 }
448
449 error = pops->puffs_node_mmap(pcc,
450 opcookie, auxt->pvnr_fflags, pcr, pcid);
451 break;
452 }
453
454 case PUFFS_VN_FSYNC:
455 {
456 struct puffs_vnreq_fsync *auxt = auxbuf;
457 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
458 PUFFS_MAKECID(pcid, &auxt->pvnr_cid);
459
460
461 if (pops->puffs_node_fsync == NULL) {
462 error = 0;
463 break;
464 }
465
466 error = pops->puffs_node_fsync(pcc, opcookie, pcr,
467 auxt->pvnr_flags, auxt->pvnr_offlo,
468 auxt->pvnr_offhi, pcid);
469 break;
470 }
471
472 case PUFFS_VN_SEEK:
473 {
474 struct puffs_vnreq_seek *auxt = auxbuf;
475 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
476
477 if (pops->puffs_node_seek == NULL) {
478 error = 0;
479 break;
480 }
481
482 error = pops->puffs_node_seek(pcc,
483 opcookie, auxt->pvnr_oldoff,
484 auxt->pvnr_newoff, pcr);
485 break;
486 }
487
488 case PUFFS_VN_REMOVE:
489 {
490 struct puffs_vnreq_remove *auxt = auxbuf;
491 struct puffs_cn pcn;
492 if (pops->puffs_node_remove == NULL) {
493 error = 0;
494 break;
495 }
496
497 pcn.pcn_pkcnp = &auxt->pvnr_cn;
498 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
499 PUFFS_KCIDTOCID(pcn.pcn_cid, &auxt->pvnr_cn_cid);
500
501 error = pops->puffs_node_remove(pcc,
502 opcookie, auxt->pvnr_cookie_targ, &pcn);
503 break;
504 }
505
506 case PUFFS_VN_LINK:
507 {
508 struct puffs_vnreq_link *auxt = auxbuf;
509 struct puffs_cn pcn;
510 if (pops->puffs_node_link == NULL) {
511 error = 0;
512 break;
513 }
514
515 pcn.pcn_pkcnp = &auxt->pvnr_cn;
516 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
517 PUFFS_KCIDTOCID(pcn.pcn_cid, &auxt->pvnr_cn_cid);
518
519 if (buildpath) {
520 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
521 if (error)
522 break;
523 }
524
525 error = pops->puffs_node_link(pcc,
526 opcookie, auxt->pvnr_cookie_targ, &pcn);
527 if (buildpath)
528 pu->pu_pathfree(pu, &pcn.pcn_po_full);
529
530 break;
531 }
532
533 case PUFFS_VN_RENAME:
534 {
535 struct puffs_vnreq_rename *auxt = auxbuf;
536 struct puffs_cn pcn_src, pcn_targ;
537 struct puffs_node *pn_src;
538
539 if (pops->puffs_node_rename == NULL) {
540 error = 0;
541 break;
542 }
543
544 pcn_src.pcn_pkcnp = &auxt->pvnr_cn_src;
545 PUFFS_KCREDTOCRED(pcn_src.pcn_cred,
546 &auxt->pvnr_cn_src_cred);
547 PUFFS_KCIDTOCID(pcn_src.pcn_cid,
548 &auxt->pvnr_cn_src_cid);
549
550 pcn_targ.pcn_pkcnp = &auxt->pvnr_cn_targ;
551 PUFFS_KCREDTOCRED(pcn_targ.pcn_cred,
552 &auxt->pvnr_cn_targ_cred);
553 PUFFS_KCIDTOCID(pcn_targ.pcn_cid,
554 &auxt->pvnr_cn_targ_cid);
555
556 if (buildpath) {
557 pn_src = auxt->pvnr_cookie_src;
558 pcn_src.pcn_po_full = pn_src->pn_po;
559
560 error = puffs_path_pcnbuild(pu, &pcn_targ,
561 auxt->pvnr_cookie_targdir);
562 if (error)
563 break;
564 }
565
566 error = pops->puffs_node_rename(pcc,
567 opcookie, auxt->pvnr_cookie_src,
568 &pcn_src, auxt->pvnr_cookie_targdir,
569 auxt->pvnr_cookie_targ, &pcn_targ);
570
571 if (buildpath) {
572 if (error) {
573 pu->pu_pathfree(pu,
574 &pcn_targ.pcn_po_full);
575 } else {
576 struct puffs_pathinfo pi;
577 struct puffs_pathobj po_old;
578
579 /* handle this node */
580 po_old = pn_src->pn_po;
581 pn_src->pn_po = pcn_targ.pcn_po_full;
582
583 if (pn_src->pn_va.va_type != VDIR) {
584 pu->pu_pathfree(pu, &po_old);
585 break;
586 }
587
588 /* handle all child nodes for DIRs */
589 pi.pi_old = &pcn_src.pcn_po_full;
590 pi.pi_new = &pcn_targ.pcn_po_full;
591
592 if (puffs_pn_nodewalk(pu,
593 puffs_path_prefixadj, &pi) != NULL)
594 error = ENOMEM;
595 pu->pu_pathfree(pu, &po_old);
596 }
597 }
598 break;
599 }
600
601 case PUFFS_VN_MKDIR:
602 {
603 struct puffs_vnreq_mkdir *auxt = auxbuf;
604 struct puffs_cn pcn;
605 if (pops->puffs_node_mkdir == NULL) {
606 error = 0;
607 break;
608 }
609
610 pcn.pcn_pkcnp = &auxt->pvnr_cn;
611 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
612 PUFFS_KCIDTOCID(pcn.pcn_cid, &auxt->pvnr_cn_cid);
613
614 if (buildpath) {
615 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
616 if (error)
617 break;
618 }
619
620 error = pops->puffs_node_mkdir(pcc,
621 opcookie, &auxt->pvnr_newnode,
622 &pcn, &auxt->pvnr_va);
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_RMDIR:
639 {
640 struct puffs_vnreq_rmdir *auxt = auxbuf;
641 struct puffs_cn pcn;
642 if (pops->puffs_node_rmdir == NULL) {
643 error = 0;
644 break;
645 }
646
647 pcn.pcn_pkcnp = &auxt->pvnr_cn;
648 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
649 PUFFS_KCIDTOCID(pcn.pcn_cid, &auxt->pvnr_cn_cid);
650
651 error = pops->puffs_node_rmdir(pcc,
652 opcookie, auxt->pvnr_cookie_targ, &pcn);
653 break;
654 }
655
656 case PUFFS_VN_SYMLINK:
657 {
658 struct puffs_vnreq_symlink *auxt = auxbuf;
659 struct puffs_cn pcn;
660 if (pops->puffs_node_symlink == NULL) {
661 error = 0;
662 break;
663 }
664
665 pcn.pcn_pkcnp = &auxt->pvnr_cn;
666 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
667 PUFFS_KCIDTOCID(pcn.pcn_cid, &auxt->pvnr_cn_cid);
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(pcc,
676 opcookie, &auxt->pvnr_newnode,
677 &pcn, &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_vnreq_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(pcc,
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_vnreq_readdir)
729 + auxt->pvnr_dentoff + (res - auxt->pvnr_resid);
730 break;
731 }
732
733 case PUFFS_VN_READLINK:
734 {
735 struct puffs_vnreq_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(pcc, opcookie, pcr,
745 auxt->pvnr_link, &auxt->pvnr_linklen);
746 break;
747 }
748
749 case PUFFS_VN_RECLAIM:
750 {
751 struct puffs_vnreq_reclaim *auxt = auxbuf;
752 PUFFS_MAKECID(pcid, &auxt->pvnr_cid);
753
754 if (pops->puffs_node_reclaim == NULL) {
755 error = 0;
756 break;
757 }
758
759 error = pops->puffs_node_reclaim(pcc, opcookie, pcid);
760 break;
761 }
762
763 case PUFFS_VN_INACTIVE:
764 {
765 struct puffs_vnreq_inactive *auxt = auxbuf;
766 PUFFS_MAKECID(pcid, &auxt->pvnr_cid);
767
768 if (pops->puffs_node_inactive == NULL) {
769 error = EOPNOTSUPP;
770 break;
771 }
772
773 auxt->pvnr_backendrefs = 1; /* safe default */
774 error = pops->puffs_node_inactive(pcc,
775 opcookie, pcid, &auxt->pvnr_backendrefs);
776 break;
777 }
778
779 case PUFFS_VN_PATHCONF:
780 {
781 struct puffs_vnreq_pathconf *auxt = auxbuf;
782 if (pops->puffs_node_pathconf == NULL) {
783 error = 0;
784 break;
785 }
786
787 error = pops->puffs_node_pathconf(pcc,
788 opcookie, auxt->pvnr_name,
789 &auxt->pvnr_retval);
790 break;
791 }
792
793 case PUFFS_VN_ADVLOCK:
794 {
795 struct puffs_vnreq_advlock *auxt = auxbuf;
796 if (pops->puffs_node_advlock == NULL) {
797 error = 0;
798 break;
799 }
800
801 error = pops->puffs_node_advlock(pcc,
802 opcookie, auxt->pvnr_id, auxt->pvnr_op,
803 &auxt->pvnr_fl, auxt->pvnr_flags);
804 break;
805 }
806
807 case PUFFS_VN_PRINT:
808 {
809 if (pops->puffs_node_print == NULL) {
810 error = 0;
811 break;
812 }
813
814 error = pops->puffs_node_print(pcc,
815 opcookie);
816 break;
817 }
818
819 case PUFFS_VN_READ:
820 {
821 struct puffs_vnreq_read *auxt = auxbuf;
822 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
823 size_t res;
824
825 if (pops->puffs_node_read == NULL) {
826 error = EIO;
827 break;
828 }
829
830 res = auxt->pvnr_resid;
831 error = pops->puffs_node_read(pcc,
832 opcookie, auxt->pvnr_data,
833 auxt->pvnr_offset, &auxt->pvnr_resid,
834 pcr, auxt->pvnr_ioflag);
835
836 /* need to move a bit more */
837 preq->preq_buflen = sizeof(struct puffs_vnreq_read)
838 + (res - auxt->pvnr_resid);
839 break;
840 }
841
842 case PUFFS_VN_WRITE:
843 {
844 struct puffs_vnreq_write *auxt = auxbuf;
845 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
846
847 if (pops->puffs_node_write == NULL) {
848 error = EIO;
849 break;
850 }
851
852 error = pops->puffs_node_write(pcc,
853 opcookie, auxt->pvnr_data,
854 auxt->pvnr_offset, &auxt->pvnr_resid,
855 pcr, auxt->pvnr_ioflag);
856
857 /* don't need to move data back to the kernel */
858 preq->preq_buflen = sizeof(struct puffs_vnreq_write);
859 break;
860 }
861
862 case PUFFS_VN_POLL:
863 {
864 struct puffs_vnreq_poll *auxt = auxbuf;
865 PUFFS_MAKECID(pcid, &auxt->pvnr_cid);
866
867 if (pops->puffs_node_poll == NULL) {
868 error = 0;
869
870 /* emulate genfs_poll() */
871 auxt->pvnr_events &= (POLLIN | POLLOUT
872 | POLLRDNORM | POLLWRNORM);
873
874 break;
875 }
876
877 error = pops->puffs_node_poll(pcc,
878 opcookie, &auxt->pvnr_events, pcid);
879 break;
880 }
881
882 /* holy bitrot, ryydman! */
883 #if 0
884 case PUFFS_VN_IOCTL:
885 error = pops->puffs_node_ioctl1(pcc, opcookie,
886 (struct puffs_vnreq_ioctl *)auxbuf, &pop);
887 if (error != 0)
888 break;
889 pop.pso_reqid = preq->preq_id;
890
891 /* let the kernel do it's intermediate duty */
892 error = ioctl(pu->pu_kargs.pa_fd, PUFFSSIZEOP, &pop);
893 /*
894 * XXX: I don't actually know what the correct
895 * thing to do in case of an error is, so I'll
896 * just ignore it for the time being.
897 */
898 error = pops->puffs_node_ioctl2(pcc, opcookie,
899 (struct puffs_vnreq_ioctl *)auxbuf, &pop);
900 break;
901
902 case PUFFS_VN_FCNTL:
903 error = pops->puffs_node_fcntl1(pcc, opcookie,
904 (struct puffs_vnreq_fcntl *)auxbuf, &pop);
905 if (error != 0)
906 break;
907 pop.pso_reqid = preq->preq_id;
908
909 /* let the kernel do it's intermediate duty */
910 error = ioctl(pu->pu_kargs.pa_fd, PUFFSSIZEOP, &pop);
911 /*
912 * XXX: I don't actually know what the correct
913 * thing to do in case of an error is, so I'll
914 * just ignore it for the time being.
915 */
916 error = pops->puffs_node_fcntl2(pcc, opcookie,
917 (struct puffs_vnreq_fcntl *)auxbuf, &pop);
918 break;
919 #endif
920
921 default:
922 printf("inval op %d\n", preq->preq_optype);
923 error = EINVAL;
924 break;
925 }
926 } else {
927 /*
928 * this one also
929 */
930 error = EINVAL;
931 }
932
933 preq->preq_rv = error;
934 pcc->pcc_flags |= PCC_DONE;
935
936 /*
937 * Note, we are calling this from here so that we can run it
938 * off of the continuation stack. Otherwise puffs_goto() would
939 * not work.
940 */
941 processresult(pcc, pcc->pcc_ppr, rv);
942 }
943
944 static void
945 processresult(struct puffs_cc *pcc, struct puffs_putreq *ppr, int how)
946 {
947 struct puffs_usermount *pu = puffs_cc_getusermount(pcc);
948
949 /* check if we need to store this reply */
950 switch (how) {
951 case PUFFCALL_ANSWER:
952 if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
953 puffsdump_rv(pcc->pcc_preq);
954
955 if (pcc->pcc_flags & PCC_REALCC)
956 puffs_req_putcc(ppr, pcc);
957 else
958 puffs_req_put(ppr, pcc->pcc_preq);
959 break;
960 case PUFFCALL_IGNORE:
961 if (pcc->pcc_flags & PCC_REALCC)
962 LIST_INSERT_HEAD(&pu->pu_ccnukelst, pcc, nlst_entries);
963 break;
964 case PUFFCALL_AGAIN:
965 if (pcc->pcc_flags & PCC_FAKECC)
966 assert(pcc->pcc_flags & PCC_DONE);
967 break;
968 default:
969 assert(/*CONSTCOND*/0);
970 }
971
972 /* who needs information when you're living on borrowed time? */
973 if (pcc->pcc_flags & PCC_BORROWED)
974 puffs_cc_yield(pcc); /* back to borrow source */
975 }
976
977
978 #if 0
979 case PUFFS_VN_KQFILTER:
980 {
981 struct puffs_vnreq_kqfilter *auxt = auxbuf;
982 if (pops->puffs_node_kqfilter == NULL) {
983 error = 0;
984 break;
985 }
986
987 error = pops->puffs_node_kqfilter(pcc,
988 opcookie, );
989 break;
990 }
991
992 case PUFFS_VN_CLOSEEXTATTR:
993 {
994 struct puffs_vnreq_closeextattr *auxt = auxbuf;
995 if (pops->puffs_closeextattr == NULL) {
996 error = 0;
997 break;
998 }
999
1000 error = pops->puffs_closeextattr(pcc,
1001 opcookie, );
1002 break;
1003 }
1004
1005 case PUFFS_VN_GETEXTATTR:
1006 {
1007 struct puffs_vnreq_getextattr *auxt = auxbuf;
1008 if (pops->puffs_getextattr == NULL) {
1009 error = 0;
1010 break;
1011 }
1012
1013 error = pops->puffs_getextattr(pcc,
1014 opcookie, );
1015 break;
1016 }
1017
1018 case PUFFS_VN_LISTEXTATTR:
1019 {
1020 struct puffs_vnreq_listextattr *auxt = auxbuf;
1021 if (pops->puffs_listextattr == NULL) {
1022 error = 0;
1023 break;
1024 }
1025
1026 error = pops->puffs_listextattr(pcc,
1027 opcookie, );
1028 break;
1029 }
1030
1031 case PUFFS_VN_OPENEXTATTR:
1032 {
1033 struct puffs_vnreq_openextattr *auxt = auxbuf;
1034 if (pops->puffs_openextattr == NULL) {
1035 error = 0;
1036 break;
1037 }
1038
1039 error = pops->puffs_openextattr(pcc,
1040 opcookie, );
1041 break;
1042 }
1043
1044 case PUFFS_VN_DELETEEXTATTR:
1045 {
1046 struct puffs_vnreq_deleteextattr *auxt = auxbuf;
1047 if (pops->puffs_deleteextattr == NULL) {
1048 error = 0;
1049 break;
1050 }
1051
1052 error = pops->puffs_deleteextattr(pcc,
1053 opcookie, );
1054 break;
1055 }
1056
1057 case PUFFS_VN_SETEXTATTR:
1058 {
1059 struct puffs_vnreq_setextattr *auxt = auxbuf;
1060 if (pops->puffs_setextattr == NULL) {
1061 error = 0;
1062 break;
1063 }
1064
1065 error = pops->puffs_setextattr(pcc,
1066 opcookie, );
1067 break;
1068 }
1069
1070 #endif
1071