1*2d9177bfSmlelstv /* $NetBSD: dispatcher.c,v 1.50 2023/12/11 12:42:18 mlelstv Exp $ */
2e9cad0ceSpooka
3e9cad0ceSpooka /*
4d1d05d65Spooka * Copyright (c) 2006, 2007, 2008 Antti Kantee. All Rights Reserved.
5e9cad0ceSpooka *
6e9cad0ceSpooka * Development of this software was supported by the
7d1d05d65Spooka * Ulla Tuominen Foundation, the Finnish Cultural Foundation and
8d1d05d65Spooka * Research Foundation of Helsinki University of Technology.
9e9cad0ceSpooka *
10e9cad0ceSpooka * Redistribution and use in source and binary forms, with or without
11e9cad0ceSpooka * modification, are permitted provided that the following conditions
12e9cad0ceSpooka * are met:
13e9cad0ceSpooka * 1. Redistributions of source code must retain the above copyright
14e9cad0ceSpooka * notice, this list of conditions and the following disclaimer.
15e9cad0ceSpooka * 2. Redistributions in binary form must reproduce the above copyright
16e9cad0ceSpooka * notice, this list of conditions and the following disclaimer in the
17e9cad0ceSpooka * documentation and/or other materials provided with the distribution.
18e9cad0ceSpooka *
19e9cad0ceSpooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20e9cad0ceSpooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21e9cad0ceSpooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22e9cad0ceSpooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23e9cad0ceSpooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24e9cad0ceSpooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25e9cad0ceSpooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26e9cad0ceSpooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27e9cad0ceSpooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28e9cad0ceSpooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29e9cad0ceSpooka * SUCH DAMAGE.
30e9cad0ceSpooka */
31e9cad0ceSpooka
32e9cad0ceSpooka #include <sys/cdefs.h>
33e9cad0ceSpooka #if !defined(lint)
34*2d9177bfSmlelstv __RCSID("$NetBSD: dispatcher.c,v 1.50 2023/12/11 12:42:18 mlelstv Exp $");
35e9cad0ceSpooka #endif /* !lint */
36e9cad0ceSpooka
37e9cad0ceSpooka #include <sys/types.h>
3875bb6c40Spooka #include <sys/poll.h>
39e9cad0ceSpooka
40e9cad0ceSpooka #include <assert.h>
41e9cad0ceSpooka #include <errno.h>
42edb40ac9Spooka #include <pthread.h>
43e9cad0ceSpooka #include <puffs.h>
44e9cad0ceSpooka #include <puffsdump.h>
45e9cad0ceSpooka #include <stdio.h>
46e9cad0ceSpooka #include <stdlib.h>
47e9cad0ceSpooka #include <unistd.h>
48e9cad0ceSpooka
49e9cad0ceSpooka #include "puffs_priv.h"
50e9cad0ceSpooka
51fb4eb353Smanu #define PUFFS_USE_FS_TTL(pu) (pu->pu_flags & PUFFS_KFLAG_CACHE_FS_TTL)
52fb4eb353Smanu
53d1d05d65Spooka static void dispatch(struct puffs_cc *);
54d1d05d65Spooka
55d1d05d65Spooka /* for our eyes only */
56d1d05d65Spooka void
puffs__ml_dispatch(struct puffs_usermount * pu,struct puffs_framebuf * pb)57d1d05d65Spooka puffs__ml_dispatch(struct puffs_usermount *pu, struct puffs_framebuf *pb)
58d1d05d65Spooka {
59d1d05d65Spooka struct puffs_cc *pcc = puffs_cc_getcc(pu);
60d1d05d65Spooka struct puffs_req *preq;
61d1d05d65Spooka
62d1d05d65Spooka pcc->pcc_pb = pb;
63d1d05d65Spooka pcc->pcc_flags |= PCC_MLCONT;
64d1d05d65Spooka dispatch(pcc);
65d1d05d65Spooka
66d1d05d65Spooka /* Put result to kernel sendqueue if necessary */
67d1d05d65Spooka preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
68d1d05d65Spooka if (PUFFSOP_WANTREPLY(preq->preq_opclass)) {
69d1d05d65Spooka if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
70d1d05d65Spooka puffsdump_rv(preq);
71d1d05d65Spooka
72d1d05d65Spooka puffs_framev_enqueue_justsend(pu, pu->pu_fd,
73d1d05d65Spooka pcc->pcc_pb, 0, 0);
74edb40ac9Spooka } else {
75d1d05d65Spooka puffs_framebuf_destroy(pcc->pcc_pb);
76edb40ac9Spooka }
77edb40ac9Spooka
78d1d05d65Spooka /* who needs information when you're living on borrowed time? */
79d1d05d65Spooka if (pcc->pcc_flags & PCC_BORROWED) {
80d1d05d65Spooka puffs_cc_yield(pcc); /* back to borrow source */
81d1d05d65Spooka }
82d1d05d65Spooka pcc->pcc_flags = 0;
83d1d05d65Spooka }
84edb40ac9Spooka
85d1d05d65Spooka /* public, but not really tested and only semi-supported */
86d1d05d65Spooka int
puffs_dispatch_create(struct puffs_usermount * pu,struct puffs_framebuf * pb,struct puffs_cc ** pccp)87d1d05d65Spooka puffs_dispatch_create(struct puffs_usermount *pu, struct puffs_framebuf *pb,
88d1d05d65Spooka struct puffs_cc **pccp)
89d1d05d65Spooka {
90d1d05d65Spooka struct puffs_cc *pcc;
91edb40ac9Spooka
92d1d05d65Spooka if (puffs__cc_create(pu, dispatch, &pcc) == -1)
93d1d05d65Spooka return -1;
94d1d05d65Spooka
95d1d05d65Spooka pcc->pcc_pb = pb;
96d1d05d65Spooka *pccp = pcc;
97d1d05d65Spooka
98d1d05d65Spooka return 0;
99d1d05d65Spooka }
100d1d05d65Spooka
101d1d05d65Spooka int
puffs_dispatch_exec(struct puffs_cc * pcc,struct puffs_framebuf ** pbp)102d1d05d65Spooka puffs_dispatch_exec(struct puffs_cc *pcc, struct puffs_framebuf **pbp)
103d1d05d65Spooka {
104edb40ac9Spooka int rv;
105edb40ac9Spooka
106d1d05d65Spooka puffs_cc_continue(pcc);
107edb40ac9Spooka
108d1d05d65Spooka if (pcc->pcc_flags & PCC_DONE) {
109d1d05d65Spooka rv = 1;
110d1d05d65Spooka *pbp = pcc->pcc_pb;
111d1d05d65Spooka pcc->pcc_flags = 0;
112d1d05d65Spooka puffs__cc_destroy(pcc, 0);
113d1d05d65Spooka } else {
114d1d05d65Spooka rv = 0;
115d1d05d65Spooka }
116edb40ac9Spooka
117edb40ac9Spooka return rv;
118edb40ac9Spooka }
119edb40ac9Spooka
120d1d05d65Spooka static void
dispatch(struct puffs_cc * pcc)121d1d05d65Spooka dispatch(struct puffs_cc *pcc)
122e9cad0ceSpooka {
123e9cad0ceSpooka struct puffs_usermount *pu = pcc->pcc_pu;
124e9cad0ceSpooka struct puffs_ops *pops = &pu->pu_ops;
12561113f40Spooka struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
12673bad8cbSpooka void *auxbuf; /* help with typecasting */
127ff423327Spooka puffs_cookie_t opcookie;
128d256e384Smanu int error = 0, buildpath, pncookie;
12973bad8cbSpooka
13073bad8cbSpooka /* XXX: smaller hammer, please */
13173bad8cbSpooka if ((PUFFSOP_OPCLASS(preq->preq_opclass == PUFFSOP_VFS &&
13273bad8cbSpooka preq->preq_optype == PUFFS_VFS_VPTOFH)) ||
13373bad8cbSpooka (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN &&
13473bad8cbSpooka (preq->preq_optype == PUFFS_VN_READDIR
13573bad8cbSpooka || preq->preq_optype == PUFFS_VN_READ))) {
13673bad8cbSpooka if (puffs_framebuf_reserve_space(pcc->pcc_pb,
13773bad8cbSpooka PUFFS_MSG_MAXSIZE) == -1)
13873bad8cbSpooka error = errno;
13973bad8cbSpooka preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
14073bad8cbSpooka }
14173bad8cbSpooka
14273bad8cbSpooka auxbuf = preq;
14373bad8cbSpooka opcookie = preq->preq_cookie;
144e9cad0ceSpooka
145d1d05d65Spooka assert((pcc->pcc_flags & PCC_DONE) == 0);
146e9cad0ceSpooka
147e9cad0ceSpooka buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH;
148d256e384Smanu pncookie = pu->pu_flags & PUFFS_FLAG_PNCOOKIE;
149d256e384Smanu assert(!buildpath || pncookie);
150d256e384Smanu
151e9cad0ceSpooka preq->preq_setbacks = 0;
152e9cad0ceSpooka
153d1d05d65Spooka if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
154d1d05d65Spooka puffsdump_req(preq);
155d1d05d65Spooka
156d1d05d65Spooka puffs__cc_setcaller(pcc, preq->preq_pid, preq->preq_lid);
157d1d05d65Spooka
158d1d05d65Spooka /* pre-operation */
159b40b63f0Spooka if (pu->pu_oppre)
16021913eabSpooka pu->pu_oppre(pu);
161b40b63f0Spooka
16273bad8cbSpooka if (error)
16373bad8cbSpooka goto out;
16473bad8cbSpooka
165d1d05d65Spooka /* Execute actual operation */
166e9cad0ceSpooka if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
167e24596a7Schristos switch ((enum puffs_vfs)preq->preq_optype) {
168e9cad0ceSpooka case PUFFS_VFS_UNMOUNT:
169e9cad0ceSpooka {
17033c91738Spooka struct puffs_vfsmsg_unmount *auxt = auxbuf;
171e9cad0ceSpooka
172e9cad0ceSpooka PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTING);
17321913eabSpooka error = pops->puffs_fs_unmount(pu, auxt->pvfsr_flags);
174e9cad0ceSpooka if (!error)
175e9cad0ceSpooka PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED);
176e9cad0ceSpooka else
177e9cad0ceSpooka PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
178e9cad0ceSpooka break;
179e9cad0ceSpooka }
180e9cad0ceSpooka
181e9cad0ceSpooka case PUFFS_VFS_STATVFS:
182e9cad0ceSpooka {
18333c91738Spooka struct puffs_vfsmsg_statvfs *auxt = auxbuf;
184e9cad0ceSpooka
18521913eabSpooka error = pops->puffs_fs_statvfs(pu, &auxt->pvfsr_sb);
186e9cad0ceSpooka break;
187e9cad0ceSpooka }
188e9cad0ceSpooka
189e9cad0ceSpooka case PUFFS_VFS_SYNC:
190e9cad0ceSpooka {
19133c91738Spooka struct puffs_vfsmsg_sync *auxt = auxbuf;
192438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvfsr_cred);
193e9cad0ceSpooka
19421913eabSpooka error = pops->puffs_fs_sync(pu,
1956a3d9a18Spooka auxt->pvfsr_waitfor, pcr);
196e9cad0ceSpooka break;
197e9cad0ceSpooka }
198e9cad0ceSpooka
199e9cad0ceSpooka case PUFFS_VFS_FHTOVP:
200e9cad0ceSpooka {
20133c91738Spooka struct puffs_vfsmsg_fhtonode *auxt = auxbuf;
20280234546Spooka struct puffs_newinfo pni;
20380234546Spooka
20480234546Spooka pni.pni_cookie = &auxt->pvfsr_fhcookie;
20580234546Spooka pni.pni_vtype = &auxt->pvfsr_vtype;
20680234546Spooka pni.pni_size = &auxt->pvfsr_size;
20780234546Spooka pni.pni_rdev = &auxt->pvfsr_rdev;
20870d81924Smanu pni.pni_va = NULL;
20970d81924Smanu pni.pni_va_ttl = NULL;
21070d81924Smanu pni.pni_cn_ttl = NULL;
211e9cad0ceSpooka
21221913eabSpooka error = pops->puffs_fs_fhtonode(pu, auxt->pvfsr_data,
21380234546Spooka auxt->pvfsr_dsize, &pni);
214e9cad0ceSpooka
215e9cad0ceSpooka break;
216e9cad0ceSpooka }
217e9cad0ceSpooka
218e9cad0ceSpooka case PUFFS_VFS_VPTOFH:
219e9cad0ceSpooka {
22033c91738Spooka struct puffs_vfsmsg_nodetofh *auxt = auxbuf;
221e9cad0ceSpooka
22221913eabSpooka error = pops->puffs_fs_nodetofh(pu,
223e9cad0ceSpooka auxt->pvfsr_fhcookie, auxt->pvfsr_data,
224e9cad0ceSpooka &auxt->pvfsr_dsize);
225e9cad0ceSpooka
226e9cad0ceSpooka break;
227e9cad0ceSpooka }
228e9cad0ceSpooka
229c3be8a8cSpooka case PUFFS_VFS_EXTATTRCTL:
230e9cad0ceSpooka {
231c3be8a8cSpooka struct puffs_vfsmsg_extattrctl *auxt = auxbuf;
232c3be8a8cSpooka const char *attrname;
233c3be8a8cSpooka int flags;
234e9cad0ceSpooka
235c3be8a8cSpooka if (pops->puffs_fs_extattrctl == NULL) {
236c3be8a8cSpooka error = EOPNOTSUPP;
237e9cad0ceSpooka break;
238c3be8a8cSpooka }
239e9cad0ceSpooka
240c3be8a8cSpooka if (auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASATTRNAME)
241c3be8a8cSpooka attrname = auxt->pvfsr_attrname;
242c3be8a8cSpooka else
243c3be8a8cSpooka attrname = NULL;
244c3be8a8cSpooka
245c3be8a8cSpooka flags = auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASNODE;
246c3be8a8cSpooka error = pops->puffs_fs_extattrctl(pu, auxt->pvfsr_cmd,
247c3be8a8cSpooka opcookie, flags,
248c3be8a8cSpooka auxt->pvfsr_attrnamespace, attrname);
249e9cad0ceSpooka break;
250e9cad0ceSpooka }
251e9cad0ceSpooka
252e9cad0ceSpooka default:
253e9cad0ceSpooka /*
254e9cad0ceSpooka * I guess the kernel sees this one coming
255e9cad0ceSpooka */
256e9cad0ceSpooka error = EINVAL;
257e9cad0ceSpooka break;
258e9cad0ceSpooka }
259e9cad0ceSpooka
260e9cad0ceSpooka /* XXX: audit return values */
261e9cad0ceSpooka /* XXX: sync with kernel */
262e9cad0ceSpooka } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
263e24596a7Schristos switch ((enum puffs_vn)preq->preq_optype) {
264e9cad0ceSpooka case PUFFS_VN_LOOKUP:
265e9cad0ceSpooka {
26633c91738Spooka struct puffs_vnmsg_lookup *auxt = auxbuf;
26780234546Spooka struct puffs_newinfo pni;
268e9cad0ceSpooka struct puffs_cn pcn;
269fb4eb353Smanu struct puffs_node *pn = NULL;
270e9cad0ceSpooka
271e9cad0ceSpooka pcn.pcn_pkcnp = &auxt->pvnr_cn;
272438f52d2Spooka PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
27380234546Spooka pni.pni_cookie = &auxt->pvnr_newnode;
27480234546Spooka pni.pni_vtype = &auxt->pvnr_vtype;
27580234546Spooka pni.pni_size = &auxt->pvnr_size;
27680234546Spooka pni.pni_rdev = &auxt->pvnr_rdev;
27770d81924Smanu pni.pni_va = &auxt->pvnr_va;
27870d81924Smanu pni.pni_va_ttl = &auxt->pvnr_va_ttl;
27970d81924Smanu pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
280438f52d2Spooka
281e9cad0ceSpooka if (buildpath) {
282e9cad0ceSpooka error = puffs_path_pcnbuild(pu, &pcn, opcookie);
283e9cad0ceSpooka if (error)
284e9cad0ceSpooka break;
285e9cad0ceSpooka }
286e9cad0ceSpooka
287e9cad0ceSpooka /* lookup *must* be present */
28821913eabSpooka error = pops->puffs_node_lookup(pu, opcookie,
28980234546Spooka &pni, &pcn);
290e9cad0ceSpooka
291e9cad0ceSpooka if (buildpath) {
292e9cad0ceSpooka if (error) {
293e9cad0ceSpooka pu->pu_pathfree(pu, &pcn.pcn_po_full);
294e9cad0ceSpooka } else {
295e9cad0ceSpooka /*
296e9cad0ceSpooka * did we get a new node or a
297e9cad0ceSpooka * recycled node?
298e9cad0ceSpooka */
299e9cad0ceSpooka pn = PU_CMAP(pu, auxt->pvnr_newnode);
300e9cad0ceSpooka if (pn->pn_po.po_path == NULL)
301e9cad0ceSpooka pn->pn_po = pcn.pcn_po_full;
302e9cad0ceSpooka else
303e9cad0ceSpooka pu->pu_pathfree(pu,
304e9cad0ceSpooka &pcn.pcn_po_full);
305e9cad0ceSpooka }
306e9cad0ceSpooka }
3078502ba8eSmanu
308d256e384Smanu if (pncookie && !error) {
3098502ba8eSmanu if (pn == NULL)
3108502ba8eSmanu pn = PU_CMAP(pu, auxt->pvnr_newnode);
3118502ba8eSmanu pn->pn_nlookup++;
3128502ba8eSmanu }
313e9cad0ceSpooka break;
314e9cad0ceSpooka }
315e9cad0ceSpooka
316e9cad0ceSpooka case PUFFS_VN_CREATE:
317e9cad0ceSpooka {
31833c91738Spooka struct puffs_vnmsg_create *auxt = auxbuf;
31980234546Spooka struct puffs_newinfo pni;
320e9cad0ceSpooka struct puffs_cn pcn;
321244cd4a7Smanu struct puffs_node *pn = NULL;
32280234546Spooka
323e9cad0ceSpooka if (pops->puffs_node_create == NULL) {
324e9cad0ceSpooka error = 0;
325e9cad0ceSpooka break;
326e9cad0ceSpooka }
327e9cad0ceSpooka
328e9cad0ceSpooka pcn.pcn_pkcnp = &auxt->pvnr_cn;
329438f52d2Spooka PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
330438f52d2Spooka
33180234546Spooka memset(&pni, 0, sizeof(pni));
33280234546Spooka pni.pni_cookie = &auxt->pvnr_newnode;
33370d81924Smanu pni.pni_va = &auxt->pvnr_va;
33470d81924Smanu pni.pni_va_ttl = &auxt->pvnr_va_ttl;
33570d81924Smanu pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
33680234546Spooka
337e9cad0ceSpooka if (buildpath) {
338e9cad0ceSpooka error = puffs_path_pcnbuild(pu, &pcn, opcookie);
339e9cad0ceSpooka if (error)
340e9cad0ceSpooka break;
341e9cad0ceSpooka }
342e9cad0ceSpooka
34321913eabSpooka error = pops->puffs_node_create(pu,
34480234546Spooka opcookie, &pni, &pcn, &auxt->pvnr_va);
345e9cad0ceSpooka
346e9cad0ceSpooka if (buildpath) {
347e9cad0ceSpooka if (error) {
348e9cad0ceSpooka pu->pu_pathfree(pu, &pcn.pcn_po_full);
349e9cad0ceSpooka } else {
350e9cad0ceSpooka pn = PU_CMAP(pu, auxt->pvnr_newnode);
351e9cad0ceSpooka pn->pn_po = pcn.pcn_po_full;
352e9cad0ceSpooka }
353e9cad0ceSpooka }
354e9cad0ceSpooka
355d256e384Smanu if (pncookie && !error) {
356244cd4a7Smanu if (pn == NULL)
357244cd4a7Smanu pn = PU_CMAP(pu, auxt->pvnr_newnode);
358244cd4a7Smanu pn->pn_nlookup++;
359244cd4a7Smanu }
360e9cad0ceSpooka break;
361e9cad0ceSpooka }
362e9cad0ceSpooka
363e9cad0ceSpooka case PUFFS_VN_MKNOD:
364e9cad0ceSpooka {
36533c91738Spooka struct puffs_vnmsg_mknod *auxt = auxbuf;
36680234546Spooka struct puffs_newinfo pni;
367e9cad0ceSpooka struct puffs_cn pcn;
368244cd4a7Smanu struct puffs_node *pn = NULL;
36980234546Spooka
370e9cad0ceSpooka if (pops->puffs_node_mknod == NULL) {
371e9cad0ceSpooka error = 0;
372e9cad0ceSpooka break;
373e9cad0ceSpooka }
374e9cad0ceSpooka
375e9cad0ceSpooka pcn.pcn_pkcnp = &auxt->pvnr_cn;
376438f52d2Spooka PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
377438f52d2Spooka
37880234546Spooka memset(&pni, 0, sizeof(pni));
37980234546Spooka pni.pni_cookie = &auxt->pvnr_newnode;
38070d81924Smanu pni.pni_va = &auxt->pvnr_va;
38170d81924Smanu pni.pni_va_ttl = &auxt->pvnr_va_ttl;
38270d81924Smanu pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
38380234546Spooka
384e9cad0ceSpooka if (buildpath) {
385e9cad0ceSpooka error = puffs_path_pcnbuild(pu, &pcn, opcookie);
386e9cad0ceSpooka if (error)
387e9cad0ceSpooka break;
388e9cad0ceSpooka }
389e9cad0ceSpooka
39021913eabSpooka error = pops->puffs_node_mknod(pu,
39180234546Spooka opcookie, &pni, &pcn, &auxt->pvnr_va);
392e9cad0ceSpooka
393e9cad0ceSpooka if (buildpath) {
394e9cad0ceSpooka if (error) {
395e9cad0ceSpooka pu->pu_pathfree(pu, &pcn.pcn_po_full);
396e9cad0ceSpooka } else {
397e9cad0ceSpooka pn = PU_CMAP(pu, auxt->pvnr_newnode);
398e9cad0ceSpooka pn->pn_po = pcn.pcn_po_full;
399e9cad0ceSpooka }
400e9cad0ceSpooka }
401e9cad0ceSpooka
402d256e384Smanu if (pncookie && !error) {
403244cd4a7Smanu if (pn == NULL)
404244cd4a7Smanu pn = PU_CMAP(pu, auxt->pvnr_newnode);
405244cd4a7Smanu pn->pn_nlookup++;
406244cd4a7Smanu }
407e9cad0ceSpooka break;
408e9cad0ceSpooka }
409e9cad0ceSpooka
410e9cad0ceSpooka case PUFFS_VN_OPEN:
411e9cad0ceSpooka {
41233c91738Spooka struct puffs_vnmsg_open *auxt = auxbuf;
413438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
414438f52d2Spooka
415ccfb03f9Smanu if (pops->puffs_node_open2 != NULL) {
416ccfb03f9Smanu error = pops->puffs_node_open2(pu,
417ccfb03f9Smanu opcookie, auxt->pvnr_mode, pcr,
418ccfb03f9Smanu &auxt->pvnr_oflags);
419ccfb03f9Smanu
420ccfb03f9Smanu break;
421ccfb03f9Smanu }
422ccfb03f9Smanu
423e9cad0ceSpooka if (pops->puffs_node_open == NULL) {
424e9cad0ceSpooka error = 0;
425e9cad0ceSpooka break;
426e9cad0ceSpooka }
427e9cad0ceSpooka
42821913eabSpooka error = pops->puffs_node_open(pu,
4296a3d9a18Spooka opcookie, auxt->pvnr_mode, pcr);
430e9cad0ceSpooka break;
431e9cad0ceSpooka }
432e9cad0ceSpooka
433e9cad0ceSpooka case PUFFS_VN_CLOSE:
434e9cad0ceSpooka {
43533c91738Spooka struct puffs_vnmsg_close *auxt = auxbuf;
436438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
437438f52d2Spooka
438e9cad0ceSpooka if (pops->puffs_node_close == NULL) {
439e9cad0ceSpooka error = 0;
440e9cad0ceSpooka break;
441e9cad0ceSpooka }
442e9cad0ceSpooka
44321913eabSpooka error = pops->puffs_node_close(pu,
4446a3d9a18Spooka opcookie, auxt->pvnr_fflag, pcr);
445e9cad0ceSpooka break;
446e9cad0ceSpooka }
447e9cad0ceSpooka
448e9cad0ceSpooka case PUFFS_VN_ACCESS:
449e9cad0ceSpooka {
45033c91738Spooka struct puffs_vnmsg_access *auxt = auxbuf;
451438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
452438f52d2Spooka
453e9cad0ceSpooka if (pops->puffs_node_access == NULL) {
454e9cad0ceSpooka error = 0;
455e9cad0ceSpooka break;
456e9cad0ceSpooka }
457e9cad0ceSpooka
45821913eabSpooka error = pops->puffs_node_access(pu,
4596a3d9a18Spooka opcookie, auxt->pvnr_mode, pcr);
460e9cad0ceSpooka break;
461e9cad0ceSpooka }
462e9cad0ceSpooka
463e9cad0ceSpooka case PUFFS_VN_GETATTR:
464e9cad0ceSpooka {
46533c91738Spooka struct puffs_vnmsg_getattr *auxt = auxbuf;
466438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
467438f52d2Spooka
46870d81924Smanu if (PUFFS_USE_FS_TTL(pu)) {
46970d81924Smanu if (pops->puffs_node_getattr_ttl == NULL) {
47070d81924Smanu error = EOPNOTSUPP;
47170d81924Smanu break;
47270d81924Smanu }
47370d81924Smanu
47470d81924Smanu error = pops->puffs_node_getattr_ttl(pu,
47570d81924Smanu opcookie, &auxt->pvnr_va, pcr,
47670d81924Smanu &auxt->pvnr_va_ttl);
47770d81924Smanu } else {
478e9cad0ceSpooka if (pops->puffs_node_getattr == NULL) {
479e9cad0ceSpooka error = EOPNOTSUPP;
480e9cad0ceSpooka break;
481e9cad0ceSpooka }
482e9cad0ceSpooka
48321913eabSpooka error = pops->puffs_node_getattr(pu,
4846a3d9a18Spooka opcookie, &auxt->pvnr_va, pcr);
485fb4eb353Smanu }
486e9cad0ceSpooka break;
487e9cad0ceSpooka }
488e9cad0ceSpooka
489e9cad0ceSpooka case PUFFS_VN_SETATTR:
490e9cad0ceSpooka {
49133c91738Spooka struct puffs_vnmsg_setattr *auxt = auxbuf;
492438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
493438f52d2Spooka
49470d81924Smanu if (PUFFS_USE_FS_TTL(pu)) {
495d1056538Smanu int xflag = 0;
496d1056538Smanu
49770d81924Smanu if (pops->puffs_node_setattr_ttl == NULL) {
49870d81924Smanu error = EOPNOTSUPP;
49970d81924Smanu break;
50070d81924Smanu }
50170d81924Smanu
502d1056538Smanu if (!PUFFSOP_WANTREPLY(preq->preq_opclass))
503d1056538Smanu xflag |= PUFFS_SETATTR_FAF;
504d1056538Smanu
50570d81924Smanu error = pops->puffs_node_setattr_ttl(pu,
50670d81924Smanu opcookie, &auxt->pvnr_va, pcr,
507d1056538Smanu &auxt->pvnr_va_ttl, xflag);
50870d81924Smanu } else {
509e9cad0ceSpooka if (pops->puffs_node_setattr == NULL) {
510e9cad0ceSpooka error = EOPNOTSUPP;
511e9cad0ceSpooka break;
512e9cad0ceSpooka }
513e9cad0ceSpooka
51421913eabSpooka error = pops->puffs_node_setattr(pu,
5156a3d9a18Spooka opcookie, &auxt->pvnr_va, pcr);
51670d81924Smanu }
517e9cad0ceSpooka break;
518e9cad0ceSpooka }
519e9cad0ceSpooka
520e9cad0ceSpooka case PUFFS_VN_MMAP:
521e9cad0ceSpooka {
52233c91738Spooka struct puffs_vnmsg_mmap *auxt = auxbuf;
523438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
524438f52d2Spooka
525e9cad0ceSpooka if (pops->puffs_node_mmap == NULL) {
526e9cad0ceSpooka error = 0;
527e9cad0ceSpooka break;
528e9cad0ceSpooka }
529e9cad0ceSpooka
53021913eabSpooka error = pops->puffs_node_mmap(pu,
5316a3d9a18Spooka opcookie, auxt->pvnr_prot, pcr);
532e9cad0ceSpooka break;
533e9cad0ceSpooka }
534e9cad0ceSpooka
535e9cad0ceSpooka case PUFFS_VN_FSYNC:
536e9cad0ceSpooka {
53733c91738Spooka struct puffs_vnmsg_fsync *auxt = auxbuf;
538438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
539438f52d2Spooka
540e9cad0ceSpooka if (pops->puffs_node_fsync == NULL) {
541e9cad0ceSpooka error = 0;
542e9cad0ceSpooka break;
543e9cad0ceSpooka }
544e9cad0ceSpooka
54521913eabSpooka error = pops->puffs_node_fsync(pu, opcookie, pcr,
546e9cad0ceSpooka auxt->pvnr_flags, auxt->pvnr_offlo,
5476a3d9a18Spooka auxt->pvnr_offhi);
548e9cad0ceSpooka break;
549e9cad0ceSpooka }
550e9cad0ceSpooka
551e9cad0ceSpooka case PUFFS_VN_SEEK:
552e9cad0ceSpooka {
55333c91738Spooka struct puffs_vnmsg_seek *auxt = auxbuf;
554438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
555438f52d2Spooka
556e9cad0ceSpooka if (pops->puffs_node_seek == NULL) {
557e9cad0ceSpooka error = 0;
558e9cad0ceSpooka break;
559e9cad0ceSpooka }
560e9cad0ceSpooka
56121913eabSpooka error = pops->puffs_node_seek(pu,
562e9cad0ceSpooka opcookie, auxt->pvnr_oldoff,
563438f52d2Spooka auxt->pvnr_newoff, pcr);
564e9cad0ceSpooka break;
565e9cad0ceSpooka }
566e9cad0ceSpooka
567e9cad0ceSpooka case PUFFS_VN_REMOVE:
568e9cad0ceSpooka {
56933c91738Spooka struct puffs_vnmsg_remove *auxt = auxbuf;
570e9cad0ceSpooka struct puffs_cn pcn;
571e9cad0ceSpooka if (pops->puffs_node_remove == NULL) {
572e9cad0ceSpooka error = 0;
573e9cad0ceSpooka break;
574e9cad0ceSpooka }
575e9cad0ceSpooka
576e9cad0ceSpooka pcn.pcn_pkcnp = &auxt->pvnr_cn;
577438f52d2Spooka PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
578e9cad0ceSpooka
57921913eabSpooka error = pops->puffs_node_remove(pu,
580e9cad0ceSpooka opcookie, auxt->pvnr_cookie_targ, &pcn);
581e9cad0ceSpooka break;
582e9cad0ceSpooka }
583e9cad0ceSpooka
584e9cad0ceSpooka case PUFFS_VN_LINK:
585e9cad0ceSpooka {
58633c91738Spooka struct puffs_vnmsg_link *auxt = auxbuf;
587e9cad0ceSpooka struct puffs_cn pcn;
588e9cad0ceSpooka if (pops->puffs_node_link == NULL) {
589e9cad0ceSpooka error = 0;
590e9cad0ceSpooka break;
591e9cad0ceSpooka }
592e9cad0ceSpooka
593e9cad0ceSpooka pcn.pcn_pkcnp = &auxt->pvnr_cn;
594438f52d2Spooka PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
595438f52d2Spooka
596e9cad0ceSpooka if (buildpath) {
597e9cad0ceSpooka error = puffs_path_pcnbuild(pu, &pcn, opcookie);
598e9cad0ceSpooka if (error)
599e9cad0ceSpooka break;
600e9cad0ceSpooka }
601e9cad0ceSpooka
60221913eabSpooka error = pops->puffs_node_link(pu,
603e9cad0ceSpooka opcookie, auxt->pvnr_cookie_targ, &pcn);
604e9cad0ceSpooka if (buildpath)
605e9cad0ceSpooka pu->pu_pathfree(pu, &pcn.pcn_po_full);
606e9cad0ceSpooka
607e9cad0ceSpooka break;
608e9cad0ceSpooka }
609e9cad0ceSpooka
610e9cad0ceSpooka case PUFFS_VN_RENAME:
611e9cad0ceSpooka {
61233c91738Spooka struct puffs_vnmsg_rename *auxt = auxbuf;
613e9cad0ceSpooka struct puffs_cn pcn_src, pcn_targ;
614e9cad0ceSpooka struct puffs_node *pn_src;
615e9cad0ceSpooka
616e9cad0ceSpooka if (pops->puffs_node_rename == NULL) {
617e9cad0ceSpooka error = 0;
618e9cad0ceSpooka break;
619e9cad0ceSpooka }
620e9cad0ceSpooka
621e9cad0ceSpooka pcn_src.pcn_pkcnp = &auxt->pvnr_cn_src;
622438f52d2Spooka PUFFS_KCREDTOCRED(pcn_src.pcn_cred,
623438f52d2Spooka &auxt->pvnr_cn_src_cred);
624ffe0a014Spooka
625e9cad0ceSpooka pcn_targ.pcn_pkcnp = &auxt->pvnr_cn_targ;
626438f52d2Spooka PUFFS_KCREDTOCRED(pcn_targ.pcn_cred,
627438f52d2Spooka &auxt->pvnr_cn_targ_cred);
628438f52d2Spooka
629e9cad0ceSpooka if (buildpath) {
630e9cad0ceSpooka pn_src = auxt->pvnr_cookie_src;
631e9cad0ceSpooka pcn_src.pcn_po_full = pn_src->pn_po;
632e9cad0ceSpooka
633e9cad0ceSpooka error = puffs_path_pcnbuild(pu, &pcn_targ,
634e9cad0ceSpooka auxt->pvnr_cookie_targdir);
635e9cad0ceSpooka if (error)
636e9cad0ceSpooka break;
63727c90c0eSchristos }
638e9cad0ceSpooka
63921913eabSpooka error = pops->puffs_node_rename(pu,
640e9cad0ceSpooka opcookie, auxt->pvnr_cookie_src,
641e9cad0ceSpooka &pcn_src, auxt->pvnr_cookie_targdir,
642e9cad0ceSpooka auxt->pvnr_cookie_targ, &pcn_targ);
643e9cad0ceSpooka
644e9cad0ceSpooka if (buildpath) {
645e9cad0ceSpooka if (error) {
646e9cad0ceSpooka pu->pu_pathfree(pu,
647e9cad0ceSpooka &pcn_targ.pcn_po_full);
648e9cad0ceSpooka } else {
649e9cad0ceSpooka struct puffs_pathinfo pi;
650e9cad0ceSpooka struct puffs_pathobj po_old;
651e9cad0ceSpooka
652e9cad0ceSpooka /* handle this node */
653e9cad0ceSpooka po_old = pn_src->pn_po;
654e9cad0ceSpooka pn_src->pn_po = pcn_targ.pcn_po_full;
655e9cad0ceSpooka
656e9cad0ceSpooka if (pn_src->pn_va.va_type != VDIR) {
657e9cad0ceSpooka pu->pu_pathfree(pu, &po_old);
658e9cad0ceSpooka break;
659e9cad0ceSpooka }
660e9cad0ceSpooka
661e9cad0ceSpooka /* handle all child nodes for DIRs */
662e9cad0ceSpooka pi.pi_old = &pcn_src.pcn_po_full;
663e9cad0ceSpooka pi.pi_new = &pcn_targ.pcn_po_full;
664e9cad0ceSpooka
66540ffc8b9Spooka PU_LOCK();
666e9cad0ceSpooka if (puffs_pn_nodewalk(pu,
667e9cad0ceSpooka puffs_path_prefixadj, &pi) != NULL)
668e9cad0ceSpooka error = ENOMEM;
66940ffc8b9Spooka PU_UNLOCK();
670e9cad0ceSpooka pu->pu_pathfree(pu, &po_old);
671e9cad0ceSpooka }
672e9cad0ceSpooka }
673e9cad0ceSpooka break;
674e9cad0ceSpooka }
675e9cad0ceSpooka
676e9cad0ceSpooka case PUFFS_VN_MKDIR:
677e9cad0ceSpooka {
67833c91738Spooka struct puffs_vnmsg_mkdir *auxt = auxbuf;
67980234546Spooka struct puffs_newinfo pni;
680e9cad0ceSpooka struct puffs_cn pcn;
681244cd4a7Smanu struct puffs_node *pn = NULL;
68280234546Spooka
683e9cad0ceSpooka if (pops->puffs_node_mkdir == NULL) {
684e9cad0ceSpooka error = 0;
685e9cad0ceSpooka break;
686e9cad0ceSpooka }
687e9cad0ceSpooka
688e9cad0ceSpooka pcn.pcn_pkcnp = &auxt->pvnr_cn;
689438f52d2Spooka PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
690438f52d2Spooka
69180234546Spooka memset(&pni, 0, sizeof(pni));
69280234546Spooka pni.pni_cookie = &auxt->pvnr_newnode;
69370d81924Smanu pni.pni_va = &auxt->pvnr_va;
69470d81924Smanu pni.pni_va_ttl = &auxt->pvnr_va_ttl;
69570d81924Smanu pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
69680234546Spooka
697e9cad0ceSpooka if (buildpath) {
698e9cad0ceSpooka error = puffs_path_pcnbuild(pu, &pcn, opcookie);
699e9cad0ceSpooka if (error)
700e9cad0ceSpooka break;
701e9cad0ceSpooka }
702e9cad0ceSpooka
70321913eabSpooka error = pops->puffs_node_mkdir(pu,
70480234546Spooka opcookie, &pni, &pcn, &auxt->pvnr_va);
705e9cad0ceSpooka
706e9cad0ceSpooka if (buildpath) {
707e9cad0ceSpooka if (error) {
708e9cad0ceSpooka pu->pu_pathfree(pu, &pcn.pcn_po_full);
709e9cad0ceSpooka } else {
710e9cad0ceSpooka pn = PU_CMAP(pu, auxt->pvnr_newnode);
711e9cad0ceSpooka pn->pn_po = pcn.pcn_po_full;
712e9cad0ceSpooka }
713e9cad0ceSpooka }
714e9cad0ceSpooka
715d256e384Smanu if (pncookie && !error) {
716244cd4a7Smanu if (pn == NULL)
717244cd4a7Smanu pn = PU_CMAP(pu, auxt->pvnr_newnode);
718244cd4a7Smanu pn->pn_nlookup++;
719244cd4a7Smanu }
720e9cad0ceSpooka break;
721e9cad0ceSpooka }
722e9cad0ceSpooka
723e9cad0ceSpooka case PUFFS_VN_RMDIR:
724e9cad0ceSpooka {
72533c91738Spooka struct puffs_vnmsg_rmdir *auxt = auxbuf;
726e9cad0ceSpooka struct puffs_cn pcn;
727e9cad0ceSpooka if (pops->puffs_node_rmdir == NULL) {
728e9cad0ceSpooka error = 0;
729e9cad0ceSpooka break;
730e9cad0ceSpooka }
731e9cad0ceSpooka
732e9cad0ceSpooka pcn.pcn_pkcnp = &auxt->pvnr_cn;
733438f52d2Spooka PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
734e9cad0ceSpooka
73521913eabSpooka error = pops->puffs_node_rmdir(pu,
736e9cad0ceSpooka opcookie, auxt->pvnr_cookie_targ, &pcn);
737e9cad0ceSpooka break;
738e9cad0ceSpooka }
739e9cad0ceSpooka
740e9cad0ceSpooka case PUFFS_VN_SYMLINK:
741e9cad0ceSpooka {
74233c91738Spooka struct puffs_vnmsg_symlink *auxt = auxbuf;
74380234546Spooka struct puffs_newinfo pni;
744e9cad0ceSpooka struct puffs_cn pcn;
745244cd4a7Smanu struct puffs_node *pn = NULL;
74680234546Spooka
747e9cad0ceSpooka if (pops->puffs_node_symlink == NULL) {
748e9cad0ceSpooka error = 0;
749e9cad0ceSpooka break;
750e9cad0ceSpooka }
751e9cad0ceSpooka
752e9cad0ceSpooka pcn.pcn_pkcnp = &auxt->pvnr_cn;
753438f52d2Spooka PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
754438f52d2Spooka
75580234546Spooka memset(&pni, 0, sizeof(pni));
75680234546Spooka pni.pni_cookie = &auxt->pvnr_newnode;
75770d81924Smanu pni.pni_va = &auxt->pvnr_va;
75870d81924Smanu pni.pni_va_ttl = &auxt->pvnr_va_ttl;
75970d81924Smanu pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
76080234546Spooka
761e9cad0ceSpooka if (buildpath) {
762e9cad0ceSpooka error = puffs_path_pcnbuild(pu, &pcn, opcookie);
763e9cad0ceSpooka if (error)
764e9cad0ceSpooka break;
765e9cad0ceSpooka }
766e9cad0ceSpooka
76721913eabSpooka error = pops->puffs_node_symlink(pu,
76880234546Spooka opcookie, &pni, &pcn,
76980234546Spooka &auxt->pvnr_va, auxt->pvnr_link);
770e9cad0ceSpooka
771e9cad0ceSpooka if (buildpath) {
772e9cad0ceSpooka if (error) {
773e9cad0ceSpooka pu->pu_pathfree(pu, &pcn.pcn_po_full);
774e9cad0ceSpooka } else {
775e9cad0ceSpooka pn = PU_CMAP(pu, auxt->pvnr_newnode);
776e9cad0ceSpooka pn->pn_po = pcn.pcn_po_full;
777e9cad0ceSpooka }
778e9cad0ceSpooka }
779e9cad0ceSpooka
780d256e384Smanu if (pncookie && !error) {
781244cd4a7Smanu if (pn == NULL)
782244cd4a7Smanu pn = PU_CMAP(pu, auxt->pvnr_newnode);
783244cd4a7Smanu pn->pn_nlookup++;
784244cd4a7Smanu }
785e9cad0ceSpooka break;
786e9cad0ceSpooka }
787e9cad0ceSpooka
788e9cad0ceSpooka case PUFFS_VN_READDIR:
789e9cad0ceSpooka {
79033c91738Spooka struct puffs_vnmsg_readdir *auxt = auxbuf;
791438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
792e9cad0ceSpooka struct dirent *dent;
793e9cad0ceSpooka off_t *cookies;
794e9cad0ceSpooka size_t res, origcookies;
795e9cad0ceSpooka
796e9cad0ceSpooka if (pops->puffs_node_readdir == NULL) {
797e9cad0ceSpooka error = 0;
798e9cad0ceSpooka break;
799e9cad0ceSpooka }
800e9cad0ceSpooka
801e9cad0ceSpooka if (auxt->pvnr_ncookies) {
802e9cad0ceSpooka /* LINTED: pvnr_data is __aligned() */
803e9cad0ceSpooka cookies = (off_t *)auxt->pvnr_data;
804e9cad0ceSpooka origcookies = auxt->pvnr_ncookies;
805e9cad0ceSpooka } else {
806e9cad0ceSpooka cookies = NULL;
807e9cad0ceSpooka origcookies = 0;
808e9cad0ceSpooka }
809e9cad0ceSpooka /* LINTED: dentoff is aligned in the kernel */
810e9cad0ceSpooka dent = (struct dirent *)
811e9cad0ceSpooka (auxt->pvnr_data + auxt->pvnr_dentoff);
812e9cad0ceSpooka
813e9cad0ceSpooka res = auxt->pvnr_resid;
81421913eabSpooka error = pops->puffs_node_readdir(pu,
815e9cad0ceSpooka opcookie, dent, &auxt->pvnr_offset,
816438f52d2Spooka &auxt->pvnr_resid, pcr, &auxt->pvnr_eofflag,
817438f52d2Spooka cookies, &auxt->pvnr_ncookies);
818e9cad0ceSpooka
819e9cad0ceSpooka /* much easier to track non-working NFS */
820e9cad0ceSpooka assert(auxt->pvnr_ncookies <= origcookies);
821e9cad0ceSpooka
822e9cad0ceSpooka /* need to move a bit more */
82333c91738Spooka preq->preq_buflen = sizeof(struct puffs_vnmsg_readdir)
824e9cad0ceSpooka + auxt->pvnr_dentoff + (res - auxt->pvnr_resid);
825e9cad0ceSpooka break;
826e9cad0ceSpooka }
827e9cad0ceSpooka
828e9cad0ceSpooka case PUFFS_VN_READLINK:
829e9cad0ceSpooka {
83033c91738Spooka struct puffs_vnmsg_readlink *auxt = auxbuf;
831438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
832438f52d2Spooka
833e9cad0ceSpooka if (pops->puffs_node_readlink == NULL) {
834e9cad0ceSpooka error = EOPNOTSUPP;
835e9cad0ceSpooka break;
836e9cad0ceSpooka }
837e9cad0ceSpooka
838438f52d2Spooka /*LINTED*/
83921913eabSpooka error = pops->puffs_node_readlink(pu, opcookie, pcr,
840e9cad0ceSpooka auxt->pvnr_link, &auxt->pvnr_linklen);
841e9cad0ceSpooka break;
842e9cad0ceSpooka }
843e9cad0ceSpooka
844e9cad0ceSpooka case PUFFS_VN_RECLAIM:
845e9cad0ceSpooka {
8468502ba8eSmanu struct puffs_vnmsg_reclaim *auxt = auxbuf;
8478502ba8eSmanu struct puffs_node *pn;
848ffe0a014Spooka
849d256e384Smanu if (pops->puffs_node_reclaim2 != NULL) {
850d256e384Smanu error = pops->puffs_node_reclaim2(pu, opcookie,
851d256e384Smanu auxt->pvnr_nlookup);
852d256e384Smanu break;
853d256e384Smanu }
854d256e384Smanu
855e9cad0ceSpooka if (pops->puffs_node_reclaim == NULL) {
856e9cad0ceSpooka error = 0;
857e9cad0ceSpooka break;
858e9cad0ceSpooka }
859e9cad0ceSpooka
8608502ba8eSmanu /*
8618502ba8eSmanu * This fixes a race condition,
8628502ba8eSmanu * where a node in reclaimed by kernel
8638502ba8eSmanu * after a lookup request is sent,
8648502ba8eSmanu * but before the reply, leaving the kernel
8658502ba8eSmanu * with a invalid vnode/cookie reference.
8668502ba8eSmanu */
867d256e384Smanu if (pncookie) {
8688502ba8eSmanu pn = PU_CMAP(pu, opcookie);
8698502ba8eSmanu pn->pn_nlookup -= auxt->pvnr_nlookup;
8708502ba8eSmanu if (pn->pn_nlookup >= 1) {
8718502ba8eSmanu error = 0;
8728502ba8eSmanu break;
8738502ba8eSmanu }
874d256e384Smanu }
8758502ba8eSmanu
87621913eabSpooka error = pops->puffs_node_reclaim(pu, opcookie);
877e9cad0ceSpooka break;
878e9cad0ceSpooka }
879e9cad0ceSpooka
880e9cad0ceSpooka case PUFFS_VN_INACTIVE:
881e9cad0ceSpooka {
882ffe0a014Spooka
883e9cad0ceSpooka if (pops->puffs_node_inactive == NULL) {
884e9cad0ceSpooka error = EOPNOTSUPP;
885e9cad0ceSpooka break;
886e9cad0ceSpooka }
887e9cad0ceSpooka
88821913eabSpooka error = pops->puffs_node_inactive(pu, opcookie);
889e9cad0ceSpooka break;
890e9cad0ceSpooka }
891e9cad0ceSpooka
892e9cad0ceSpooka case PUFFS_VN_PATHCONF:
893e9cad0ceSpooka {
89433c91738Spooka struct puffs_vnmsg_pathconf *auxt = auxbuf;
895e9cad0ceSpooka if (pops->puffs_node_pathconf == NULL) {
896*2d9177bfSmlelstv error = EINVAL;
897e9cad0ceSpooka break;
898e9cad0ceSpooka }
899e9cad0ceSpooka
90021913eabSpooka error = pops->puffs_node_pathconf(pu,
901e9cad0ceSpooka opcookie, auxt->pvnr_name,
902e9cad0ceSpooka &auxt->pvnr_retval);
903e9cad0ceSpooka break;
904e9cad0ceSpooka }
905e9cad0ceSpooka
906e9cad0ceSpooka case PUFFS_VN_ADVLOCK:
907e9cad0ceSpooka {
90833c91738Spooka struct puffs_vnmsg_advlock *auxt = auxbuf;
909e9cad0ceSpooka if (pops->puffs_node_advlock == NULL) {
910e9cad0ceSpooka error = 0;
911e9cad0ceSpooka break;
912e9cad0ceSpooka }
913e9cad0ceSpooka
91421913eabSpooka error = pops->puffs_node_advlock(pu,
915e9cad0ceSpooka opcookie, auxt->pvnr_id, auxt->pvnr_op,
916e9cad0ceSpooka &auxt->pvnr_fl, auxt->pvnr_flags);
917e9cad0ceSpooka break;
918e9cad0ceSpooka }
919e9cad0ceSpooka
920e9cad0ceSpooka case PUFFS_VN_PRINT:
921e9cad0ceSpooka {
922e9cad0ceSpooka if (pops->puffs_node_print == NULL) {
923e9cad0ceSpooka error = 0;
924e9cad0ceSpooka break;
925e9cad0ceSpooka }
926e9cad0ceSpooka
92721913eabSpooka error = pops->puffs_node_print(pu,
928e9cad0ceSpooka opcookie);
929e9cad0ceSpooka break;
930e9cad0ceSpooka }
931e9cad0ceSpooka
93275008bfcSpooka case PUFFS_VN_ABORTOP:
93375008bfcSpooka {
93475008bfcSpooka struct puffs_vnmsg_abortop *auxt = auxbuf;
93575008bfcSpooka struct puffs_cn pcn;
93675008bfcSpooka
93775008bfcSpooka if (pops->puffs_node_abortop == NULL) {
93875008bfcSpooka error = 0;
93975008bfcSpooka break;
94075008bfcSpooka }
94175008bfcSpooka
94275008bfcSpooka pcn.pcn_pkcnp = &auxt->pvnr_cn;
94375008bfcSpooka PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
94475008bfcSpooka
94575008bfcSpooka error = pops->puffs_node_abortop(pu, opcookie, &pcn);
94675008bfcSpooka
94775008bfcSpooka break;
94875008bfcSpooka }
94975008bfcSpooka
950e9cad0ceSpooka case PUFFS_VN_READ:
951e9cad0ceSpooka {
95233c91738Spooka struct puffs_vnmsg_read *auxt = auxbuf;
953438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
954e9cad0ceSpooka size_t res;
955e9cad0ceSpooka
956e9cad0ceSpooka if (pops->puffs_node_read == NULL) {
957e9cad0ceSpooka error = EIO;
958e9cad0ceSpooka break;
959e9cad0ceSpooka }
960e9cad0ceSpooka
961e9cad0ceSpooka res = auxt->pvnr_resid;
96221913eabSpooka error = pops->puffs_node_read(pu,
963e9cad0ceSpooka opcookie, auxt->pvnr_data,
964e9cad0ceSpooka auxt->pvnr_offset, &auxt->pvnr_resid,
965438f52d2Spooka pcr, auxt->pvnr_ioflag);
966e9cad0ceSpooka
967e9cad0ceSpooka /* need to move a bit more */
96833c91738Spooka preq->preq_buflen = sizeof(struct puffs_vnmsg_read)
969e9cad0ceSpooka + (res - auxt->pvnr_resid);
970e9cad0ceSpooka break;
971e9cad0ceSpooka }
972e9cad0ceSpooka
973e9cad0ceSpooka case PUFFS_VN_WRITE:
974e9cad0ceSpooka {
97533c91738Spooka struct puffs_vnmsg_write *auxt = auxbuf;
976438f52d2Spooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
977e9cad0ceSpooka
978d1056538Smanu if (pops->puffs_node_write2 != NULL) {
979d1056538Smanu int xflag = 0;
980e9cad0ceSpooka
981d1056538Smanu if (!PUFFSOP_WANTREPLY(preq->preq_opclass))
982d1056538Smanu xflag |= PUFFS_SETATTR_FAF;
983d1056538Smanu
984d1056538Smanu error = pops->puffs_node_write2(pu,
985d1056538Smanu opcookie, auxt->pvnr_data,
986d1056538Smanu auxt->pvnr_offset, &auxt->pvnr_resid,
987d1056538Smanu pcr, auxt->pvnr_ioflag, xflag);
988d1056538Smanu
989d1056538Smanu } else if (pops->puffs_node_write != NULL) {
99021913eabSpooka error = pops->puffs_node_write(pu,
991e9cad0ceSpooka opcookie, auxt->pvnr_data,
992e9cad0ceSpooka auxt->pvnr_offset, &auxt->pvnr_resid,
993438f52d2Spooka pcr, auxt->pvnr_ioflag);
994d1056538Smanu } else {
995d1056538Smanu error = EIO;
996d1056538Smanu break;
997d1056538Smanu }
998d1056538Smanu
999e9cad0ceSpooka
1000e9cad0ceSpooka /* don't need to move data back to the kernel */
100133c91738Spooka preq->preq_buflen = sizeof(struct puffs_vnmsg_write);
1002e9cad0ceSpooka break;
1003e9cad0ceSpooka }
1004e9cad0ceSpooka
100575bb6c40Spooka case PUFFS_VN_POLL:
100675bb6c40Spooka {
100733c91738Spooka struct puffs_vnmsg_poll *auxt = auxbuf;
1008ffe0a014Spooka
100975bb6c40Spooka if (pops->puffs_node_poll == NULL) {
101075bb6c40Spooka error = 0;
101175bb6c40Spooka
101275bb6c40Spooka /* emulate genfs_poll() */
101375bb6c40Spooka auxt->pvnr_events &= (POLLIN | POLLOUT
101475bb6c40Spooka | POLLRDNORM | POLLWRNORM);
101575bb6c40Spooka
101675bb6c40Spooka break;
101775bb6c40Spooka }
101875bb6c40Spooka
101921913eabSpooka error = pops->puffs_node_poll(pu,
10206a3d9a18Spooka opcookie, &auxt->pvnr_events);
102175bb6c40Spooka break;
102275bb6c40Spooka }
102375bb6c40Spooka
1024c3be8a8cSpooka case PUFFS_VN_GETEXTATTR:
1025c3be8a8cSpooka {
1026c3be8a8cSpooka struct puffs_vnmsg_getextattr *auxt = auxbuf;
1027c3be8a8cSpooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
1028c3be8a8cSpooka size_t res, *resp, *sizep;
1029c3be8a8cSpooka uint8_t *data;
1030c3be8a8cSpooka
1031c3be8a8cSpooka if (pops->puffs_node_getextattr == NULL) {
1032c3be8a8cSpooka error = EOPNOTSUPP;
1033c3be8a8cSpooka break;
1034c3be8a8cSpooka }
1035c3be8a8cSpooka
1036c3be8a8cSpooka if (auxt->pvnr_datasize)
1037c3be8a8cSpooka sizep = &auxt->pvnr_datasize;
1038c3be8a8cSpooka else
1039c3be8a8cSpooka sizep = NULL;
1040c3be8a8cSpooka
1041c3be8a8cSpooka res = auxt->pvnr_resid;
1042c3be8a8cSpooka if (res > 0) {
1043c3be8a8cSpooka data = auxt->pvnr_data;
1044c3be8a8cSpooka resp = &auxt->pvnr_resid;
1045c3be8a8cSpooka } else {
1046c3be8a8cSpooka data = NULL;
1047c3be8a8cSpooka resp = NULL;
1048c3be8a8cSpooka }
1049c3be8a8cSpooka
1050c3be8a8cSpooka error = pops->puffs_node_getextattr(pu,
1051c3be8a8cSpooka opcookie, auxt->pvnr_attrnamespace,
1052c3be8a8cSpooka auxt->pvnr_attrname, sizep, data, resp, pcr);
1053c3be8a8cSpooka
1054c3be8a8cSpooka /* need to move a bit more? */
1055c3be8a8cSpooka preq->preq_buflen =
1056c3be8a8cSpooka sizeof(struct puffs_vnmsg_getextattr)
1057c3be8a8cSpooka + (res - auxt->pvnr_resid);
1058c3be8a8cSpooka break;
1059c3be8a8cSpooka }
1060c3be8a8cSpooka
1061c3be8a8cSpooka case PUFFS_VN_SETEXTATTR:
1062c3be8a8cSpooka {
1063c3be8a8cSpooka struct puffs_vnmsg_setextattr *auxt = auxbuf;
1064c3be8a8cSpooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
1065c3be8a8cSpooka size_t *resp;
1066c3be8a8cSpooka uint8_t *data;
1067c3be8a8cSpooka
1068c3be8a8cSpooka if (pops->puffs_node_setextattr == NULL) {
1069c3be8a8cSpooka error = EOPNOTSUPP;
1070c3be8a8cSpooka break;
1071c3be8a8cSpooka }
1072c3be8a8cSpooka
1073c3be8a8cSpooka if (auxt->pvnr_resid > 0) {
1074c3be8a8cSpooka data = auxt->pvnr_data;
1075c3be8a8cSpooka resp = &auxt->pvnr_resid;
1076c3be8a8cSpooka } else {
1077c3be8a8cSpooka data = NULL;
1078c3be8a8cSpooka resp = NULL;
1079c3be8a8cSpooka }
1080c3be8a8cSpooka
1081c3be8a8cSpooka error = pops->puffs_node_setextattr(pu,
1082c3be8a8cSpooka opcookie, auxt->pvnr_attrnamespace,
1083c3be8a8cSpooka auxt->pvnr_attrname, data, resp, pcr);
1084c3be8a8cSpooka break;
1085c3be8a8cSpooka }
1086c3be8a8cSpooka
1087c3be8a8cSpooka case PUFFS_VN_LISTEXTATTR:
1088c3be8a8cSpooka {
1089c3be8a8cSpooka struct puffs_vnmsg_listextattr *auxt = auxbuf;
1090c3be8a8cSpooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
1091c3be8a8cSpooka size_t res, *resp, *sizep;
1092be95d607Smanu int flag;
1093c3be8a8cSpooka uint8_t *data;
1094c3be8a8cSpooka
1095c3be8a8cSpooka if (pops->puffs_node_listextattr == NULL) {
1096c3be8a8cSpooka error = EOPNOTSUPP;
1097c3be8a8cSpooka break;
1098c3be8a8cSpooka }
1099c3be8a8cSpooka
1100c3be8a8cSpooka if (auxt->pvnr_datasize)
1101c3be8a8cSpooka sizep = &auxt->pvnr_datasize;
1102c3be8a8cSpooka else
1103c3be8a8cSpooka sizep = NULL;
1104c3be8a8cSpooka
1105c3be8a8cSpooka res = auxt->pvnr_resid;
1106c3be8a8cSpooka if (res > 0) {
1107c3be8a8cSpooka data = auxt->pvnr_data;
1108c3be8a8cSpooka resp = &auxt->pvnr_resid;
1109c3be8a8cSpooka } else {
1110c3be8a8cSpooka data = NULL;
1111c3be8a8cSpooka resp = NULL;
1112c3be8a8cSpooka }
1113c3be8a8cSpooka
1114c3be8a8cSpooka res = auxt->pvnr_resid;
1115be95d607Smanu flag = auxt->pvnr_flag;
1116c3be8a8cSpooka error = pops->puffs_node_listextattr(pu,
1117c3be8a8cSpooka opcookie, auxt->pvnr_attrnamespace,
1118be95d607Smanu sizep, data, resp, flag, pcr);
1119c3be8a8cSpooka
1120c3be8a8cSpooka /* need to move a bit more? */
1121c3be8a8cSpooka preq->preq_buflen =
1122c3be8a8cSpooka sizeof(struct puffs_vnmsg_listextattr)
1123c3be8a8cSpooka + (res - auxt->pvnr_resid);
1124c3be8a8cSpooka break;
1125c3be8a8cSpooka }
1126c3be8a8cSpooka
1127c3be8a8cSpooka case PUFFS_VN_DELETEEXTATTR:
1128c3be8a8cSpooka {
1129c3be8a8cSpooka struct puffs_vnmsg_deleteextattr *auxt = auxbuf;
1130c3be8a8cSpooka PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
1131c3be8a8cSpooka
1132c3be8a8cSpooka if (pops->puffs_node_deleteextattr == NULL) {
1133c3be8a8cSpooka error = EOPNOTSUPP;
1134c3be8a8cSpooka break;
1135c3be8a8cSpooka }
1136c3be8a8cSpooka
1137c3be8a8cSpooka error = pops->puffs_node_deleteextattr(pu,
1138c3be8a8cSpooka opcookie, auxt->pvnr_attrnamespace,
1139c3be8a8cSpooka auxt->pvnr_attrname, pcr);
1140c3be8a8cSpooka break;
1141c3be8a8cSpooka }
1142c3be8a8cSpooka
1143cf73d533Smanu case PUFFS_VN_FALLOCATE:
1144cf73d533Smanu {
1145cf73d533Smanu struct puffs_vnmsg_fallocate *auxt = auxbuf;
1146cf73d533Smanu
1147cf73d533Smanu if (pops->puffs_node_fallocate == NULL) {
1148cf73d533Smanu error = EOPNOTSUPP;
1149cf73d533Smanu break;
1150cf73d533Smanu }
1151cf73d533Smanu
1152cf73d533Smanu error = pops->puffs_node_fallocate(pu,
1153cf73d533Smanu opcookie, auxt->pvnr_off, auxt->pvnr_len);
1154cf73d533Smanu break;
1155cf73d533Smanu }
1156cf73d533Smanu
1157cf73d533Smanu case PUFFS_VN_FDISCARD:
1158cf73d533Smanu {
1159cf73d533Smanu struct puffs_vnmsg_fdiscard *auxt = auxbuf;
1160cf73d533Smanu
1161cf73d533Smanu if (pops->puffs_node_fdiscard == NULL) {
1162cf73d533Smanu error = EOPNOTSUPP;
1163cf73d533Smanu break;
1164cf73d533Smanu }
1165cf73d533Smanu
1166cf73d533Smanu error = pops->puffs_node_fdiscard(pu,
1167cf73d533Smanu opcookie, auxt->pvnr_off, auxt->pvnr_len);
1168cf73d533Smanu break;
1169cf73d533Smanu }
1170cf73d533Smanu
1171e9cad0ceSpooka default:
1172e9cad0ceSpooka printf("inval op %d\n", preq->preq_optype);
1173e9cad0ceSpooka error = EINVAL;
1174e9cad0ceSpooka break;
1175e9cad0ceSpooka }
1176d1d05d65Spooka
117775008bfcSpooka #if 0
117875008bfcSpooka /* not issued by kernel currently */
1179d1d05d65Spooka } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_CACHE) {
1180d1d05d65Spooka struct puffs_cacheinfo *pci = (void *)preq;
1181d1d05d65Spooka
1182d1d05d65Spooka if (pu->pu_ops.puffs_cache_write) {
1183d1d05d65Spooka pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie,
1184d1d05d65Spooka pci->pcache_nruns, pci->pcache_runs);
1185d1d05d65Spooka }
1186d1d05d65Spooka error = 0;
118775008bfcSpooka #endif
1188d1d05d65Spooka
1189d1d05d65Spooka } else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_ERROR) {
1190d1d05d65Spooka struct puffs_error *perr = (void *)preq;
1191d1d05d65Spooka
1192d1d05d65Spooka pu->pu_errnotify(pu, preq->preq_optype,
1193d1d05d65Spooka perr->perr_error, perr->perr_str, preq->preq_cookie);
1194d1d05d65Spooka error = 0;
1195e9cad0ceSpooka } else {
1196e9cad0ceSpooka /*
1197d1d05d65Spooka * I guess the kernel sees this one coming also
1198e9cad0ceSpooka */
1199e9cad0ceSpooka error = EINVAL;
1200e9cad0ceSpooka }
120173bad8cbSpooka
120273bad8cbSpooka out:
1203e9cad0ceSpooka preq->preq_rv = error;
1204291fe845Spooka
1205b40b63f0Spooka if (pu->pu_oppost)
120621913eabSpooka pu->pu_oppost(pu);
1207b40b63f0Spooka
1208d1d05d65Spooka pcc->pcc_flags |= PCC_DONE;
1209edb40ac9Spooka }
1210