1 /* $NetBSD: dispatcher.c,v 1.48 2014/10/31 13:56:04 manu 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.48 2014/10/31 13:56:04 manu Exp $");
37 #include <sys/types.h>
44 #include <puffsdump.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 */
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
;
63 pcc
->pcc_flags
|= PCC_MLCONT
;
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
)
72 puffs_framev_enqueue_justsend(pu
, pu
->pu_fd
,
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 */
85 /* public, but not really tested and only semi-supported */
87 puffs_dispatch_create(struct puffs_usermount
*pu
, struct puffs_framebuf
*pb
,
88 struct puffs_cc
**pccp
)
92 if (puffs__cc_create(pu
, dispatch
, &pcc
) == -1)
102 puffs_dispatch_exec(struct puffs_cc
*pcc
, struct puffs_framebuf
**pbp
)
106 puffs_cc_continue(pcc
);
108 if (pcc
->pcc_flags
& PCC_DONE
) {
112 puffs__cc_destroy(pcc
, 0);
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)
139 preq
= puffs__framebuf_getdataptr(pcc
->pcc_pb
);
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
)
156 puffs__cc_setcaller(pcc
, preq
->preq_pid
, preq
->preq_lid
);
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
);
175 PU_SETSTATE(pu
, PUFFS_STATE_UNMOUNTED
);
177 PU_SETSTATE(pu
, PUFFS_STATE_RUNNING
);
181 case PUFFS_VFS_STATVFS
:
183 struct puffs_vfsmsg_statvfs
*auxt
= auxbuf
;
185 error
= pops
->puffs_fs_statvfs(pu
, &auxt
->pvfsr_sb
);
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
);
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
;
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
);
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
,
229 case PUFFS_VFS_EXTATTRCTL
:
231 struct puffs_vfsmsg_extattrctl
*auxt
= auxbuf
;
232 const char *attrname
;
235 if (pops
->puffs_fs_extattrctl
== NULL
) {
240 if (auxt
->pvfsr_flags
& PUFFS_EXTATTRCTL_HASATTRNAME
)
241 attrname
= auxt
->pvfsr_attrname
;
245 flags
= auxt
->pvfsr_flags
& PUFFS_EXTATTRCTL_HASNODE
;
246 error
= pops
->puffs_fs_extattrctl(pu
, auxt
->pvfsr_cmd
,
248 auxt
->pvfsr_attrnamespace
, attrname
);
254 * I guess the kernel sees this one coming
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
;
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
;
282 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
287 /* lookup *must* be present */
288 error
= pops
->puffs_node_lookup(pu
, opcookie
,
293 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
296 * did we get a new node or a
299 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
300 if (pn
->pn_po
.po_path
== NULL
)
301 pn
->pn_po
= pcn
.pcn_po_full
;
308 if (pncookie
&& !error
) {
310 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
316 case PUFFS_VN_CREATE
:
318 struct puffs_vnmsg_create
*auxt
= auxbuf
;
319 struct puffs_newinfo pni
;
321 struct puffs_node
*pn
= NULL
;
323 if (pops
->puffs_node_create
== NULL
) {
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
;
338 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
343 error
= pops
->puffs_node_create(pu
,
344 opcookie
, &pni
, &pcn
, &auxt
->pvnr_va
);
348 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
350 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
351 pn
->pn_po
= pcn
.pcn_po_full
;
355 if (pncookie
&& !error
) {
357 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
365 struct puffs_vnmsg_mknod
*auxt
= auxbuf
;
366 struct puffs_newinfo pni
;
368 struct puffs_node
*pn
= NULL
;
370 if (pops
->puffs_node_mknod
== NULL
) {
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
;
385 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
390 error
= pops
->puffs_node_mknod(pu
,
391 opcookie
, &pni
, &pcn
, &auxt
->pvnr_va
);
395 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
397 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
398 pn
->pn_po
= pcn
.pcn_po_full
;
402 if (pncookie
&& !error
) {
404 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
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
,
423 if (pops
->puffs_node_open
== NULL
) {
428 error
= pops
->puffs_node_open(pu
,
429 opcookie
, auxt
->pvnr_mode
, pcr
);
435 struct puffs_vnmsg_close
*auxt
= auxbuf
;
436 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
438 if (pops
->puffs_node_close
== NULL
) {
443 error
= pops
->puffs_node_close(pu
,
444 opcookie
, auxt
->pvnr_fflag
, pcr
);
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
) {
458 error
= pops
->puffs_node_access(pu
,
459 opcookie
, auxt
->pvnr_mode
, pcr
);
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
) {
474 error
= pops
->puffs_node_getattr_ttl(pu
,
475 opcookie
, &auxt
->pvnr_va
, pcr
,
478 if (pops
->puffs_node_getattr
== NULL
) {
483 error
= pops
->puffs_node_getattr(pu
,
484 opcookie
, &auxt
->pvnr_va
, pcr
);
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
)) {
497 if (pops
->puffs_node_setattr_ttl
== NULL
) {
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
);
509 if (pops
->puffs_node_setattr
== NULL
) {
514 error
= pops
->puffs_node_setattr(pu
,
515 opcookie
, &auxt
->pvnr_va
, pcr
);
522 struct puffs_vnmsg_mmap
*auxt
= auxbuf
;
523 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
525 if (pops
->puffs_node_mmap
== NULL
) {
530 error
= pops
->puffs_node_mmap(pu
,
531 opcookie
, auxt
->pvnr_prot
, pcr
);
537 struct puffs_vnmsg_fsync
*auxt
= auxbuf
;
538 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
540 if (pops
->puffs_node_fsync
== NULL
) {
545 error
= pops
->puffs_node_fsync(pu
, opcookie
, pcr
,
546 auxt
->pvnr_flags
, auxt
->pvnr_offlo
,
553 struct puffs_vnmsg_seek
*auxt
= auxbuf
;
554 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
556 if (pops
->puffs_node_seek
== NULL
) {
561 error
= pops
->puffs_node_seek(pu
,
562 opcookie
, auxt
->pvnr_oldoff
,
563 auxt
->pvnr_newoff
, pcr
);
567 case PUFFS_VN_REMOVE
:
569 struct puffs_vnmsg_remove
*auxt
= auxbuf
;
571 if (pops
->puffs_node_remove
== NULL
) {
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
);
586 struct puffs_vnmsg_link
*auxt
= auxbuf
;
588 if (pops
->puffs_node_link
== NULL
) {
593 pcn
.pcn_pkcnp
= &auxt
->pvnr_cn
;
594 PUFFS_KCREDTOCRED(pcn
.pcn_cred
, &auxt
->pvnr_cn_cred
);
597 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
602 error
= pops
->puffs_node_link(pu
,
603 opcookie
, auxt
->pvnr_cookie_targ
, &pcn
);
605 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
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
) {
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
);
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
);
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
);
647 &pcn_targ
.pcn_po_full
);
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
);
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
;
666 if (puffs_pn_nodewalk(pu
,
667 puffs_path_prefixadj
, &pi
) != NULL
)
670 pu
->pu_pathfree(pu
, &po_old
);
678 struct puffs_vnmsg_mkdir
*auxt
= auxbuf
;
679 struct puffs_newinfo pni
;
681 struct puffs_node
*pn
= NULL
;
683 if (pops
->puffs_node_mkdir
== NULL
) {
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
;
698 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
703 error
= pops
->puffs_node_mkdir(pu
,
704 opcookie
, &pni
, &pcn
, &auxt
->pvnr_va
);
708 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
710 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
711 pn
->pn_po
= pcn
.pcn_po_full
;
715 if (pncookie
&& !error
) {
717 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
725 struct puffs_vnmsg_rmdir
*auxt
= auxbuf
;
727 if (pops
->puffs_node_rmdir
== NULL
) {
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
);
740 case PUFFS_VN_SYMLINK
:
742 struct puffs_vnmsg_symlink
*auxt
= auxbuf
;
743 struct puffs_newinfo pni
;
745 struct puffs_node
*pn
= NULL
;
747 if (pops
->puffs_node_symlink
== NULL
) {
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
;
762 error
= puffs_path_pcnbuild(pu
, &pcn
, opcookie
);
767 error
= pops
->puffs_node_symlink(pu
,
768 opcookie
, &pni
, &pcn
,
769 &auxt
->pvnr_va
, auxt
->pvnr_link
);
773 pu
->pu_pathfree(pu
, &pcn
.pcn_po_full
);
775 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
776 pn
->pn_po
= pcn
.pcn_po_full
;
780 if (pncookie
&& !error
) {
782 pn
= PU_CMAP(pu
, auxt
->pvnr_newnode
);
788 case PUFFS_VN_READDIR
:
790 struct puffs_vnmsg_readdir
*auxt
= auxbuf
;
791 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
794 size_t res
, origcookies
;
796 if (pops
->puffs_node_readdir
== NULL
) {
801 if (auxt
->pvnr_ncookies
) {
802 /* LINTED: pvnr_data is __aligned() */
803 cookies
= (off_t
*)auxt
->pvnr_data
;
804 origcookies
= auxt
->pvnr_ncookies
;
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
);
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
) {
839 error
= pops
->puffs_node_readlink(pu
, opcookie
, pcr
,
840 auxt
->pvnr_link
, &auxt
->pvnr_linklen
);
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
,
855 if (pops
->puffs_node_reclaim
== NULL
) {
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.
868 pn
= PU_CMAP(pu
, opcookie
);
869 pn
->pn_nlookup
-= auxt
->pvnr_nlookup
;
870 if (pn
->pn_nlookup
>= 1) {
876 error
= pops
->puffs_node_reclaim(pu
, opcookie
);
880 case PUFFS_VN_INACTIVE
:
883 if (pops
->puffs_node_inactive
== NULL
) {
888 error
= pops
->puffs_node_inactive(pu
, opcookie
);
892 case PUFFS_VN_PATHCONF
:
894 struct puffs_vnmsg_pathconf
*auxt
= auxbuf
;
895 if (pops
->puffs_node_pathconf
== NULL
) {
900 error
= pops
->puffs_node_pathconf(pu
,
901 opcookie
, auxt
->pvnr_name
,
906 case PUFFS_VN_ADVLOCK
:
908 struct puffs_vnmsg_advlock
*auxt
= auxbuf
;
909 if (pops
->puffs_node_advlock
== NULL
) {
914 error
= pops
->puffs_node_advlock(pu
,
915 opcookie
, auxt
->pvnr_id
, auxt
->pvnr_op
,
916 &auxt
->pvnr_fl
, auxt
->pvnr_flags
);
922 if (pops
->puffs_node_print
== NULL
) {
927 error
= pops
->puffs_node_print(pu
,
932 case PUFFS_VN_ABORTOP
:
934 struct puffs_vnmsg_abortop
*auxt
= auxbuf
;
937 if (pops
->puffs_node_abortop
== NULL
) {
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
);
952 struct puffs_vnmsg_read
*auxt
= auxbuf
;
953 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
956 if (pops
->puffs_node_read
== NULL
) {
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
);
975 struct puffs_vnmsg_write
*auxt
= auxbuf
;
976 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
978 if (pops
->puffs_node_write2
!= NULL
) {
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
);
1000 /* don't need to move data back to the kernel */
1001 preq
->preq_buflen
= sizeof(struct puffs_vnmsg_write
);
1007 struct puffs_vnmsg_poll
*auxt
= auxbuf
;
1009 if (pops
->puffs_node_poll
== NULL
) {
1012 /* emulate genfs_poll() */
1013 auxt
->pvnr_events
&= (POLLIN
| POLLOUT
1014 | POLLRDNORM
| POLLWRNORM
);
1019 error
= pops
->puffs_node_poll(pu
,
1020 opcookie
, &auxt
->pvnr_events
);
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
;
1031 if (pops
->puffs_node_getextattr
== NULL
) {
1036 if (auxt
->pvnr_datasize
)
1037 sizep
= &auxt
->pvnr_datasize
;
1041 res
= auxt
->pvnr_resid
;
1043 data
= auxt
->pvnr_data
;
1044 resp
= &auxt
->pvnr_resid
;
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? */
1056 sizeof(struct puffs_vnmsg_getextattr
)
1057 + (res
- auxt
->pvnr_resid
);
1061 case PUFFS_VN_SETEXTATTR
:
1063 struct puffs_vnmsg_setextattr
*auxt
= auxbuf
;
1064 PUFFS_MAKECRED(pcr
, &auxt
->pvnr_cred
);
1068 if (pops
->puffs_node_setextattr
== NULL
) {
1073 if (auxt
->pvnr_resid
> 0) {
1074 data
= auxt
->pvnr_data
;
1075 resp
= &auxt
->pvnr_resid
;
1081 error
= pops
->puffs_node_setextattr(pu
,
1082 opcookie
, auxt
->pvnr_attrnamespace
,
1083 auxt
->pvnr_attrname
, data
, resp
, pcr
);
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
;
1095 if (pops
->puffs_node_listextattr
== NULL
) {
1100 if (auxt
->pvnr_datasize
)
1101 sizep
= &auxt
->pvnr_datasize
;
1105 res
= auxt
->pvnr_resid
;
1107 data
= auxt
->pvnr_data
;
1108 resp
= &auxt
->pvnr_resid
;
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? */
1122 sizeof(struct puffs_vnmsg_listextattr
)
1123 + (res
- auxt
->pvnr_resid
);
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
) {
1137 error
= pops
->puffs_node_deleteextattr(pu
,
1138 opcookie
, auxt
->pvnr_attrnamespace
,
1139 auxt
->pvnr_attrname
, pcr
);
1143 case PUFFS_VN_FALLOCATE
:
1145 struct puffs_vnmsg_fallocate
*auxt
= auxbuf
;
1147 if (pops
->puffs_node_fallocate
== NULL
) {
1152 error
= pops
->puffs_node_fallocate(pu
,
1153 opcookie
, auxt
->pvnr_off
, auxt
->pvnr_len
);
1157 case PUFFS_VN_FDISCARD
:
1159 struct puffs_vnmsg_fdiscard
*auxt
= auxbuf
;
1161 if (pops
->puffs_node_fdiscard
== NULL
) {
1166 error
= pops
->puffs_node_fdiscard(pu
,
1167 opcookie
, auxt
->pvnr_off
, auxt
->pvnr_len
);
1172 printf("inval op %d\n", preq
->preq_optype
);
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
);
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
);
1197 * I guess the kernel sees this one coming also
1203 preq
->preq_rv
= error
;
1208 pcc
->pcc_flags
|= PCC_DONE
;