1 /* $NetBSD: dispatcher.c,v 1.46 2013/11/06 19:56:38 christos Exp $ */
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
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
32 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: dispatcher.c,v 1.46 2013/11/06 19:56:38 christos Exp $");
37 #include <sys/types.h>
44 #endif /* !defined(__minix) */
46 #include <puffsdump.h>
51 #include "puffs_priv.h"
53 #define PUFFS_USE_FS_TTL(pu) (pu->pu_flags & PUFFS_KFLAG_CACHE_FS_TTL)
55 static void dispatch(struct puffs_cc
*);
57 /* for our eyes only */
59 puffs__ml_dispatch(struct puffs_usermount
*pu
, struct puffs_framebuf
*pb
)
61 struct puffs_cc
*pcc
= puffs_cc_getcc(pu
);
62 struct puffs_req
*preq
;
65 pcc
->pcc_flags
|= PCC_MLCONT
;
68 /* Put result to kernel sendqueue if necessary */
69 preq
= puffs__framebuf_getdataptr(pcc
->pcc_pb
);
70 if (PUFFSOP_WANTREPLY(preq
->preq_opclass
)) {
71 if (pu
->pu_flags
& PUFFS_FLAG_OPDUMP
)
74 puffs_framev_enqueue_justsend(pu
, pu
->pu_fd
,
77 puffs_framebuf_destroy(pcc
->pcc_pb
);
80 /* who needs information when you're living on borrowed time? */
81 if (pcc
->pcc_flags
& PCC_BORROWED
) {
82 puffs_cc_yield(pcc
); /* back to borrow source */
87 /* public, but not really tested and only semi-supported */
89 puffs_dispatch_create(struct puffs_usermount
*pu
, struct puffs_framebuf
*pb
,
90 struct puffs_cc
**pccp
)
94 if (puffs__cc_create(pu
, dispatch
, &pcc
) == -1)
104 puffs_dispatch_exec(struct puffs_cc
*pcc
, struct puffs_framebuf
**pbp
)
108 puffs_cc_continue(pcc
);
110 if (pcc
->pcc_flags
& PCC_DONE
) {
114 puffs__cc_destroy(pcc
, 0);
123 dispatch(struct puffs_cc
*pcc
)
125 struct puffs_usermount
*pu
= pcc
->pcc_pu
;
126 struct puffs_ops
*pops
= &pu
->pu_ops
;
127 struct puffs_req
*preq
= puffs__framebuf_getdataptr(pcc
->pcc_pb
);
128 void *auxbuf
; /* help with typecasting */
129 puffs_cookie_t opcookie
;
130 int error
= 0, buildpath
, pncookie
;
132 /* XXX: smaller hammer, please */
133 if ((PUFFSOP_OPCLASS(preq
->preq_opclass
== PUFFSOP_VFS
&&
134 preq
->preq_optype
== PUFFS_VFS_VPTOFH
)) ||
135 (PUFFSOP_OPCLASS(preq
->preq_opclass
) == PUFFSOP_VN
&&
136 (preq
->preq_optype
== PUFFS_VN_READDIR
137 || preq
->preq_optype
== PUFFS_VN_READ
))) {
138 if (puffs_framebuf_reserve_space(pcc
->pcc_pb
,
139 PUFFS_MSG_MAXSIZE
) == -1)
141 preq
= puffs__framebuf_getdataptr(pcc
->pcc_pb
);
145 opcookie
= preq
->preq_cookie
;
147 assert((pcc
->pcc_flags
& PCC_DONE
) == 0);
149 buildpath
= pu
->pu_flags
& PUFFS_FLAG_BUILDPATH
;
150 pncookie
= pu
->pu_flags
& PUFFS_FLAG_PNCOOKIE
;
151 assert(!buildpath
|| pncookie
);
153 preq
->preq_setbacks
= 0;
155 if (pu
->pu_flags
& PUFFS_FLAG_OPDUMP
)
158 puffs__cc_setcaller(pcc
, preq
->preq_pid
, preq
->preq_lid
);
167 /* Execute actual operation */
168 if (PUFFSOP_OPCLASS(preq
->preq_opclass
) == PUFFSOP_VFS
) {
169 switch (preq
->preq_optype
) {
170 case PUFFS_VFS_UNMOUNT
:
172 struct puffs_vfsmsg_unmount
*auxt
= auxbuf
;
174 PU_SETSTATE(pu
, PUFFS_STATE_UNMOUNTING
);
175 error
= pops
->puffs_fs_unmount(pu
, auxt
->pvfsr_flags
);
177 PU_SETSTATE(pu
, PUFFS_STATE_UNMOUNTED
);
179 PU_SETSTATE(pu
, PUFFS_STATE_RUNNING
);
183 case PUFFS_VFS_STATVFS
:
185 struct puffs_vfsmsg_statvfs
*auxt
= auxbuf
;
187 error
= pops
->puffs_fs_statvfs(pu
, &auxt
->pvfsr_sb
);
193 struct puffs_vfsmsg_sync
*auxt
= auxbuf
;
194 PUFFS_MAKECRED(pcr
, &auxt
->pvfsr_cred
);
196 error
= pops
->puffs_fs_sync(pu
,
197 auxt
->pvfsr_waitfor
, pcr
);
201 case PUFFS_VFS_FHTOVP
:
203 struct puffs_vfsmsg_fhtonode
*auxt
= auxbuf
;
204 struct puffs_newinfo pni
;
206 pni
.pni_cookie
= &auxt
->pvfsr_fhcookie
;
207 pni
.pni_vtype
= &auxt
->pvfsr_vtype
;
208 pni
.pni_size
= &auxt
->pvfsr_size
;
209 pni
.pni_rdev
= &auxt
->pvfsr_rdev
;
211 pni
.pni_va_ttl
= NULL
;
212 pni
.pni_cn_ttl
= NULL
;
214 error
= pops
->puffs_fs_fhtonode(pu
, auxt
->pvfsr_data
,
215 auxt
->pvfsr_dsize
, &pni
);
220 case PUFFS_VFS_VPTOFH
:
222 struct puffs_vfsmsg_nodetofh
*auxt
= auxbuf
;
224 error
= pops
->puffs_fs_nodetofh(pu
,
225 auxt
->pvfsr_fhcookie
, auxt
->pvfsr_data
,
231 case PUFFS_VFS_EXTATTRCTL
:
233 struct puffs_vfsmsg_extattrctl
*auxt
= auxbuf
;
234 const char *attrname
;
237 if (pops
->puffs_fs_extattrctl
== NULL
) {
242 if (auxt
->pvfsr_flags
& PUFFS_EXTATTRCTL_HASATTRNAME
)
243 attrname
= auxt
->pvfsr_attrname
;
247 flags
= auxt
->pvfsr_flags
& PUFFS_EXTATTRCTL_HASNODE
;
248 error
= pops
->puffs_fs_extattrctl(pu
, auxt
->pvfsr_cmd
,
250 auxt
->pvfsr_attrnamespace
, attrname
);
256 * I guess the kernel sees this one coming
262 /* XXX: audit return values */
263 /* XXX: sync with kernel */
264 } else if (PUFFSOP_OPCLASS(preq
->preq_opclass
) == PUFFSOP_VN
) {
265 switch (preq
->preq_optype
) {
266 case PUFFS_VN_LOOKUP
:
268 struct puffs_vnmsg_lookup
*auxt
= auxbuf
;
269 struct puffs_newinfo pni
;
271 struct puffs_node
*pn
= NULL
;
273 pcn
.pcn_pkcnp
= &auxt
->pvnr_cn
;
274 PUFFS_KCREDTOCRED(pcn
.pcn_cred
, &auxt
->pvnr_cn_cred
);
275 pni
.pni_cookie
= &auxt
->pvnr_newnode
;
276 pni
.pni_vtype
= &auxt
->pvnr_vtype
;
277 pni
.pni_size
= &auxt
->pvnr_size
;
278 pni
.pni_rdev
= &auxt
->pvnr_rdev
;
279 pni
.pni_va
= &auxt
->pvnr_va
;
280 pni
.pni_va_ttl
= &auxt
->pvnr_va_ttl
;
281 pni
.pni_cn_ttl
= &auxt
->pvnr_cn_ttl
;
284 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
289 /* lookup *must* be present */
290 error
= pops
->puffs_node_lookup(pu
, opcookie
,
295 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
298 * did we get a new node or a
301 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
302 if (pn
->pn_po
.po_path
== NULL
)
303 pn
->pn_po
= pcn
.pcn_po_full
;
310 if (pncookie
&& !error
) {
312 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
318 case PUFFS_VN_CREATE
:
320 struct puffs_vnmsg_create
*auxt
= auxbuf
;
321 struct puffs_newinfo pni
;
323 struct puffs_node
*pn
= NULL
;
325 if (pops
->puffs_node_create
== NULL
) {
330 pcn
.pcn_pkcnp
= &auxt
->pvnr_cn
;
331 PUFFS_KCREDTOCRED(pcn
.pcn_cred
, &auxt
->pvnr_cn_cred
);
333 memset(&pni
, 0, sizeof(pni
));
334 pni
.pni_cookie
= &auxt
->pvnr_newnode
;
335 pni
.pni_va
= &auxt
->pvnr_va
;
336 pni
.pni_va_ttl
= &auxt
->pvnr_va_ttl
;
337 pni
.pni_cn_ttl
= &auxt
->pvnr_cn_ttl
;
340 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
345 error
= pops
->puffs_node_create(pu
,
346 opcookie
, &pni
, &pcn
, &auxt
->pvnr_va
);
350 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
352 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
353 pn
->pn_po
= pcn
.pcn_po_full
;
357 if (pncookie
&& !error
) {
359 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
367 struct puffs_vnmsg_mknod
*auxt
= auxbuf
;
368 struct puffs_newinfo pni
;
370 struct puffs_node
*pn
= NULL
;
372 if (pops
->puffs_node_mknod
== NULL
) {
377 pcn
.pcn_pkcnp
= &auxt
->pvnr_cn
;
378 PUFFS_KCREDTOCRED(pcn
.pcn_cred
, &auxt
->pvnr_cn_cred
);
380 memset(&pni
, 0, sizeof(pni
));
381 pni
.pni_cookie
= &auxt
->pvnr_newnode
;
382 pni
.pni_va
= &auxt
->pvnr_va
;
383 pni
.pni_va_ttl
= &auxt
->pvnr_va_ttl
;
384 pni
.pni_cn_ttl
= &auxt
->pvnr_cn_ttl
;
387 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
392 error
= pops
->puffs_node_mknod(pu
,
393 opcookie
, &pni
, &pcn
, &auxt
->pvnr_va
);
397 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
399 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
400 pn
->pn_po
= pcn
.pcn_po_full
;
404 if (pncookie
&& !error
) {
406 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
414 struct puffs_vnmsg_open
*auxt
= auxbuf
;
415 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
417 if (pops
->puffs_node_open
== NULL
) {
422 error
= pops
->puffs_node_open(pu
,
423 opcookie
, auxt
->pvnr_mode
, pcr
);
429 struct puffs_vnmsg_close
*auxt
= auxbuf
;
430 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
432 if (pops
->puffs_node_close
== NULL
) {
437 error
= pops
->puffs_node_close(pu
,
438 opcookie
, auxt
->pvnr_fflag
, pcr
);
442 case PUFFS_VN_ACCESS
:
444 struct puffs_vnmsg_access
*auxt
= auxbuf
;
445 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
447 if (pops
->puffs_node_access
== NULL
) {
452 error
= pops
->puffs_node_access(pu
,
453 opcookie
, auxt
->pvnr_mode
, pcr
);
457 case PUFFS_VN_GETATTR
:
459 struct puffs_vnmsg_getattr
*auxt
= auxbuf
;
460 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
462 if (PUFFS_USE_FS_TTL(pu
)) {
463 if (pops
->puffs_node_getattr_ttl
== NULL
) {
468 error
= pops
->puffs_node_getattr_ttl(pu
,
469 opcookie
, &auxt
->pvnr_va
, pcr
,
472 if (pops
->puffs_node_getattr
== NULL
) {
477 error
= pops
->puffs_node_getattr(pu
,
478 opcookie
, &auxt
->pvnr_va
, pcr
);
483 case PUFFS_VN_SETATTR
:
485 struct puffs_vnmsg_setattr
*auxt
= auxbuf
;
486 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
488 if (PUFFS_USE_FS_TTL(pu
)) {
491 if (pops
->puffs_node_setattr_ttl
== NULL
) {
496 if (!PUFFSOP_WANTREPLY(preq
->preq_opclass
))
497 xflag
|= PUFFS_SETATTR_FAF
;
499 error
= pops
->puffs_node_setattr_ttl(pu
,
500 opcookie
, &auxt
->pvnr_va
, pcr
,
501 &auxt
->pvnr_va_ttl
, xflag
);
503 if (pops
->puffs_node_setattr
== NULL
) {
508 error
= pops
->puffs_node_setattr(pu
,
509 opcookie
, &auxt
->pvnr_va
, pcr
);
516 struct puffs_vnmsg_mmap
*auxt
= auxbuf
;
517 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
519 if (pops
->puffs_node_mmap
== NULL
) {
524 error
= pops
->puffs_node_mmap(pu
,
525 opcookie
, auxt
->pvnr_prot
, pcr
);
531 struct puffs_vnmsg_fsync
*auxt
= auxbuf
;
532 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
534 if (pops
->puffs_node_fsync
== NULL
) {
539 error
= pops
->puffs_node_fsync(pu
, opcookie
, pcr
,
540 auxt
->pvnr_flags
, auxt
->pvnr_offlo
,
547 struct puffs_vnmsg_seek
*auxt
= auxbuf
;
548 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
550 if (pops
->puffs_node_seek
== NULL
) {
555 error
= pops
->puffs_node_seek(pu
,
556 opcookie
, auxt
->pvnr_oldoff
,
557 auxt
->pvnr_newoff
, pcr
);
561 case PUFFS_VN_REMOVE
:
563 struct puffs_vnmsg_remove
*auxt
= auxbuf
;
565 if (pops
->puffs_node_remove
== NULL
) {
570 pcn
.pcn_pkcnp
= &auxt
->pvnr_cn
;
571 PUFFS_KCREDTOCRED(pcn
.pcn_cred
, &auxt
->pvnr_cn_cred
);
573 error
= pops
->puffs_node_remove(pu
,
574 opcookie
, auxt
->pvnr_cookie_targ
, &pcn
);
580 struct puffs_vnmsg_link
*auxt
= auxbuf
;
582 if (pops
->puffs_node_link
== NULL
) {
587 pcn
.pcn_pkcnp
= &auxt
->pvnr_cn
;
588 PUFFS_KCREDTOCRED(pcn
.pcn_cred
, &auxt
->pvnr_cn_cred
);
591 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
596 error
= pops
->puffs_node_link(pu
,
597 opcookie
, auxt
->pvnr_cookie_targ
, &pcn
);
599 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
604 case PUFFS_VN_RENAME
:
606 struct puffs_vnmsg_rename
*auxt
= auxbuf
;
607 struct puffs_cn pcn_src
, pcn_targ
;
608 struct puffs_node
*pn_src
;
610 if (pops
->puffs_node_rename
== NULL
) {
615 pcn_src
.pcn_pkcnp
= &auxt
->pvnr_cn_src
;
616 PUFFS_KCREDTOCRED(pcn_src
.pcn_cred
,
617 &auxt
->pvnr_cn_src_cred
);
619 pcn_targ
.pcn_pkcnp
= &auxt
->pvnr_cn_targ
;
620 PUFFS_KCREDTOCRED(pcn_targ
.pcn_cred
,
621 &auxt
->pvnr_cn_targ_cred
);
624 pn_src
= auxt
->pvnr_cookie_src
;
625 pcn_src
.pcn_po_full
= pn_src
->pn_po
;
627 error
= puffs_path_pcnbuild(pu
, &pcn_targ
,
628 auxt
->pvnr_cookie_targdir
);
633 error
= pops
->puffs_node_rename(pu
,
634 opcookie
, auxt
->pvnr_cookie_src
,
635 &pcn_src
, auxt
->pvnr_cookie_targdir
,
636 auxt
->pvnr_cookie_targ
, &pcn_targ
);
641 &pcn_targ
.pcn_po_full
);
643 struct puffs_pathinfo pi
;
644 struct puffs_pathobj po_old
;
646 /* handle this node */
647 po_old
= pn_src
->pn_po
;
648 pn_src
->pn_po
= pcn_targ
.pcn_po_full
;
650 if (pn_src
->pn_va
.va_type
!= VDIR
) {
651 pu
->pu_pathfree(pu
, &po_old
);
655 /* handle all child nodes for DIRs */
656 pi
.pi_old
= &pcn_src
.pcn_po_full
;
657 pi
.pi_new
= &pcn_targ
.pcn_po_full
;
660 if (puffs_pn_nodewalk(pu
,
661 puffs_path_prefixadj
, &pi
) != NULL
)
664 pu
->pu_pathfree(pu
, &po_old
);
672 struct puffs_vnmsg_mkdir
*auxt
= auxbuf
;
673 struct puffs_newinfo pni
;
675 struct puffs_node
*pn
= NULL
;
677 if (pops
->puffs_node_mkdir
== NULL
) {
682 pcn
.pcn_pkcnp
= &auxt
->pvnr_cn
;
683 PUFFS_KCREDTOCRED(pcn
.pcn_cred
, &auxt
->pvnr_cn_cred
);
685 memset(&pni
, 0, sizeof(pni
));
686 pni
.pni_cookie
= &auxt
->pvnr_newnode
;
687 pni
.pni_va
= &auxt
->pvnr_va
;
688 pni
.pni_va_ttl
= &auxt
->pvnr_va_ttl
;
689 pni
.pni_cn_ttl
= &auxt
->pvnr_cn_ttl
;
692 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
697 error
= pops
->puffs_node_mkdir(pu
,
698 opcookie
, &pni
, &pcn
, &auxt
->pvnr_va
);
702 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
704 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
705 pn
->pn_po
= pcn
.pcn_po_full
;
709 if (pncookie
&& !error
) {
711 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
719 struct puffs_vnmsg_rmdir
*auxt
= auxbuf
;
721 if (pops
->puffs_node_rmdir
== NULL
) {
726 pcn
.pcn_pkcnp
= &auxt
->pvnr_cn
;
727 PUFFS_KCREDTOCRED(pcn
.pcn_cred
, &auxt
->pvnr_cn_cred
);
729 error
= pops
->puffs_node_rmdir(pu
,
730 opcookie
, auxt
->pvnr_cookie_targ
, &pcn
);
734 case PUFFS_VN_SYMLINK
:
736 struct puffs_vnmsg_symlink
*auxt
= auxbuf
;
737 struct puffs_newinfo pni
;
739 struct puffs_node
*pn
= NULL
;
741 if (pops
->puffs_node_symlink
== NULL
) {
746 pcn
.pcn_pkcnp
= &auxt
->pvnr_cn
;
747 PUFFS_KCREDTOCRED(pcn
.pcn_cred
, &auxt
->pvnr_cn_cred
);
749 memset(&pni
, 0, sizeof(pni
));
750 pni
.pni_cookie
= &auxt
->pvnr_newnode
;
751 pni
.pni_va
= &auxt
->pvnr_va
;
752 pni
.pni_va_ttl
= &auxt
->pvnr_va_ttl
;
753 pni
.pni_cn_ttl
= &auxt
->pvnr_cn_ttl
;
756 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
761 error
= pops
->puffs_node_symlink(pu
,
762 opcookie
, &pni
, &pcn
,
763 &auxt
->pvnr_va
, auxt
->pvnr_link
);
767 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
769 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
770 pn
->pn_po
= pcn
.pcn_po_full
;
774 if (pncookie
&& !error
) {
776 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
782 case PUFFS_VN_READDIR
:
784 struct puffs_vnmsg_readdir
*auxt
= auxbuf
;
785 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
788 size_t res
, origcookies
;
790 if (pops
->puffs_node_readdir
== NULL
) {
795 if (auxt
->pvnr_ncookies
) {
796 /* LINTED: pvnr_data is __aligned() */
797 cookies
= (off_t
*)auxt
->pvnr_data
;
798 origcookies
= auxt
->pvnr_ncookies
;
803 /* LINTED: dentoff is aligned in the kernel */
804 dent
= (struct dirent
*)
805 (auxt
->pvnr_data
+ auxt
->pvnr_dentoff
);
807 res
= auxt
->pvnr_resid
;
808 error
= pops
->puffs_node_readdir(pu
,
809 opcookie
, dent
, &auxt
->pvnr_offset
,
810 &auxt
->pvnr_resid
, pcr
, &auxt
->pvnr_eofflag
,
811 cookies
, &auxt
->pvnr_ncookies
);
813 /* much easier to track non-working NFS */
814 assert(auxt
->pvnr_ncookies
<= origcookies
);
816 /* need to move a bit more */
817 preq
->preq_buflen
= sizeof(struct puffs_vnmsg_readdir
)
818 + auxt
->pvnr_dentoff
+ (res
- auxt
->pvnr_resid
);
822 case PUFFS_VN_READLINK
:
824 struct puffs_vnmsg_readlink
*auxt
= auxbuf
;
825 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
827 if (pops
->puffs_node_readlink
== NULL
) {
833 error
= pops
->puffs_node_readlink(pu
, opcookie
, pcr
,
834 auxt
->pvnr_link
, &auxt
->pvnr_linklen
);
838 case PUFFS_VN_RECLAIM
:
840 struct puffs_vnmsg_reclaim
*auxt
= auxbuf
;
841 struct puffs_node
*pn
;
843 if (pops
->puffs_node_reclaim2
!= NULL
) {
844 error
= pops
->puffs_node_reclaim2(pu
, opcookie
,
849 if (pops
->puffs_node_reclaim
== NULL
) {
855 * This fixes a race condition,
856 * where a node in reclaimed by kernel
857 * after a lookup request is sent,
858 * but before the reply, leaving the kernel
859 * with a invalid vnode/cookie reference.
862 pn
= PU_CMAP(pu
, opcookie
);
863 pn
->pn_nlookup
-= auxt
->pvnr_nlookup
;
864 if (pn
->pn_nlookup
>= 1) {
870 error
= pops
->puffs_node_reclaim(pu
, opcookie
);
874 case PUFFS_VN_INACTIVE
:
877 if (pops
->puffs_node_inactive
== NULL
) {
882 error
= pops
->puffs_node_inactive(pu
, opcookie
);
886 case PUFFS_VN_PATHCONF
:
888 struct puffs_vnmsg_pathconf
*auxt
= auxbuf
;
889 if (pops
->puffs_node_pathconf
== NULL
) {
894 error
= pops
->puffs_node_pathconf(pu
,
895 opcookie
, auxt
->pvnr_name
,
900 case PUFFS_VN_ADVLOCK
:
902 struct puffs_vnmsg_advlock
*auxt
= auxbuf
;
903 if (pops
->puffs_node_advlock
== NULL
) {
908 error
= pops
->puffs_node_advlock(pu
,
909 opcookie
, auxt
->pvnr_id
, auxt
->pvnr_op
,
910 &auxt
->pvnr_fl
, auxt
->pvnr_flags
);
916 if (pops
->puffs_node_print
== NULL
) {
921 error
= pops
->puffs_node_print(pu
,
926 case PUFFS_VN_ABORTOP
:
928 struct puffs_vnmsg_abortop
*auxt
= auxbuf
;
931 if (pops
->puffs_node_abortop
== NULL
) {
936 pcn
.pcn_pkcnp
= &auxt
->pvnr_cn
;
937 PUFFS_KCREDTOCRED(pcn
.pcn_cred
, &auxt
->pvnr_cn_cred
);
939 error
= pops
->puffs_node_abortop(pu
, opcookie
, &pcn
);
946 struct puffs_vnmsg_read
*auxt
= auxbuf
;
947 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
950 if (pops
->puffs_node_read
== NULL
) {
955 res
= auxt
->pvnr_resid
;
956 error
= pops
->puffs_node_read(pu
,
957 opcookie
, auxt
->pvnr_data
,
958 auxt
->pvnr_offset
, &auxt
->pvnr_resid
,
959 pcr
, auxt
->pvnr_ioflag
);
961 /* need to move a bit more */
962 preq
->preq_buflen
= sizeof(struct puffs_vnmsg_read
)
963 + (res
- auxt
->pvnr_resid
);
969 struct puffs_vnmsg_write
*auxt
= auxbuf
;
970 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
972 if (pops
->puffs_node_write2
!= NULL
) {
975 if (!PUFFSOP_WANTREPLY(preq
->preq_opclass
))
976 xflag
|= PUFFS_SETATTR_FAF
;
978 error
= pops
->puffs_node_write2(pu
,
979 opcookie
, auxt
->pvnr_data
,
980 auxt
->pvnr_offset
, &auxt
->pvnr_resid
,
981 pcr
, auxt
->pvnr_ioflag
, xflag
);
983 } else if (pops
->puffs_node_write
!= NULL
) {
984 error
= pops
->puffs_node_write(pu
,
985 opcookie
, auxt
->pvnr_data
,
986 auxt
->pvnr_offset
, &auxt
->pvnr_resid
,
987 pcr
, auxt
->pvnr_ioflag
);
994 /* don't need to move data back to the kernel */
995 preq
->preq_buflen
= sizeof(struct puffs_vnmsg_write
);
1001 struct puffs_vnmsg_poll
*auxt
= auxbuf
;
1003 if (pops
->puffs_node_poll
== NULL
) {
1006 /* emulate genfs_poll() */
1007 auxt
->pvnr_events
&= (POLLIN
| POLLOUT
1008 | POLLRDNORM
| POLLWRNORM
);
1013 error
= pops
->puffs_node_poll(pu
,
1014 opcookie
, &auxt
->pvnr_events
);
1018 case PUFFS_VN_GETEXTATTR
:
1020 struct puffs_vnmsg_getextattr
*auxt
= auxbuf
;
1021 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
1022 size_t res
, *resp
, *sizep
;
1025 if (pops
->puffs_node_getextattr
== NULL
) {
1030 if (auxt
->pvnr_datasize
)
1031 sizep
= &auxt
->pvnr_datasize
;
1035 res
= auxt
->pvnr_resid
;
1037 data
= auxt
->pvnr_data
;
1038 resp
= &auxt
->pvnr_resid
;
1044 error
= pops
->puffs_node_getextattr(pu
,
1045 opcookie
, auxt
->pvnr_attrnamespace
,
1046 auxt
->pvnr_attrname
, sizep
, data
, resp
, pcr
);
1048 /* need to move a bit more? */
1050 sizeof(struct puffs_vnmsg_getextattr
)
1051 + (res
- auxt
->pvnr_resid
);
1055 case PUFFS_VN_SETEXTATTR
:
1057 struct puffs_vnmsg_setextattr
*auxt
= auxbuf
;
1058 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
1062 if (pops
->puffs_node_setextattr
== NULL
) {
1067 if (auxt
->pvnr_resid
> 0) {
1068 data
= auxt
->pvnr_data
;
1069 resp
= &auxt
->pvnr_resid
;
1075 error
= pops
->puffs_node_setextattr(pu
,
1076 opcookie
, auxt
->pvnr_attrnamespace
,
1077 auxt
->pvnr_attrname
, data
, resp
, pcr
);
1081 case PUFFS_VN_LISTEXTATTR
:
1083 struct puffs_vnmsg_listextattr
*auxt
= auxbuf
;
1084 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
1085 size_t res
, *resp
, *sizep
;
1089 if (pops
->puffs_node_listextattr
== NULL
) {
1094 if (auxt
->pvnr_datasize
)
1095 sizep
= &auxt
->pvnr_datasize
;
1099 res
= auxt
->pvnr_resid
;
1101 data
= auxt
->pvnr_data
;
1102 resp
= &auxt
->pvnr_resid
;
1108 res
= auxt
->pvnr_resid
;
1109 flag
= auxt
->pvnr_flag
;
1110 error
= pops
->puffs_node_listextattr(pu
,
1111 opcookie
, auxt
->pvnr_attrnamespace
,
1112 sizep
, data
, resp
, flag
, pcr
);
1114 /* need to move a bit more? */
1116 sizeof(struct puffs_vnmsg_listextattr
)
1117 + (res
- auxt
->pvnr_resid
);
1121 case PUFFS_VN_DELETEEXTATTR
:
1123 struct puffs_vnmsg_deleteextattr
*auxt
= auxbuf
;
1124 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
1126 if (pops
->puffs_node_deleteextattr
== NULL
) {
1131 error
= pops
->puffs_node_deleteextattr(pu
,
1132 opcookie
, auxt
->pvnr_attrnamespace
,
1133 auxt
->pvnr_attrname
, pcr
);
1138 printf("inval op %d\n", preq
->preq_optype
);
1144 /* not issued by kernel currently */
1145 } else if (PUFFSOP_OPCLASS(preq
->preq_opclass
) == PUFFSOP_CACHE
) {
1146 struct puffs_cacheinfo
*pci
= (void *)preq
;
1148 if (pu
->pu_ops
.puffs_cache_write
) {
1149 pu
->pu_ops
.puffs_cache_write(pu
, preq
->preq_cookie
,
1150 pci
->pcache_nruns
, pci
->pcache_runs
);
1155 } else if (PUFFSOP_OPCLASS(preq
->preq_opclass
) == PUFFSOP_ERROR
) {
1156 struct puffs_error
*perr
= (void *)preq
;
1158 pu
->pu_errnotify(pu
, preq
->preq_optype
,
1159 perr
->perr_error
, perr
->perr_str
, preq
->preq_cookie
);
1163 * I guess the kernel sees this one coming also
1169 preq
->preq_rv
= error
;
1174 pcc
->pcc_flags
|= PCC_DONE
;