Remove building with NOCRYPTO option
[minix.git] / lib / libpuffs / dispatcher.c
blob79cc28de5f68eb831552b4c2602b9bc7fc700792
1 /* $NetBSD: dispatcher.c,v 1.48 2014/10/31 13:56:04 manu Exp $ */
3 /*
4 * Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved.
6 * Development of this software was supported by the
7 * Ulla Tuominen Foundation, the Finnish Cultural Foundation and
8 * Research Foundation of Helsinki University of Technology.
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.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #if !defined(lint)
34 __RCSID("$NetBSD: dispatcher.c,v 1.48 2014/10/31 13:56:04 manu Exp $");
35 #endif /* !lint */
37 #include <sys/types.h>
38 #include <sys/poll.h>
40 #include <assert.h>
41 #include <errno.h>
42 #include <pthread.h>
43 #include <puffs.h>
44 #include <puffsdump.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <unistd.h>
49 #include "puffs_priv.h"
51 #define PUFFS_USE_FS_TTL(pu) (pu->pu_flags & PUFFS_KFLAG_CACHE_FS_TTL)
53 static void dispatch(struct puffs_cc *);
55 /* for our eyes only */
56 void
57 puffs__ml_dispatch(struct puffs_usermount *pu, struct puffs_framebuf *pb)
59 struct puffs_cc *pcc = puffs_cc_getcc(pu);
60 struct puffs_req *preq;
62 pcc->pcc_pb = pb;
63 pcc->pcc_flags |= PCC_MLCONT;
64 dispatch(pcc);
66 /* Put result to kernel sendqueue if necessary */
67 preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
68 if (PUFFSOP_WANTREPLY(preq->preq_opclass)) {
69 if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
70 puffsdump_rv(preq);
72 puffs_framev_enqueue_justsend(pu, pu->pu_fd,
73 pcc->pcc_pb, 0, 0);
74 } else {
75 puffs_framebuf_destroy(pcc->pcc_pb);
78 /* who needs information when you're living on borrowed time? */
79 if (pcc->pcc_flags & PCC_BORROWED) {
80 puffs_cc_yield(pcc); /* back to borrow source */
82 pcc->pcc_flags = 0;
85 /* public, but not really tested and only semi-supported */
86 int
87 puffs_dispatch_create(struct puffs_usermount *pu, struct puffs_framebuf *pb,
88 struct puffs_cc **pccp)
90 struct puffs_cc *pcc;
92 if (puffs__cc_create(pu, dispatch, &pcc) == -1)
93 return -1;
95 pcc->pcc_pb = pb;
96 *pccp = pcc;
98 return 0;
102 puffs_dispatch_exec(struct puffs_cc *pcc, struct puffs_framebuf **pbp)
104 int rv;
106 puffs_cc_continue(pcc);
108 if (pcc->pcc_flags & PCC_DONE) {
109 rv = 1;
110 *pbp = pcc->pcc_pb;
111 pcc->pcc_flags = 0;
112 puffs__cc_destroy(pcc, 0);
113 } else {
114 rv = 0;
117 return rv;
120 static void
121 dispatch(struct puffs_cc *pcc)
123 struct puffs_usermount *pu = pcc->pcc_pu;
124 struct puffs_ops *pops = &pu->pu_ops;
125 struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
126 void *auxbuf; /* help with typecasting */
127 puffs_cookie_t opcookie;
128 int error = 0, buildpath, pncookie;
130 /* XXX: smaller hammer, please */
131 if ((PUFFSOP_OPCLASS(preq->preq_opclass == PUFFSOP_VFS &&
132 preq->preq_optype == PUFFS_VFS_VPTOFH)) ||
133 (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN &&
134 (preq->preq_optype == PUFFS_VN_READDIR
135 || preq->preq_optype == PUFFS_VN_READ))) {
136 if (puffs_framebuf_reserve_space(pcc->pcc_pb,
137 PUFFS_MSG_MAXSIZE) == -1)
138 error = errno;
139 preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
142 auxbuf = preq;
143 opcookie = preq->preq_cookie;
145 assert((pcc->pcc_flags & PCC_DONE) == 0);
147 buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH;
148 pncookie = pu->pu_flags & PUFFS_FLAG_PNCOOKIE;
149 assert(!buildpath || pncookie);
151 preq->preq_setbacks = 0;
153 if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
154 puffsdump_req(preq);
156 puffs__cc_setcaller(pcc, preq->preq_pid, preq->preq_lid);
158 /* pre-operation */
159 if (pu->pu_oppre)
160 pu->pu_oppre(pu);
162 if (error)
163 goto out;
165 /* Execute actual operation */
166 if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
167 switch (preq->preq_optype) {
168 case PUFFS_VFS_UNMOUNT:
170 struct puffs_vfsmsg_unmount *auxt = auxbuf;
172 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTING);
173 error = pops->puffs_fs_unmount(pu, auxt->pvfsr_flags);
174 if (!error)
175 PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED);
176 else
177 PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
178 break;
181 case PUFFS_VFS_STATVFS:
183 struct puffs_vfsmsg_statvfs *auxt = auxbuf;
185 error = pops->puffs_fs_statvfs(pu, &auxt->pvfsr_sb);
186 break;
189 case PUFFS_VFS_SYNC:
191 struct puffs_vfsmsg_sync *auxt = auxbuf;
192 PUFFS_MAKECRED(pcr, &auxt->pvfsr_cred);
194 error = pops->puffs_fs_sync(pu,
195 auxt->pvfsr_waitfor, pcr);
196 break;
199 case PUFFS_VFS_FHTOVP:
201 struct puffs_vfsmsg_fhtonode *auxt = auxbuf;
202 struct puffs_newinfo pni;
204 pni.pni_cookie = &auxt->pvfsr_fhcookie;
205 pni.pni_vtype = &auxt->pvfsr_vtype;
206 pni.pni_size = &auxt->pvfsr_size;
207 pni.pni_rdev = &auxt->pvfsr_rdev;
208 pni.pni_va = NULL;
209 pni.pni_va_ttl = NULL;
210 pni.pni_cn_ttl = NULL;
212 error = pops->puffs_fs_fhtonode(pu, auxt->pvfsr_data,
213 auxt->pvfsr_dsize, &pni);
215 break;
218 case PUFFS_VFS_VPTOFH:
220 struct puffs_vfsmsg_nodetofh *auxt = auxbuf;
222 error = pops->puffs_fs_nodetofh(pu,
223 auxt->pvfsr_fhcookie, auxt->pvfsr_data,
224 &auxt->pvfsr_dsize);
226 break;
229 case PUFFS_VFS_EXTATTRCTL:
231 struct puffs_vfsmsg_extattrctl *auxt = auxbuf;
232 const char *attrname;
233 int flags;
235 if (pops->puffs_fs_extattrctl == NULL) {
236 error = EOPNOTSUPP;
237 break;
240 if (auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASATTRNAME)
241 attrname = auxt->pvfsr_attrname;
242 else
243 attrname = NULL;
245 flags = auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASNODE;
246 error = pops->puffs_fs_extattrctl(pu, auxt->pvfsr_cmd,
247 opcookie, flags,
248 auxt->pvfsr_attrnamespace, attrname);
249 break;
252 default:
254 * I guess the kernel sees this one coming
256 error = EINVAL;
257 break;
260 /* XXX: audit return values */
261 /* XXX: sync with kernel */
262 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
263 switch (preq->preq_optype) {
264 case PUFFS_VN_LOOKUP:
266 struct puffs_vnmsg_lookup *auxt = auxbuf;
267 struct puffs_newinfo pni;
268 struct puffs_cn pcn;
269 struct puffs_node *pn = NULL;
271 pcn.pcn_pkcnp = &auxt->pvnr_cn;
272 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
273 pni.pni_cookie = &auxt->pvnr_newnode;
274 pni.pni_vtype = &auxt->pvnr_vtype;
275 pni.pni_size = &auxt->pvnr_size;
276 pni.pni_rdev = &auxt->pvnr_rdev;
277 pni.pni_va = &auxt->pvnr_va;
278 pni.pni_va_ttl = &auxt->pvnr_va_ttl;
279 pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
281 if (buildpath) {
282 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
283 if (error)
284 break;
287 /* lookup *must* be present */
288 error = pops->puffs_node_lookup(pu, opcookie,
289 &pni, &pcn);
291 if (buildpath) {
292 if (error) {
293 pu->pu_pathfree(pu, &pcn.pcn_po_full);
294 } else {
296 * did we get a new node or a
297 * recycled node?
299 pn = PU_CMAP(pu, auxt->pvnr_newnode);
300 if (pn->pn_po.po_path == NULL)
301 pn->pn_po = pcn.pcn_po_full;
302 else
303 pu->pu_pathfree(pu,
304 &pcn.pcn_po_full);
308 if (pncookie && !error) {
309 if (pn == NULL)
310 pn = PU_CMAP(pu, auxt->pvnr_newnode);
311 pn->pn_nlookup++;
313 break;
316 case PUFFS_VN_CREATE:
318 struct puffs_vnmsg_create *auxt = auxbuf;
319 struct puffs_newinfo pni;
320 struct puffs_cn pcn;
321 struct puffs_node *pn = NULL;
323 if (pops->puffs_node_create == NULL) {
324 error = 0;
325 break;
328 pcn.pcn_pkcnp = &auxt->pvnr_cn;
329 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
331 memset(&pni, 0, sizeof(pni));
332 pni.pni_cookie = &auxt->pvnr_newnode;
333 pni.pni_va = &auxt->pvnr_va;
334 pni.pni_va_ttl = &auxt->pvnr_va_ttl;
335 pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
337 if (buildpath) {
338 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
339 if (error)
340 break;
343 error = pops->puffs_node_create(pu,
344 opcookie, &pni, &pcn, &auxt->pvnr_va);
346 if (buildpath) {
347 if (error) {
348 pu->pu_pathfree(pu, &pcn.pcn_po_full);
349 } else {
350 pn = PU_CMAP(pu, auxt->pvnr_newnode);
351 pn->pn_po = pcn.pcn_po_full;
355 if (pncookie && !error) {
356 if (pn == NULL)
357 pn = PU_CMAP(pu, auxt->pvnr_newnode);
358 pn->pn_nlookup++;
360 break;
363 case PUFFS_VN_MKNOD:
365 struct puffs_vnmsg_mknod *auxt = auxbuf;
366 struct puffs_newinfo pni;
367 struct puffs_cn pcn;
368 struct puffs_node *pn = NULL;
370 if (pops->puffs_node_mknod == NULL) {
371 error = 0;
372 break;
375 pcn.pcn_pkcnp = &auxt->pvnr_cn;
376 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
378 memset(&pni, 0, sizeof(pni));
379 pni.pni_cookie = &auxt->pvnr_newnode;
380 pni.pni_va = &auxt->pvnr_va;
381 pni.pni_va_ttl = &auxt->pvnr_va_ttl;
382 pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
384 if (buildpath) {
385 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
386 if (error)
387 break;
390 error = pops->puffs_node_mknod(pu,
391 opcookie, &pni, &pcn, &auxt->pvnr_va);
393 if (buildpath) {
394 if (error) {
395 pu->pu_pathfree(pu, &pcn.pcn_po_full);
396 } else {
397 pn = PU_CMAP(pu, auxt->pvnr_newnode);
398 pn->pn_po = pcn.pcn_po_full;
402 if (pncookie && !error) {
403 if (pn == NULL)
404 pn = PU_CMAP(pu, auxt->pvnr_newnode);
405 pn->pn_nlookup++;
407 break;
410 case PUFFS_VN_OPEN:
412 struct puffs_vnmsg_open *auxt = auxbuf;
413 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
415 if (pops->puffs_node_open2 != NULL) {
416 error = pops->puffs_node_open2(pu,
417 opcookie, auxt->pvnr_mode, pcr,
418 &auxt->pvnr_oflags);
420 break;
423 if (pops->puffs_node_open == NULL) {
424 error = 0;
425 break;
428 error = pops->puffs_node_open(pu,
429 opcookie, auxt->pvnr_mode, pcr);
430 break;
433 case PUFFS_VN_CLOSE:
435 struct puffs_vnmsg_close *auxt = auxbuf;
436 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
438 if (pops->puffs_node_close == NULL) {
439 error = 0;
440 break;
443 error = pops->puffs_node_close(pu,
444 opcookie, auxt->pvnr_fflag, pcr);
445 break;
448 case PUFFS_VN_ACCESS:
450 struct puffs_vnmsg_access *auxt = auxbuf;
451 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
453 if (pops->puffs_node_access == NULL) {
454 error = 0;
455 break;
458 error = pops->puffs_node_access(pu,
459 opcookie, auxt->pvnr_mode, pcr);
460 break;
463 case PUFFS_VN_GETATTR:
465 struct puffs_vnmsg_getattr *auxt = auxbuf;
466 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
468 if (PUFFS_USE_FS_TTL(pu)) {
469 if (pops->puffs_node_getattr_ttl == NULL) {
470 error = EOPNOTSUPP;
471 break;
474 error = pops->puffs_node_getattr_ttl(pu,
475 opcookie, &auxt->pvnr_va, pcr,
476 &auxt->pvnr_va_ttl);
477 } else {
478 if (pops->puffs_node_getattr == NULL) {
479 error = EOPNOTSUPP;
480 break;
483 error = pops->puffs_node_getattr(pu,
484 opcookie, &auxt->pvnr_va, pcr);
486 break;
489 case PUFFS_VN_SETATTR:
491 struct puffs_vnmsg_setattr *auxt = auxbuf;
492 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
494 if (PUFFS_USE_FS_TTL(pu)) {
495 int xflag = 0;
497 if (pops->puffs_node_setattr_ttl == NULL) {
498 error = EOPNOTSUPP;
499 break;
502 if (!PUFFSOP_WANTREPLY(preq->preq_opclass))
503 xflag |= PUFFS_SETATTR_FAF;
505 error = pops->puffs_node_setattr_ttl(pu,
506 opcookie, &auxt->pvnr_va, pcr,
507 &auxt->pvnr_va_ttl, xflag);
508 } else {
509 if (pops->puffs_node_setattr == NULL) {
510 error = EOPNOTSUPP;
511 break;
514 error = pops->puffs_node_setattr(pu,
515 opcookie, &auxt->pvnr_va, pcr);
517 break;
520 case PUFFS_VN_MMAP:
522 struct puffs_vnmsg_mmap *auxt = auxbuf;
523 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
525 if (pops->puffs_node_mmap == NULL) {
526 error = 0;
527 break;
530 error = pops->puffs_node_mmap(pu,
531 opcookie, auxt->pvnr_prot, pcr);
532 break;
535 case PUFFS_VN_FSYNC:
537 struct puffs_vnmsg_fsync *auxt = auxbuf;
538 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
540 if (pops->puffs_node_fsync == NULL) {
541 error = 0;
542 break;
545 error = pops->puffs_node_fsync(pu, opcookie, pcr,
546 auxt->pvnr_flags, auxt->pvnr_offlo,
547 auxt->pvnr_offhi);
548 break;
551 case PUFFS_VN_SEEK:
553 struct puffs_vnmsg_seek *auxt = auxbuf;
554 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
556 if (pops->puffs_node_seek == NULL) {
557 error = 0;
558 break;
561 error = pops->puffs_node_seek(pu,
562 opcookie, auxt->pvnr_oldoff,
563 auxt->pvnr_newoff, pcr);
564 break;
567 case PUFFS_VN_REMOVE:
569 struct puffs_vnmsg_remove *auxt = auxbuf;
570 struct puffs_cn pcn;
571 if (pops->puffs_node_remove == NULL) {
572 error = 0;
573 break;
576 pcn.pcn_pkcnp = &auxt->pvnr_cn;
577 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
579 error = pops->puffs_node_remove(pu,
580 opcookie, auxt->pvnr_cookie_targ, &pcn);
581 break;
584 case PUFFS_VN_LINK:
586 struct puffs_vnmsg_link *auxt = auxbuf;
587 struct puffs_cn pcn;
588 if (pops->puffs_node_link == NULL) {
589 error = 0;
590 break;
593 pcn.pcn_pkcnp = &auxt->pvnr_cn;
594 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
596 if (buildpath) {
597 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
598 if (error)
599 break;
602 error = pops->puffs_node_link(pu,
603 opcookie, auxt->pvnr_cookie_targ, &pcn);
604 if (buildpath)
605 pu->pu_pathfree(pu, &pcn.pcn_po_full);
607 break;
610 case PUFFS_VN_RENAME:
612 struct puffs_vnmsg_rename *auxt = auxbuf;
613 struct puffs_cn pcn_src, pcn_targ;
614 struct puffs_node *pn_src;
616 if (pops->puffs_node_rename == NULL) {
617 error = 0;
618 break;
621 pcn_src.pcn_pkcnp = &auxt->pvnr_cn_src;
622 PUFFS_KCREDTOCRED(pcn_src.pcn_cred,
623 &auxt->pvnr_cn_src_cred);
625 pcn_targ.pcn_pkcnp = &auxt->pvnr_cn_targ;
626 PUFFS_KCREDTOCRED(pcn_targ.pcn_cred,
627 &auxt->pvnr_cn_targ_cred);
629 if (buildpath) {
630 pn_src = auxt->pvnr_cookie_src;
631 pcn_src.pcn_po_full = pn_src->pn_po;
633 error = puffs_path_pcnbuild(pu, &pcn_targ,
634 auxt->pvnr_cookie_targdir);
635 if (error)
636 break;
639 error = pops->puffs_node_rename(pu,
640 opcookie, auxt->pvnr_cookie_src,
641 &pcn_src, auxt->pvnr_cookie_targdir,
642 auxt->pvnr_cookie_targ, &pcn_targ);
644 if (buildpath) {
645 if (error) {
646 pu->pu_pathfree(pu,
647 &pcn_targ.pcn_po_full);
648 } else {
649 struct puffs_pathinfo pi;
650 struct puffs_pathobj po_old;
652 /* handle this node */
653 po_old = pn_src->pn_po;
654 pn_src->pn_po = pcn_targ.pcn_po_full;
656 if (pn_src->pn_va.va_type != VDIR) {
657 pu->pu_pathfree(pu, &po_old);
658 break;
661 /* handle all child nodes for DIRs */
662 pi.pi_old = &pcn_src.pcn_po_full;
663 pi.pi_new = &pcn_targ.pcn_po_full;
665 PU_LOCK();
666 if (puffs_pn_nodewalk(pu,
667 puffs_path_prefixadj, &pi) != NULL)
668 error = ENOMEM;
669 PU_UNLOCK();
670 pu->pu_pathfree(pu, &po_old);
673 break;
676 case PUFFS_VN_MKDIR:
678 struct puffs_vnmsg_mkdir *auxt = auxbuf;
679 struct puffs_newinfo pni;
680 struct puffs_cn pcn;
681 struct puffs_node *pn = NULL;
683 if (pops->puffs_node_mkdir == NULL) {
684 error = 0;
685 break;
688 pcn.pcn_pkcnp = &auxt->pvnr_cn;
689 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
691 memset(&pni, 0, sizeof(pni));
692 pni.pni_cookie = &auxt->pvnr_newnode;
693 pni.pni_va = &auxt->pvnr_va;
694 pni.pni_va_ttl = &auxt->pvnr_va_ttl;
695 pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
697 if (buildpath) {
698 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
699 if (error)
700 break;
703 error = pops->puffs_node_mkdir(pu,
704 opcookie, &pni, &pcn, &auxt->pvnr_va);
706 if (buildpath) {
707 if (error) {
708 pu->pu_pathfree(pu, &pcn.pcn_po_full);
709 } else {
710 pn = PU_CMAP(pu, auxt->pvnr_newnode);
711 pn->pn_po = pcn.pcn_po_full;
715 if (pncookie && !error) {
716 if (pn == NULL)
717 pn = PU_CMAP(pu, auxt->pvnr_newnode);
718 pn->pn_nlookup++;
720 break;
723 case PUFFS_VN_RMDIR:
725 struct puffs_vnmsg_rmdir *auxt = auxbuf;
726 struct puffs_cn pcn;
727 if (pops->puffs_node_rmdir == NULL) {
728 error = 0;
729 break;
732 pcn.pcn_pkcnp = &auxt->pvnr_cn;
733 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
735 error = pops->puffs_node_rmdir(pu,
736 opcookie, auxt->pvnr_cookie_targ, &pcn);
737 break;
740 case PUFFS_VN_SYMLINK:
742 struct puffs_vnmsg_symlink *auxt = auxbuf;
743 struct puffs_newinfo pni;
744 struct puffs_cn pcn;
745 struct puffs_node *pn = NULL;
747 if (pops->puffs_node_symlink == NULL) {
748 error = 0;
749 break;
752 pcn.pcn_pkcnp = &auxt->pvnr_cn;
753 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
755 memset(&pni, 0, sizeof(pni));
756 pni.pni_cookie = &auxt->pvnr_newnode;
757 pni.pni_va = &auxt->pvnr_va;
758 pni.pni_va_ttl = &auxt->pvnr_va_ttl;
759 pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
761 if (buildpath) {
762 error = puffs_path_pcnbuild(pu, &pcn, opcookie);
763 if (error)
764 break;
767 error = pops->puffs_node_symlink(pu,
768 opcookie, &pni, &pcn,
769 &auxt->pvnr_va, auxt->pvnr_link);
771 if (buildpath) {
772 if (error) {
773 pu->pu_pathfree(pu, &pcn.pcn_po_full);
774 } else {
775 pn = PU_CMAP(pu, auxt->pvnr_newnode);
776 pn->pn_po = pcn.pcn_po_full;
780 if (pncookie && !error) {
781 if (pn == NULL)
782 pn = PU_CMAP(pu, auxt->pvnr_newnode);
783 pn->pn_nlookup++;
785 break;
788 case PUFFS_VN_READDIR:
790 struct puffs_vnmsg_readdir *auxt = auxbuf;
791 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
792 struct dirent *dent;
793 off_t *cookies;
794 size_t res, origcookies;
796 if (pops->puffs_node_readdir == NULL) {
797 error = 0;
798 break;
801 if (auxt->pvnr_ncookies) {
802 /* LINTED: pvnr_data is __aligned() */
803 cookies = (off_t *)auxt->pvnr_data;
804 origcookies = auxt->pvnr_ncookies;
805 } else {
806 cookies = NULL;
807 origcookies = 0;
809 /* LINTED: dentoff is aligned in the kernel */
810 dent = (struct dirent *)
811 (auxt->pvnr_data + auxt->pvnr_dentoff);
813 res = auxt->pvnr_resid;
814 error = pops->puffs_node_readdir(pu,
815 opcookie, dent, &auxt->pvnr_offset,
816 &auxt->pvnr_resid, pcr, &auxt->pvnr_eofflag,
817 cookies, &auxt->pvnr_ncookies);
819 /* much easier to track non-working NFS */
820 assert(auxt->pvnr_ncookies <= origcookies);
822 /* need to move a bit more */
823 preq->preq_buflen = sizeof(struct puffs_vnmsg_readdir)
824 + auxt->pvnr_dentoff + (res - auxt->pvnr_resid);
825 break;
828 case PUFFS_VN_READLINK:
830 struct puffs_vnmsg_readlink *auxt = auxbuf;
831 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
833 if (pops->puffs_node_readlink == NULL) {
834 error = EOPNOTSUPP;
835 break;
838 /*LINTED*/
839 error = pops->puffs_node_readlink(pu, opcookie, pcr,
840 auxt->pvnr_link, &auxt->pvnr_linklen);
841 break;
844 case PUFFS_VN_RECLAIM:
846 struct puffs_vnmsg_reclaim *auxt = auxbuf;
847 struct puffs_node *pn;
849 if (pops->puffs_node_reclaim2 != NULL) {
850 error = pops->puffs_node_reclaim2(pu, opcookie,
851 auxt->pvnr_nlookup);
852 break;
855 if (pops->puffs_node_reclaim == NULL) {
856 error = 0;
857 break;
861 * This fixes a race condition,
862 * where a node in reclaimed by kernel
863 * after a lookup request is sent,
864 * but before the reply, leaving the kernel
865 * with a invalid vnode/cookie reference.
867 if (pncookie) {
868 pn = PU_CMAP(pu, opcookie);
869 pn->pn_nlookup -= auxt->pvnr_nlookup;
870 if (pn->pn_nlookup >= 1) {
871 error = 0;
872 break;
876 error = pops->puffs_node_reclaim(pu, opcookie);
877 break;
880 case PUFFS_VN_INACTIVE:
883 if (pops->puffs_node_inactive == NULL) {
884 error = EOPNOTSUPP;
885 break;
888 error = pops->puffs_node_inactive(pu, opcookie);
889 break;
892 case PUFFS_VN_PATHCONF:
894 struct puffs_vnmsg_pathconf *auxt = auxbuf;
895 if (pops->puffs_node_pathconf == NULL) {
896 error = 0;
897 break;
900 error = pops->puffs_node_pathconf(pu,
901 opcookie, auxt->pvnr_name,
902 &auxt->pvnr_retval);
903 break;
906 case PUFFS_VN_ADVLOCK:
908 struct puffs_vnmsg_advlock *auxt = auxbuf;
909 if (pops->puffs_node_advlock == NULL) {
910 error = 0;
911 break;
914 error = pops->puffs_node_advlock(pu,
915 opcookie, auxt->pvnr_id, auxt->pvnr_op,
916 &auxt->pvnr_fl, auxt->pvnr_flags);
917 break;
920 case PUFFS_VN_PRINT:
922 if (pops->puffs_node_print == NULL) {
923 error = 0;
924 break;
927 error = pops->puffs_node_print(pu,
928 opcookie);
929 break;
932 case PUFFS_VN_ABORTOP:
934 struct puffs_vnmsg_abortop *auxt = auxbuf;
935 struct puffs_cn pcn;
937 if (pops->puffs_node_abortop == NULL) {
938 error = 0;
939 break;
942 pcn.pcn_pkcnp = &auxt->pvnr_cn;
943 PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
945 error = pops->puffs_node_abortop(pu, opcookie, &pcn);
947 break;
950 case PUFFS_VN_READ:
952 struct puffs_vnmsg_read *auxt = auxbuf;
953 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
954 size_t res;
956 if (pops->puffs_node_read == NULL) {
957 error = EIO;
958 break;
961 res = auxt->pvnr_resid;
962 error = pops->puffs_node_read(pu,
963 opcookie, auxt->pvnr_data,
964 auxt->pvnr_offset, &auxt->pvnr_resid,
965 pcr, auxt->pvnr_ioflag);
967 /* need to move a bit more */
968 preq->preq_buflen = sizeof(struct puffs_vnmsg_read)
969 + (res - auxt->pvnr_resid);
970 break;
973 case PUFFS_VN_WRITE:
975 struct puffs_vnmsg_write *auxt = auxbuf;
976 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
978 if (pops->puffs_node_write2 != NULL) {
979 int xflag = 0;
981 if (!PUFFSOP_WANTREPLY(preq->preq_opclass))
982 xflag |= PUFFS_SETATTR_FAF;
984 error = pops->puffs_node_write2(pu,
985 opcookie, auxt->pvnr_data,
986 auxt->pvnr_offset, &auxt->pvnr_resid,
987 pcr, auxt->pvnr_ioflag, xflag);
989 } else if (pops->puffs_node_write != NULL) {
990 error = pops->puffs_node_write(pu,
991 opcookie, auxt->pvnr_data,
992 auxt->pvnr_offset, &auxt->pvnr_resid,
993 pcr, auxt->pvnr_ioflag);
994 } else {
995 error = EIO;
996 break;
1000 /* don't need to move data back to the kernel */
1001 preq->preq_buflen = sizeof(struct puffs_vnmsg_write);
1002 break;
1005 case PUFFS_VN_POLL:
1007 struct puffs_vnmsg_poll *auxt = auxbuf;
1009 if (pops->puffs_node_poll == NULL) {
1010 error = 0;
1012 /* emulate genfs_poll() */
1013 auxt->pvnr_events &= (POLLIN | POLLOUT
1014 | POLLRDNORM | POLLWRNORM);
1016 break;
1019 error = pops->puffs_node_poll(pu,
1020 opcookie, &auxt->pvnr_events);
1021 break;
1024 case PUFFS_VN_GETEXTATTR:
1026 struct puffs_vnmsg_getextattr *auxt = auxbuf;
1027 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
1028 size_t res, *resp, *sizep;
1029 uint8_t *data;
1031 if (pops->puffs_node_getextattr == NULL) {
1032 error = EOPNOTSUPP;
1033 break;
1036 if (auxt->pvnr_datasize)
1037 sizep = &auxt->pvnr_datasize;
1038 else
1039 sizep = NULL;
1041 res = auxt->pvnr_resid;
1042 if (res > 0) {
1043 data = auxt->pvnr_data;
1044 resp = &auxt->pvnr_resid;
1045 } else {
1046 data = NULL;
1047 resp = NULL;
1050 error = pops->puffs_node_getextattr(pu,
1051 opcookie, auxt->pvnr_attrnamespace,
1052 auxt->pvnr_attrname, sizep, data, resp, pcr);
1054 /* need to move a bit more? */
1055 preq->preq_buflen =
1056 sizeof(struct puffs_vnmsg_getextattr)
1057 + (res - auxt->pvnr_resid);
1058 break;
1061 case PUFFS_VN_SETEXTATTR:
1063 struct puffs_vnmsg_setextattr *auxt = auxbuf;
1064 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
1065 size_t *resp;
1066 uint8_t *data;
1068 if (pops->puffs_node_setextattr == NULL) {
1069 error = EOPNOTSUPP;
1070 break;
1073 if (auxt->pvnr_resid > 0) {
1074 data = auxt->pvnr_data;
1075 resp = &auxt->pvnr_resid;
1076 } else {
1077 data = NULL;
1078 resp = NULL;
1081 error = pops->puffs_node_setextattr(pu,
1082 opcookie, auxt->pvnr_attrnamespace,
1083 auxt->pvnr_attrname, data, resp, pcr);
1084 break;
1087 case PUFFS_VN_LISTEXTATTR:
1089 struct puffs_vnmsg_listextattr *auxt = auxbuf;
1090 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
1091 size_t res, *resp, *sizep;
1092 int flag;
1093 uint8_t *data;
1095 if (pops->puffs_node_listextattr == NULL) {
1096 error = EOPNOTSUPP;
1097 break;
1100 if (auxt->pvnr_datasize)
1101 sizep = &auxt->pvnr_datasize;
1102 else
1103 sizep = NULL;
1105 res = auxt->pvnr_resid;
1106 if (res > 0) {
1107 data = auxt->pvnr_data;
1108 resp = &auxt->pvnr_resid;
1109 } else {
1110 data = NULL;
1111 resp = NULL;
1114 res = auxt->pvnr_resid;
1115 flag = auxt->pvnr_flag;
1116 error = pops->puffs_node_listextattr(pu,
1117 opcookie, auxt->pvnr_attrnamespace,
1118 sizep, data, resp, flag, pcr);
1120 /* need to move a bit more? */
1121 preq->preq_buflen =
1122 sizeof(struct puffs_vnmsg_listextattr)
1123 + (res - auxt->pvnr_resid);
1124 break;
1127 case PUFFS_VN_DELETEEXTATTR:
1129 struct puffs_vnmsg_deleteextattr *auxt = auxbuf;
1130 PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
1132 if (pops->puffs_node_deleteextattr == NULL) {
1133 error = EOPNOTSUPP;
1134 break;
1137 error = pops->puffs_node_deleteextattr(pu,
1138 opcookie, auxt->pvnr_attrnamespace,
1139 auxt->pvnr_attrname, pcr);
1140 break;
1143 case PUFFS_VN_FALLOCATE:
1145 struct puffs_vnmsg_fallocate *auxt = auxbuf;
1147 if (pops->puffs_node_fallocate == NULL) {
1148 error = EOPNOTSUPP;
1149 break;
1152 error = pops->puffs_node_fallocate(pu,
1153 opcookie, auxt->pvnr_off, auxt->pvnr_len);
1154 break;
1157 case PUFFS_VN_FDISCARD:
1159 struct puffs_vnmsg_fdiscard *auxt = auxbuf;
1161 if (pops->puffs_node_fdiscard == NULL) {
1162 error = EOPNOTSUPP;
1163 break;
1166 error = pops->puffs_node_fdiscard(pu,
1167 opcookie, auxt->pvnr_off, auxt->pvnr_len);
1168 break;
1171 default:
1172 printf("inval op %d\n", preq->preq_optype);
1173 error = EINVAL;
1174 break;
1177 #if 0
1178 /* not issued by kernel currently */
1179 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_CACHE) {
1180 struct puffs_cacheinfo *pci = (void *)preq;
1182 if (pu->pu_ops.puffs_cache_write) {
1183 pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie,
1184 pci->pcache_nruns, pci->pcache_runs);
1186 error = 0;
1187 #endif
1189 } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_ERROR) {
1190 struct puffs_error *perr = (void *)preq;
1192 pu->pu_errnotify(pu, preq->preq_optype,
1193 perr->perr_error, perr->perr_str, preq->preq_cookie);
1194 error = 0;
1195 } else {
1197 * I guess the kernel sees this one coming also
1199 error = EINVAL;
1202 out:
1203 preq->preq_rv = error;
1205 if (pu->pu_oppost)
1206 pu->pu_oppost(pu);
1208 pcc->pcc_flags |= PCC_DONE;