xref: /netbsd-src/lib/libpuffs/dispatcher.c (revision 2d9177bfbe2761bad0a3780ff348d979fe4c5cd4)
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