xref: /minix3/lib/libpuffs/dispatcher.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: dispatcher.c,v 1.48 2014/10/31 13:56:04 manu Exp $	*/
284d9c625SLionel Sambuc 
384d9c625SLionel Sambuc /*
484d9c625SLionel Sambuc  * Copyright (c) 2006, 2007, 2008 Antti Kantee.  All Rights Reserved.
584d9c625SLionel Sambuc  *
684d9c625SLionel Sambuc  * Development of this software was supported by the
784d9c625SLionel Sambuc  * Ulla Tuominen Foundation, the Finnish Cultural Foundation and
884d9c625SLionel Sambuc  * Research Foundation of Helsinki University of Technology.
984d9c625SLionel Sambuc  *
1084d9c625SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
1184d9c625SLionel Sambuc  * modification, are permitted provided that the following conditions
1284d9c625SLionel Sambuc  * are met:
1384d9c625SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
1484d9c625SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
1584d9c625SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
1684d9c625SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
1784d9c625SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
1884d9c625SLionel Sambuc  *
1984d9c625SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
2084d9c625SLionel Sambuc  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2184d9c625SLionel Sambuc  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2284d9c625SLionel Sambuc  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2384d9c625SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2484d9c625SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2584d9c625SLionel Sambuc  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2684d9c625SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2784d9c625SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2884d9c625SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2984d9c625SLionel Sambuc  * SUCH DAMAGE.
3084d9c625SLionel Sambuc  */
3184d9c625SLionel Sambuc 
3284d9c625SLionel Sambuc #include <sys/cdefs.h>
3384d9c625SLionel Sambuc #if !defined(lint)
34*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: dispatcher.c,v 1.48 2014/10/31 13:56:04 manu Exp $");
3584d9c625SLionel Sambuc #endif /* !lint */
3684d9c625SLionel Sambuc 
3784d9c625SLionel Sambuc #include <sys/types.h>
3884d9c625SLionel Sambuc #include <sys/poll.h>
3984d9c625SLionel Sambuc 
4084d9c625SLionel Sambuc #include <assert.h>
4184d9c625SLionel Sambuc #include <errno.h>
4284d9c625SLionel Sambuc #include <pthread.h>
4384d9c625SLionel Sambuc #include <puffs.h>
4484d9c625SLionel Sambuc #include <puffsdump.h>
4584d9c625SLionel Sambuc #include <stdio.h>
4684d9c625SLionel Sambuc #include <stdlib.h>
4784d9c625SLionel Sambuc #include <unistd.h>
4884d9c625SLionel Sambuc 
4984d9c625SLionel Sambuc #include "puffs_priv.h"
5084d9c625SLionel Sambuc 
5184d9c625SLionel Sambuc #define PUFFS_USE_FS_TTL(pu) (pu->pu_flags & PUFFS_KFLAG_CACHE_FS_TTL)
5284d9c625SLionel Sambuc 
5384d9c625SLionel Sambuc static void dispatch(struct puffs_cc *);
5484d9c625SLionel Sambuc 
5584d9c625SLionel Sambuc /* for our eyes only */
5684d9c625SLionel Sambuc void
puffs__ml_dispatch(struct puffs_usermount * pu,struct puffs_framebuf * pb)5784d9c625SLionel Sambuc puffs__ml_dispatch(struct puffs_usermount *pu, struct puffs_framebuf *pb)
5884d9c625SLionel Sambuc {
5984d9c625SLionel Sambuc 	struct puffs_cc *pcc = puffs_cc_getcc(pu);
6084d9c625SLionel Sambuc 	struct puffs_req *preq;
6184d9c625SLionel Sambuc 
6284d9c625SLionel Sambuc 	pcc->pcc_pb = pb;
6384d9c625SLionel Sambuc 	pcc->pcc_flags |= PCC_MLCONT;
6484d9c625SLionel Sambuc 	dispatch(pcc);
6584d9c625SLionel Sambuc 
6684d9c625SLionel Sambuc 	/* Put result to kernel sendqueue if necessary */
6784d9c625SLionel Sambuc 	preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
6884d9c625SLionel Sambuc 	if (PUFFSOP_WANTREPLY(preq->preq_opclass)) {
6984d9c625SLionel Sambuc 		if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
7084d9c625SLionel Sambuc 			puffsdump_rv(preq);
7184d9c625SLionel Sambuc 
7284d9c625SLionel Sambuc 		puffs_framev_enqueue_justsend(pu, pu->pu_fd,
7384d9c625SLionel Sambuc 		    pcc->pcc_pb, 0, 0);
7484d9c625SLionel Sambuc 	} else {
7584d9c625SLionel Sambuc 		puffs_framebuf_destroy(pcc->pcc_pb);
7684d9c625SLionel Sambuc 	}
7784d9c625SLionel Sambuc 
7884d9c625SLionel Sambuc 	/* who needs information when you're living on borrowed time? */
7984d9c625SLionel Sambuc 	if (pcc->pcc_flags & PCC_BORROWED) {
8084d9c625SLionel Sambuc 		puffs_cc_yield(pcc); /* back to borrow source */
8184d9c625SLionel Sambuc 	}
8284d9c625SLionel Sambuc 	pcc->pcc_flags = 0;
8384d9c625SLionel Sambuc }
8484d9c625SLionel Sambuc 
8584d9c625SLionel Sambuc /* public, but not really tested and only semi-supported */
8684d9c625SLionel Sambuc int
puffs_dispatch_create(struct puffs_usermount * pu,struct puffs_framebuf * pb,struct puffs_cc ** pccp)8784d9c625SLionel Sambuc puffs_dispatch_create(struct puffs_usermount *pu, struct puffs_framebuf *pb,
8884d9c625SLionel Sambuc 	struct puffs_cc **pccp)
8984d9c625SLionel Sambuc {
9084d9c625SLionel Sambuc 	struct puffs_cc *pcc;
9184d9c625SLionel Sambuc 
9284d9c625SLionel Sambuc 	if (puffs__cc_create(pu, dispatch, &pcc) == -1)
9384d9c625SLionel Sambuc 		return -1;
9484d9c625SLionel Sambuc 
9584d9c625SLionel Sambuc 	pcc->pcc_pb = pb;
9684d9c625SLionel Sambuc 	*pccp = pcc;
9784d9c625SLionel Sambuc 
9884d9c625SLionel Sambuc 	return 0;
9984d9c625SLionel Sambuc }
10084d9c625SLionel Sambuc 
10184d9c625SLionel Sambuc int
puffs_dispatch_exec(struct puffs_cc * pcc,struct puffs_framebuf ** pbp)10284d9c625SLionel Sambuc puffs_dispatch_exec(struct puffs_cc *pcc, struct puffs_framebuf **pbp)
10384d9c625SLionel Sambuc {
10484d9c625SLionel Sambuc 	int rv;
10584d9c625SLionel Sambuc 
10684d9c625SLionel Sambuc 	puffs_cc_continue(pcc);
10784d9c625SLionel Sambuc 
10884d9c625SLionel Sambuc 	if (pcc->pcc_flags & PCC_DONE) {
10984d9c625SLionel Sambuc 		rv = 1;
11084d9c625SLionel Sambuc 		*pbp = pcc->pcc_pb;
11184d9c625SLionel Sambuc 		pcc->pcc_flags = 0;
11284d9c625SLionel Sambuc 		puffs__cc_destroy(pcc, 0);
11384d9c625SLionel Sambuc 	} else {
11484d9c625SLionel Sambuc 		rv = 0;
11584d9c625SLionel Sambuc 	}
11684d9c625SLionel Sambuc 
11784d9c625SLionel Sambuc 	return rv;
11884d9c625SLionel Sambuc }
11984d9c625SLionel Sambuc 
12084d9c625SLionel Sambuc static void
dispatch(struct puffs_cc * pcc)12184d9c625SLionel Sambuc dispatch(struct puffs_cc *pcc)
12284d9c625SLionel Sambuc {
12384d9c625SLionel Sambuc 	struct puffs_usermount *pu = pcc->pcc_pu;
12484d9c625SLionel Sambuc 	struct puffs_ops *pops = &pu->pu_ops;
12584d9c625SLionel Sambuc 	struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
12684d9c625SLionel Sambuc 	void *auxbuf; /* help with typecasting */
12784d9c625SLionel Sambuc 	puffs_cookie_t opcookie;
12884d9c625SLionel Sambuc 	int error = 0, buildpath, pncookie;
12984d9c625SLionel Sambuc 
13084d9c625SLionel Sambuc 	/* XXX: smaller hammer, please */
13184d9c625SLionel Sambuc 	if ((PUFFSOP_OPCLASS(preq->preq_opclass == PUFFSOP_VFS &&
13284d9c625SLionel Sambuc 	    preq->preq_optype == PUFFS_VFS_VPTOFH)) ||
13384d9c625SLionel Sambuc 	    (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN &&
13484d9c625SLionel Sambuc 	    (preq->preq_optype == PUFFS_VN_READDIR
13584d9c625SLionel Sambuc 	    || preq->preq_optype == PUFFS_VN_READ))) {
13684d9c625SLionel Sambuc 		if (puffs_framebuf_reserve_space(pcc->pcc_pb,
13784d9c625SLionel Sambuc 		    PUFFS_MSG_MAXSIZE) == -1)
13884d9c625SLionel Sambuc 			error = errno;
13984d9c625SLionel Sambuc 		preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
14084d9c625SLionel Sambuc 	}
14184d9c625SLionel Sambuc 
14284d9c625SLionel Sambuc 	auxbuf = preq;
14384d9c625SLionel Sambuc 	opcookie = preq->preq_cookie;
14484d9c625SLionel Sambuc 
14584d9c625SLionel Sambuc 	assert((pcc->pcc_flags & PCC_DONE) == 0);
14684d9c625SLionel Sambuc 
14784d9c625SLionel Sambuc 	buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH;
14884d9c625SLionel Sambuc 	pncookie = pu->pu_flags & PUFFS_FLAG_PNCOOKIE;
14984d9c625SLionel Sambuc 	assert(!buildpath || pncookie);
15084d9c625SLionel Sambuc 
15184d9c625SLionel Sambuc 	preq->preq_setbacks = 0;
15284d9c625SLionel Sambuc 
15384d9c625SLionel Sambuc 	if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
15484d9c625SLionel Sambuc 		puffsdump_req(preq);
15584d9c625SLionel Sambuc 
15684d9c625SLionel Sambuc 	puffs__cc_setcaller(pcc, preq->preq_pid, preq->preq_lid);
15784d9c625SLionel Sambuc 
15884d9c625SLionel Sambuc 	/* pre-operation */
15984d9c625SLionel Sambuc 	if (pu->pu_oppre)
16084d9c625SLionel Sambuc 		pu->pu_oppre(pu);
16184d9c625SLionel Sambuc 
16284d9c625SLionel Sambuc 	if (error)
16384d9c625SLionel Sambuc 		goto out;
16484d9c625SLionel Sambuc 
16584d9c625SLionel Sambuc 	/* Execute actual operation */
16684d9c625SLionel Sambuc 	if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
16784d9c625SLionel Sambuc 		switch (preq->preq_optype) {
16884d9c625SLionel Sambuc 		case PUFFS_VFS_UNMOUNT:
16984d9c625SLionel Sambuc 		{
17084d9c625SLionel Sambuc 			struct puffs_vfsmsg_unmount *auxt = auxbuf;
17184d9c625SLionel Sambuc 
17284d9c625SLionel Sambuc 			PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTING);
17384d9c625SLionel Sambuc 			error = pops->puffs_fs_unmount(pu, auxt->pvfsr_flags);
17484d9c625SLionel Sambuc 			if (!error)
17584d9c625SLionel Sambuc 				PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED);
17684d9c625SLionel Sambuc 			else
17784d9c625SLionel Sambuc 				PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
17884d9c625SLionel Sambuc 			break;
17984d9c625SLionel Sambuc 		}
18084d9c625SLionel Sambuc 
18184d9c625SLionel Sambuc 		case PUFFS_VFS_STATVFS:
18284d9c625SLionel Sambuc 		{
18384d9c625SLionel Sambuc 			struct puffs_vfsmsg_statvfs *auxt = auxbuf;
18484d9c625SLionel Sambuc 
18584d9c625SLionel Sambuc 			error = pops->puffs_fs_statvfs(pu, &auxt->pvfsr_sb);
18684d9c625SLionel Sambuc 			break;
18784d9c625SLionel Sambuc 		}
18884d9c625SLionel Sambuc 
18984d9c625SLionel Sambuc 		case PUFFS_VFS_SYNC:
19084d9c625SLionel Sambuc 		{
19184d9c625SLionel Sambuc 			struct puffs_vfsmsg_sync *auxt = auxbuf;
19284d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvfsr_cred);
19384d9c625SLionel Sambuc 
19484d9c625SLionel Sambuc 			error = pops->puffs_fs_sync(pu,
19584d9c625SLionel Sambuc 			    auxt->pvfsr_waitfor, pcr);
19684d9c625SLionel Sambuc 			break;
19784d9c625SLionel Sambuc 		}
19884d9c625SLionel Sambuc 
19984d9c625SLionel Sambuc 		case PUFFS_VFS_FHTOVP:
20084d9c625SLionel Sambuc 		{
20184d9c625SLionel Sambuc 			struct puffs_vfsmsg_fhtonode *auxt = auxbuf;
20284d9c625SLionel Sambuc 			struct puffs_newinfo pni;
20384d9c625SLionel Sambuc 
20484d9c625SLionel Sambuc 			pni.pni_cookie = &auxt->pvfsr_fhcookie;
20584d9c625SLionel Sambuc 			pni.pni_vtype = &auxt->pvfsr_vtype;
20684d9c625SLionel Sambuc 			pni.pni_size = &auxt->pvfsr_size;
20784d9c625SLionel Sambuc 			pni.pni_rdev = &auxt->pvfsr_rdev;
20884d9c625SLionel Sambuc 			pni.pni_va = NULL;
20984d9c625SLionel Sambuc 			pni.pni_va_ttl = NULL;
21084d9c625SLionel Sambuc 			pni.pni_cn_ttl = NULL;
21184d9c625SLionel Sambuc 
21284d9c625SLionel Sambuc 			error = pops->puffs_fs_fhtonode(pu, auxt->pvfsr_data,
21384d9c625SLionel Sambuc 			    auxt->pvfsr_dsize, &pni);
21484d9c625SLionel Sambuc 
21584d9c625SLionel Sambuc 			break;
21684d9c625SLionel Sambuc 		}
21784d9c625SLionel Sambuc 
21884d9c625SLionel Sambuc 		case PUFFS_VFS_VPTOFH:
21984d9c625SLionel Sambuc 		{
22084d9c625SLionel Sambuc 			struct puffs_vfsmsg_nodetofh *auxt = auxbuf;
22184d9c625SLionel Sambuc 
22284d9c625SLionel Sambuc 			error = pops->puffs_fs_nodetofh(pu,
22384d9c625SLionel Sambuc 			    auxt->pvfsr_fhcookie, auxt->pvfsr_data,
22484d9c625SLionel Sambuc 			    &auxt->pvfsr_dsize);
22584d9c625SLionel Sambuc 
22684d9c625SLionel Sambuc 			break;
22784d9c625SLionel Sambuc 		}
22884d9c625SLionel Sambuc 
22984d9c625SLionel Sambuc 		case PUFFS_VFS_EXTATTRCTL:
23084d9c625SLionel Sambuc 		{
23184d9c625SLionel Sambuc 			struct puffs_vfsmsg_extattrctl *auxt = auxbuf;
23284d9c625SLionel Sambuc 			const char *attrname;
23384d9c625SLionel Sambuc 			int flags;
23484d9c625SLionel Sambuc 
23584d9c625SLionel Sambuc 			if (pops->puffs_fs_extattrctl == NULL) {
23684d9c625SLionel Sambuc 				error = EOPNOTSUPP;
23784d9c625SLionel Sambuc 				break;
23884d9c625SLionel Sambuc 			}
23984d9c625SLionel Sambuc 
24084d9c625SLionel Sambuc 			if (auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASATTRNAME)
24184d9c625SLionel Sambuc 				attrname = auxt->pvfsr_attrname;
24284d9c625SLionel Sambuc 			else
24384d9c625SLionel Sambuc 				attrname = NULL;
24484d9c625SLionel Sambuc 
24584d9c625SLionel Sambuc 			flags = auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASNODE;
24684d9c625SLionel Sambuc 			error = pops->puffs_fs_extattrctl(pu, auxt->pvfsr_cmd,
24784d9c625SLionel Sambuc 			    opcookie, flags,
24884d9c625SLionel Sambuc 			    auxt->pvfsr_attrnamespace, attrname);
24984d9c625SLionel Sambuc 			break;
25084d9c625SLionel Sambuc 		}
25184d9c625SLionel Sambuc 
25284d9c625SLionel Sambuc 		default:
25384d9c625SLionel Sambuc 			/*
25484d9c625SLionel Sambuc 			 * I guess the kernel sees this one coming
25584d9c625SLionel Sambuc 			 */
25684d9c625SLionel Sambuc 			error = EINVAL;
25784d9c625SLionel Sambuc 			break;
25884d9c625SLionel Sambuc 		}
25984d9c625SLionel Sambuc 
26084d9c625SLionel Sambuc 	/* XXX: audit return values */
26184d9c625SLionel Sambuc 	/* XXX: sync with kernel */
26284d9c625SLionel Sambuc 	} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
26384d9c625SLionel Sambuc 		switch (preq->preq_optype) {
26484d9c625SLionel Sambuc 		case PUFFS_VN_LOOKUP:
26584d9c625SLionel Sambuc 		{
26684d9c625SLionel Sambuc 			struct puffs_vnmsg_lookup *auxt = auxbuf;
26784d9c625SLionel Sambuc 			struct puffs_newinfo pni;
26884d9c625SLionel Sambuc 			struct puffs_cn pcn;
26984d9c625SLionel Sambuc 			struct puffs_node *pn = NULL;
27084d9c625SLionel Sambuc 
27184d9c625SLionel Sambuc 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
27284d9c625SLionel Sambuc 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
27384d9c625SLionel Sambuc 			pni.pni_cookie = &auxt->pvnr_newnode;
27484d9c625SLionel Sambuc 			pni.pni_vtype = &auxt->pvnr_vtype;
27584d9c625SLionel Sambuc 			pni.pni_size = &auxt->pvnr_size;
27684d9c625SLionel Sambuc 			pni.pni_rdev = &auxt->pvnr_rdev;
27784d9c625SLionel Sambuc 			pni.pni_va = &auxt->pvnr_va;
27884d9c625SLionel Sambuc 			pni.pni_va_ttl = &auxt->pvnr_va_ttl;
27984d9c625SLionel Sambuc 			pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
28084d9c625SLionel Sambuc 
28184d9c625SLionel Sambuc 			if (buildpath) {
28284d9c625SLionel Sambuc 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
28384d9c625SLionel Sambuc 				if (error)
28484d9c625SLionel Sambuc 					break;
28584d9c625SLionel Sambuc 			}
28684d9c625SLionel Sambuc 
28784d9c625SLionel Sambuc 			/* lookup *must* be present */
28884d9c625SLionel Sambuc 			error = pops->puffs_node_lookup(pu, opcookie,
28984d9c625SLionel Sambuc 			    &pni, &pcn);
29084d9c625SLionel Sambuc 
29184d9c625SLionel Sambuc 			if (buildpath) {
29284d9c625SLionel Sambuc 				if (error) {
29384d9c625SLionel Sambuc 					pu->pu_pathfree(pu, &pcn.pcn_po_full);
29484d9c625SLionel Sambuc 				} else {
29584d9c625SLionel Sambuc 					/*
29684d9c625SLionel Sambuc 					 * did we get a new node or a
29784d9c625SLionel Sambuc 					 * recycled node?
29884d9c625SLionel Sambuc 					 */
29984d9c625SLionel Sambuc 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
30084d9c625SLionel Sambuc 					if (pn->pn_po.po_path == NULL)
30184d9c625SLionel Sambuc 						pn->pn_po = pcn.pcn_po_full;
30284d9c625SLionel Sambuc 					else
30384d9c625SLionel Sambuc 						pu->pu_pathfree(pu,
30484d9c625SLionel Sambuc 						    &pcn.pcn_po_full);
30584d9c625SLionel Sambuc 				}
30684d9c625SLionel Sambuc 			}
30784d9c625SLionel Sambuc 
30884d9c625SLionel Sambuc 			if (pncookie && !error) {
30984d9c625SLionel Sambuc 				if (pn == NULL)
31084d9c625SLionel Sambuc 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
31184d9c625SLionel Sambuc 				pn->pn_nlookup++;
31284d9c625SLionel Sambuc 			}
31384d9c625SLionel Sambuc 			break;
31484d9c625SLionel Sambuc 		}
31584d9c625SLionel Sambuc 
31684d9c625SLionel Sambuc 		case PUFFS_VN_CREATE:
31784d9c625SLionel Sambuc 		{
31884d9c625SLionel Sambuc 			struct puffs_vnmsg_create *auxt = auxbuf;
31984d9c625SLionel Sambuc 			struct puffs_newinfo pni;
32084d9c625SLionel Sambuc 			struct puffs_cn pcn;
32184d9c625SLionel Sambuc 			struct puffs_node *pn = NULL;
32284d9c625SLionel Sambuc 
32384d9c625SLionel Sambuc 			if (pops->puffs_node_create == NULL) {
32484d9c625SLionel Sambuc 				error = 0;
32584d9c625SLionel Sambuc 				break;
32684d9c625SLionel Sambuc 			}
32784d9c625SLionel Sambuc 
32884d9c625SLionel Sambuc 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
32984d9c625SLionel Sambuc 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
33084d9c625SLionel Sambuc 
33184d9c625SLionel Sambuc 			memset(&pni, 0, sizeof(pni));
33284d9c625SLionel Sambuc 			pni.pni_cookie = &auxt->pvnr_newnode;
33384d9c625SLionel Sambuc 			pni.pni_va = &auxt->pvnr_va;
33484d9c625SLionel Sambuc 			pni.pni_va_ttl = &auxt->pvnr_va_ttl;
33584d9c625SLionel Sambuc 			pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
33684d9c625SLionel Sambuc 
33784d9c625SLionel Sambuc 			if (buildpath) {
33884d9c625SLionel Sambuc 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
33984d9c625SLionel Sambuc 				if (error)
34084d9c625SLionel Sambuc 					break;
34184d9c625SLionel Sambuc 			}
34284d9c625SLionel Sambuc 
34384d9c625SLionel Sambuc 			error = pops->puffs_node_create(pu,
34484d9c625SLionel Sambuc 			    opcookie, &pni, &pcn, &auxt->pvnr_va);
34584d9c625SLionel Sambuc 
34684d9c625SLionel Sambuc 			if (buildpath) {
34784d9c625SLionel Sambuc 				if (error) {
34884d9c625SLionel Sambuc 					pu->pu_pathfree(pu, &pcn.pcn_po_full);
34984d9c625SLionel Sambuc 				} else {
35084d9c625SLionel Sambuc 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
35184d9c625SLionel Sambuc 					pn->pn_po = pcn.pcn_po_full;
35284d9c625SLionel Sambuc 				}
35384d9c625SLionel Sambuc 			}
35484d9c625SLionel Sambuc 
35584d9c625SLionel Sambuc 			if (pncookie && !error) {
35684d9c625SLionel Sambuc 				if (pn == NULL)
35784d9c625SLionel Sambuc 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
35884d9c625SLionel Sambuc 				pn->pn_nlookup++;
35984d9c625SLionel Sambuc 			}
36084d9c625SLionel Sambuc 			break;
36184d9c625SLionel Sambuc 		}
36284d9c625SLionel Sambuc 
36384d9c625SLionel Sambuc 		case PUFFS_VN_MKNOD:
36484d9c625SLionel Sambuc 		{
36584d9c625SLionel Sambuc 			struct puffs_vnmsg_mknod *auxt = auxbuf;
36684d9c625SLionel Sambuc 			struct puffs_newinfo pni;
36784d9c625SLionel Sambuc 			struct puffs_cn pcn;
36884d9c625SLionel Sambuc 			struct puffs_node *pn = NULL;
36984d9c625SLionel Sambuc 
37084d9c625SLionel Sambuc 			if (pops->puffs_node_mknod == NULL) {
37184d9c625SLionel Sambuc 				error = 0;
37284d9c625SLionel Sambuc 				break;
37384d9c625SLionel Sambuc 			}
37484d9c625SLionel Sambuc 
37584d9c625SLionel Sambuc 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
37684d9c625SLionel Sambuc 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
37784d9c625SLionel Sambuc 
37884d9c625SLionel Sambuc 			memset(&pni, 0, sizeof(pni));
37984d9c625SLionel Sambuc 			pni.pni_cookie = &auxt->pvnr_newnode;
38084d9c625SLionel Sambuc 			pni.pni_va = &auxt->pvnr_va;
38184d9c625SLionel Sambuc 			pni.pni_va_ttl = &auxt->pvnr_va_ttl;
38284d9c625SLionel Sambuc 			pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
38384d9c625SLionel Sambuc 
38484d9c625SLionel Sambuc 			if (buildpath) {
38584d9c625SLionel Sambuc 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
38684d9c625SLionel Sambuc 				if (error)
38784d9c625SLionel Sambuc 					break;
38884d9c625SLionel Sambuc 			}
38984d9c625SLionel Sambuc 
39084d9c625SLionel Sambuc 			error = pops->puffs_node_mknod(pu,
39184d9c625SLionel Sambuc 			    opcookie, &pni, &pcn, &auxt->pvnr_va);
39284d9c625SLionel Sambuc 
39384d9c625SLionel Sambuc 			if (buildpath) {
39484d9c625SLionel Sambuc 				if (error) {
39584d9c625SLionel Sambuc 					pu->pu_pathfree(pu, &pcn.pcn_po_full);
39684d9c625SLionel Sambuc 				} else {
39784d9c625SLionel Sambuc 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
39884d9c625SLionel Sambuc 					pn->pn_po = pcn.pcn_po_full;
39984d9c625SLionel Sambuc 				}
40084d9c625SLionel Sambuc 			}
40184d9c625SLionel Sambuc 
40284d9c625SLionel Sambuc 			if (pncookie && !error) {
40384d9c625SLionel Sambuc 				if (pn == NULL)
40484d9c625SLionel Sambuc 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
40584d9c625SLionel Sambuc 				pn->pn_nlookup++;
40684d9c625SLionel Sambuc 			}
40784d9c625SLionel Sambuc 			break;
40884d9c625SLionel Sambuc 		}
40984d9c625SLionel Sambuc 
41084d9c625SLionel Sambuc 		case PUFFS_VN_OPEN:
41184d9c625SLionel Sambuc 		{
41284d9c625SLionel Sambuc 			struct puffs_vnmsg_open *auxt = auxbuf;
41384d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
41484d9c625SLionel Sambuc 
415*0a6a1f1dSLionel Sambuc 			if (pops->puffs_node_open2 != NULL) {
416*0a6a1f1dSLionel Sambuc 				error = pops->puffs_node_open2(pu,
417*0a6a1f1dSLionel Sambuc 				    opcookie, auxt->pvnr_mode, pcr,
418*0a6a1f1dSLionel Sambuc 				    &auxt->pvnr_oflags);
419*0a6a1f1dSLionel Sambuc 
420*0a6a1f1dSLionel Sambuc 				break;
421*0a6a1f1dSLionel Sambuc 			}
422*0a6a1f1dSLionel Sambuc 
42384d9c625SLionel Sambuc 			if (pops->puffs_node_open == NULL) {
42484d9c625SLionel Sambuc 				error = 0;
42584d9c625SLionel Sambuc 				break;
42684d9c625SLionel Sambuc 			}
42784d9c625SLionel Sambuc 
42884d9c625SLionel Sambuc 			error = pops->puffs_node_open(pu,
42984d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_mode, pcr);
43084d9c625SLionel Sambuc 			break;
43184d9c625SLionel Sambuc 		}
43284d9c625SLionel Sambuc 
43384d9c625SLionel Sambuc 		case PUFFS_VN_CLOSE:
43484d9c625SLionel Sambuc 		{
43584d9c625SLionel Sambuc 			struct puffs_vnmsg_close *auxt = auxbuf;
43684d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
43784d9c625SLionel Sambuc 
43884d9c625SLionel Sambuc 			if (pops->puffs_node_close == NULL) {
43984d9c625SLionel Sambuc 				error = 0;
44084d9c625SLionel Sambuc 				break;
44184d9c625SLionel Sambuc 			}
44284d9c625SLionel Sambuc 
44384d9c625SLionel Sambuc 			error = pops->puffs_node_close(pu,
44484d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_fflag, pcr);
44584d9c625SLionel Sambuc 			break;
44684d9c625SLionel Sambuc 		}
44784d9c625SLionel Sambuc 
44884d9c625SLionel Sambuc 		case PUFFS_VN_ACCESS:
44984d9c625SLionel Sambuc 		{
45084d9c625SLionel Sambuc 			struct puffs_vnmsg_access *auxt = auxbuf;
45184d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
45284d9c625SLionel Sambuc 
45384d9c625SLionel Sambuc 			if (pops->puffs_node_access == NULL) {
45484d9c625SLionel Sambuc 				error = 0;
45584d9c625SLionel Sambuc 				break;
45684d9c625SLionel Sambuc 			}
45784d9c625SLionel Sambuc 
45884d9c625SLionel Sambuc 			error = pops->puffs_node_access(pu,
45984d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_mode, pcr);
46084d9c625SLionel Sambuc 			break;
46184d9c625SLionel Sambuc 		}
46284d9c625SLionel Sambuc 
46384d9c625SLionel Sambuc 		case PUFFS_VN_GETATTR:
46484d9c625SLionel Sambuc 		{
46584d9c625SLionel Sambuc 			struct puffs_vnmsg_getattr *auxt = auxbuf;
46684d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
46784d9c625SLionel Sambuc 
46884d9c625SLionel Sambuc 			if (PUFFS_USE_FS_TTL(pu)) {
46984d9c625SLionel Sambuc 				if (pops->puffs_node_getattr_ttl == NULL) {
47084d9c625SLionel Sambuc 					error = EOPNOTSUPP;
47184d9c625SLionel Sambuc 					break;
47284d9c625SLionel Sambuc 				}
47384d9c625SLionel Sambuc 
47484d9c625SLionel Sambuc 				error = pops->puffs_node_getattr_ttl(pu,
47584d9c625SLionel Sambuc 				    opcookie, &auxt->pvnr_va, pcr,
47684d9c625SLionel Sambuc 				    &auxt->pvnr_va_ttl);
47784d9c625SLionel Sambuc 			} else {
47884d9c625SLionel Sambuc 				if (pops->puffs_node_getattr == NULL) {
47984d9c625SLionel Sambuc 					error = EOPNOTSUPP;
48084d9c625SLionel Sambuc 					break;
48184d9c625SLionel Sambuc 				}
48284d9c625SLionel Sambuc 
48384d9c625SLionel Sambuc 				error = pops->puffs_node_getattr(pu,
48484d9c625SLionel Sambuc 				    opcookie, &auxt->pvnr_va, pcr);
48584d9c625SLionel Sambuc 			}
48684d9c625SLionel Sambuc 			break;
48784d9c625SLionel Sambuc 		}
48884d9c625SLionel Sambuc 
48984d9c625SLionel Sambuc 		case PUFFS_VN_SETATTR:
49084d9c625SLionel Sambuc 		{
49184d9c625SLionel Sambuc 			struct puffs_vnmsg_setattr *auxt = auxbuf;
49284d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
49384d9c625SLionel Sambuc 
49484d9c625SLionel Sambuc 			if (PUFFS_USE_FS_TTL(pu)) {
49584d9c625SLionel Sambuc 				int xflag = 0;
49684d9c625SLionel Sambuc 
49784d9c625SLionel Sambuc 				if (pops->puffs_node_setattr_ttl == NULL) {
49884d9c625SLionel Sambuc 					error = EOPNOTSUPP;
49984d9c625SLionel Sambuc 					break;
50084d9c625SLionel Sambuc 				}
50184d9c625SLionel Sambuc 
50284d9c625SLionel Sambuc 				if (!PUFFSOP_WANTREPLY(preq->preq_opclass))
50384d9c625SLionel Sambuc 					xflag |= PUFFS_SETATTR_FAF;
50484d9c625SLionel Sambuc 
50584d9c625SLionel Sambuc 				error = pops->puffs_node_setattr_ttl(pu,
50684d9c625SLionel Sambuc 				    opcookie, &auxt->pvnr_va, pcr,
50784d9c625SLionel Sambuc 				    &auxt->pvnr_va_ttl, xflag);
50884d9c625SLionel Sambuc 			} else {
50984d9c625SLionel Sambuc 				if (pops->puffs_node_setattr == NULL) {
51084d9c625SLionel Sambuc 					error = EOPNOTSUPP;
51184d9c625SLionel Sambuc 					break;
51284d9c625SLionel Sambuc 				}
51384d9c625SLionel Sambuc 
51484d9c625SLionel Sambuc 				error = pops->puffs_node_setattr(pu,
51584d9c625SLionel Sambuc 				    opcookie, &auxt->pvnr_va, pcr);
51684d9c625SLionel Sambuc 			}
51784d9c625SLionel Sambuc 			break;
51884d9c625SLionel Sambuc 		}
51984d9c625SLionel Sambuc 
52084d9c625SLionel Sambuc 		case PUFFS_VN_MMAP:
52184d9c625SLionel Sambuc 		{
52284d9c625SLionel Sambuc 			struct puffs_vnmsg_mmap *auxt = auxbuf;
52384d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
52484d9c625SLionel Sambuc 
52584d9c625SLionel Sambuc 			if (pops->puffs_node_mmap == NULL) {
52684d9c625SLionel Sambuc 				error = 0;
52784d9c625SLionel Sambuc 				break;
52884d9c625SLionel Sambuc 			}
52984d9c625SLionel Sambuc 
53084d9c625SLionel Sambuc 			error = pops->puffs_node_mmap(pu,
53184d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_prot, pcr);
53284d9c625SLionel Sambuc 			break;
53384d9c625SLionel Sambuc 		}
53484d9c625SLionel Sambuc 
53584d9c625SLionel Sambuc 		case PUFFS_VN_FSYNC:
53684d9c625SLionel Sambuc 		{
53784d9c625SLionel Sambuc 			struct puffs_vnmsg_fsync *auxt = auxbuf;
53884d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
53984d9c625SLionel Sambuc 
54084d9c625SLionel Sambuc 			if (pops->puffs_node_fsync == NULL) {
54184d9c625SLionel Sambuc 				error = 0;
54284d9c625SLionel Sambuc 				break;
54384d9c625SLionel Sambuc 			}
54484d9c625SLionel Sambuc 
54584d9c625SLionel Sambuc 			error = pops->puffs_node_fsync(pu, opcookie, pcr,
54684d9c625SLionel Sambuc 			    auxt->pvnr_flags, auxt->pvnr_offlo,
54784d9c625SLionel Sambuc 			    auxt->pvnr_offhi);
54884d9c625SLionel Sambuc 			break;
54984d9c625SLionel Sambuc 		}
55084d9c625SLionel Sambuc 
55184d9c625SLionel Sambuc 		case PUFFS_VN_SEEK:
55284d9c625SLionel Sambuc 		{
55384d9c625SLionel Sambuc 			struct puffs_vnmsg_seek *auxt = auxbuf;
55484d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
55584d9c625SLionel Sambuc 
55684d9c625SLionel Sambuc 			if (pops->puffs_node_seek == NULL) {
55784d9c625SLionel Sambuc 				error = 0;
55884d9c625SLionel Sambuc 				break;
55984d9c625SLionel Sambuc 			}
56084d9c625SLionel Sambuc 
56184d9c625SLionel Sambuc 			error = pops->puffs_node_seek(pu,
56284d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_oldoff,
56384d9c625SLionel Sambuc 			    auxt->pvnr_newoff, pcr);
56484d9c625SLionel Sambuc 			break;
56584d9c625SLionel Sambuc 		}
56684d9c625SLionel Sambuc 
56784d9c625SLionel Sambuc 		case PUFFS_VN_REMOVE:
56884d9c625SLionel Sambuc 		{
56984d9c625SLionel Sambuc 			struct puffs_vnmsg_remove *auxt = auxbuf;
57084d9c625SLionel Sambuc 			struct puffs_cn pcn;
57184d9c625SLionel Sambuc 			if (pops->puffs_node_remove == NULL) {
57284d9c625SLionel Sambuc 				error = 0;
57384d9c625SLionel Sambuc 				break;
57484d9c625SLionel Sambuc 			}
57584d9c625SLionel Sambuc 
57684d9c625SLionel Sambuc 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
57784d9c625SLionel Sambuc 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
57884d9c625SLionel Sambuc 
57984d9c625SLionel Sambuc 			error = pops->puffs_node_remove(pu,
58084d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_cookie_targ, &pcn);
58184d9c625SLionel Sambuc 			break;
58284d9c625SLionel Sambuc 		}
58384d9c625SLionel Sambuc 
58484d9c625SLionel Sambuc 		case PUFFS_VN_LINK:
58584d9c625SLionel Sambuc 		{
58684d9c625SLionel Sambuc 			struct puffs_vnmsg_link *auxt = auxbuf;
58784d9c625SLionel Sambuc 			struct puffs_cn pcn;
58884d9c625SLionel Sambuc 			if (pops->puffs_node_link == NULL) {
58984d9c625SLionel Sambuc 				error = 0;
59084d9c625SLionel Sambuc 				break;
59184d9c625SLionel Sambuc 			}
59284d9c625SLionel Sambuc 
59384d9c625SLionel Sambuc 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
59484d9c625SLionel Sambuc 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
59584d9c625SLionel Sambuc 
59684d9c625SLionel Sambuc 			if (buildpath) {
59784d9c625SLionel Sambuc 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
59884d9c625SLionel Sambuc 				if (error)
59984d9c625SLionel Sambuc 					break;
60084d9c625SLionel Sambuc 			}
60184d9c625SLionel Sambuc 
60284d9c625SLionel Sambuc 			error = pops->puffs_node_link(pu,
60384d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_cookie_targ, &pcn);
60484d9c625SLionel Sambuc 			if (buildpath)
60584d9c625SLionel Sambuc 				pu->pu_pathfree(pu, &pcn.pcn_po_full);
60684d9c625SLionel Sambuc 
60784d9c625SLionel Sambuc 			break;
60884d9c625SLionel Sambuc 		}
60984d9c625SLionel Sambuc 
61084d9c625SLionel Sambuc 		case PUFFS_VN_RENAME:
61184d9c625SLionel Sambuc 		{
61284d9c625SLionel Sambuc 			struct puffs_vnmsg_rename *auxt = auxbuf;
61384d9c625SLionel Sambuc 			struct puffs_cn pcn_src, pcn_targ;
61484d9c625SLionel Sambuc 			struct puffs_node *pn_src;
61584d9c625SLionel Sambuc 
61684d9c625SLionel Sambuc 			if (pops->puffs_node_rename == NULL) {
61784d9c625SLionel Sambuc 				error = 0;
61884d9c625SLionel Sambuc 				break;
61984d9c625SLionel Sambuc 			}
62084d9c625SLionel Sambuc 
62184d9c625SLionel Sambuc 			pcn_src.pcn_pkcnp = &auxt->pvnr_cn_src;
62284d9c625SLionel Sambuc 			PUFFS_KCREDTOCRED(pcn_src.pcn_cred,
62384d9c625SLionel Sambuc 			    &auxt->pvnr_cn_src_cred);
62484d9c625SLionel Sambuc 
62584d9c625SLionel Sambuc 			pcn_targ.pcn_pkcnp = &auxt->pvnr_cn_targ;
62684d9c625SLionel Sambuc 			PUFFS_KCREDTOCRED(pcn_targ.pcn_cred,
62784d9c625SLionel Sambuc 			    &auxt->pvnr_cn_targ_cred);
62884d9c625SLionel Sambuc 
62984d9c625SLionel Sambuc 			if (buildpath) {
63084d9c625SLionel Sambuc 				pn_src = auxt->pvnr_cookie_src;
63184d9c625SLionel Sambuc 				pcn_src.pcn_po_full = pn_src->pn_po;
63284d9c625SLionel Sambuc 
63384d9c625SLionel Sambuc 				error = puffs_path_pcnbuild(pu, &pcn_targ,
63484d9c625SLionel Sambuc 				    auxt->pvnr_cookie_targdir);
63584d9c625SLionel Sambuc 				if (error)
63684d9c625SLionel Sambuc 					break;
63784d9c625SLionel Sambuc 			}
63884d9c625SLionel Sambuc 
63984d9c625SLionel Sambuc 			error = pops->puffs_node_rename(pu,
64084d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_cookie_src,
64184d9c625SLionel Sambuc 			    &pcn_src, auxt->pvnr_cookie_targdir,
64284d9c625SLionel Sambuc 			    auxt->pvnr_cookie_targ, &pcn_targ);
64384d9c625SLionel Sambuc 
64484d9c625SLionel Sambuc 			if (buildpath) {
64584d9c625SLionel Sambuc 				if (error) {
64684d9c625SLionel Sambuc 					pu->pu_pathfree(pu,
64784d9c625SLionel Sambuc 					    &pcn_targ.pcn_po_full);
64884d9c625SLionel Sambuc 				} else {
64984d9c625SLionel Sambuc 					struct puffs_pathinfo pi;
65084d9c625SLionel Sambuc 					struct puffs_pathobj po_old;
65184d9c625SLionel Sambuc 
65284d9c625SLionel Sambuc 					/* handle this node */
65384d9c625SLionel Sambuc 					po_old = pn_src->pn_po;
65484d9c625SLionel Sambuc 					pn_src->pn_po = pcn_targ.pcn_po_full;
65584d9c625SLionel Sambuc 
65684d9c625SLionel Sambuc 					if (pn_src->pn_va.va_type != VDIR) {
65784d9c625SLionel Sambuc 						pu->pu_pathfree(pu, &po_old);
65884d9c625SLionel Sambuc 						break;
65984d9c625SLionel Sambuc 					}
66084d9c625SLionel Sambuc 
66184d9c625SLionel Sambuc 					/* handle all child nodes for DIRs */
66284d9c625SLionel Sambuc 					pi.pi_old = &pcn_src.pcn_po_full;
66384d9c625SLionel Sambuc 					pi.pi_new = &pcn_targ.pcn_po_full;
66484d9c625SLionel Sambuc 
66584d9c625SLionel Sambuc 					PU_LOCK();
66684d9c625SLionel Sambuc 					if (puffs_pn_nodewalk(pu,
66784d9c625SLionel Sambuc 					    puffs_path_prefixadj, &pi) != NULL)
66884d9c625SLionel Sambuc 						error = ENOMEM;
66984d9c625SLionel Sambuc 					PU_UNLOCK();
67084d9c625SLionel Sambuc 					pu->pu_pathfree(pu, &po_old);
67184d9c625SLionel Sambuc 				}
67284d9c625SLionel Sambuc 			}
67384d9c625SLionel Sambuc 			break;
67484d9c625SLionel Sambuc 		}
67584d9c625SLionel Sambuc 
67684d9c625SLionel Sambuc 		case PUFFS_VN_MKDIR:
67784d9c625SLionel Sambuc 		{
67884d9c625SLionel Sambuc 			struct puffs_vnmsg_mkdir *auxt = auxbuf;
67984d9c625SLionel Sambuc 			struct puffs_newinfo pni;
68084d9c625SLionel Sambuc 			struct puffs_cn pcn;
68184d9c625SLionel Sambuc 			struct puffs_node *pn = NULL;
68284d9c625SLionel Sambuc 
68384d9c625SLionel Sambuc 			if (pops->puffs_node_mkdir == NULL) {
68484d9c625SLionel Sambuc 				error = 0;
68584d9c625SLionel Sambuc 				break;
68684d9c625SLionel Sambuc 			}
68784d9c625SLionel Sambuc 
68884d9c625SLionel Sambuc 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
68984d9c625SLionel Sambuc 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
69084d9c625SLionel Sambuc 
69184d9c625SLionel Sambuc 			memset(&pni, 0, sizeof(pni));
69284d9c625SLionel Sambuc 			pni.pni_cookie = &auxt->pvnr_newnode;
69384d9c625SLionel Sambuc 			pni.pni_va = &auxt->pvnr_va;
69484d9c625SLionel Sambuc 			pni.pni_va_ttl = &auxt->pvnr_va_ttl;
69584d9c625SLionel Sambuc 			pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
69684d9c625SLionel Sambuc 
69784d9c625SLionel Sambuc 			if (buildpath) {
69884d9c625SLionel Sambuc 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
69984d9c625SLionel Sambuc 				if (error)
70084d9c625SLionel Sambuc 					break;
70184d9c625SLionel Sambuc 			}
70284d9c625SLionel Sambuc 
70384d9c625SLionel Sambuc 			error = pops->puffs_node_mkdir(pu,
70484d9c625SLionel Sambuc 			    opcookie, &pni, &pcn, &auxt->pvnr_va);
70584d9c625SLionel Sambuc 
70684d9c625SLionel Sambuc 			if (buildpath) {
70784d9c625SLionel Sambuc 				if (error) {
70884d9c625SLionel Sambuc 					pu->pu_pathfree(pu, &pcn.pcn_po_full);
70984d9c625SLionel Sambuc 				} else {
71084d9c625SLionel Sambuc 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
71184d9c625SLionel Sambuc 					pn->pn_po = pcn.pcn_po_full;
71284d9c625SLionel Sambuc 				}
71384d9c625SLionel Sambuc 			}
71484d9c625SLionel Sambuc 
71584d9c625SLionel Sambuc 			if (pncookie && !error) {
71684d9c625SLionel Sambuc 				if (pn == NULL)
71784d9c625SLionel Sambuc 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
71884d9c625SLionel Sambuc 				pn->pn_nlookup++;
71984d9c625SLionel Sambuc 			}
72084d9c625SLionel Sambuc 			break;
72184d9c625SLionel Sambuc 		}
72284d9c625SLionel Sambuc 
72384d9c625SLionel Sambuc 		case PUFFS_VN_RMDIR:
72484d9c625SLionel Sambuc 		{
72584d9c625SLionel Sambuc 			struct puffs_vnmsg_rmdir *auxt = auxbuf;
72684d9c625SLionel Sambuc 			struct puffs_cn pcn;
72784d9c625SLionel Sambuc 			if (pops->puffs_node_rmdir == NULL) {
72884d9c625SLionel Sambuc 				error = 0;
72984d9c625SLionel Sambuc 				break;
73084d9c625SLionel Sambuc 			}
73184d9c625SLionel Sambuc 
73284d9c625SLionel Sambuc 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
73384d9c625SLionel Sambuc 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
73484d9c625SLionel Sambuc 
73584d9c625SLionel Sambuc 			error = pops->puffs_node_rmdir(pu,
73684d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_cookie_targ, &pcn);
73784d9c625SLionel Sambuc 			break;
73884d9c625SLionel Sambuc 		}
73984d9c625SLionel Sambuc 
74084d9c625SLionel Sambuc 		case PUFFS_VN_SYMLINK:
74184d9c625SLionel Sambuc 		{
74284d9c625SLionel Sambuc 			struct puffs_vnmsg_symlink *auxt = auxbuf;
74384d9c625SLionel Sambuc 			struct puffs_newinfo pni;
74484d9c625SLionel Sambuc 			struct puffs_cn pcn;
74584d9c625SLionel Sambuc 			struct puffs_node *pn = NULL;
74684d9c625SLionel Sambuc 
74784d9c625SLionel Sambuc 			if (pops->puffs_node_symlink == NULL) {
74884d9c625SLionel Sambuc 				error = 0;
74984d9c625SLionel Sambuc 				break;
75084d9c625SLionel Sambuc 			}
75184d9c625SLionel Sambuc 
75284d9c625SLionel Sambuc 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
75384d9c625SLionel Sambuc 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
75484d9c625SLionel Sambuc 
75584d9c625SLionel Sambuc 			memset(&pni, 0, sizeof(pni));
75684d9c625SLionel Sambuc 			pni.pni_cookie = &auxt->pvnr_newnode;
75784d9c625SLionel Sambuc 			pni.pni_va = &auxt->pvnr_va;
75884d9c625SLionel Sambuc 			pni.pni_va_ttl = &auxt->pvnr_va_ttl;
75984d9c625SLionel Sambuc 			pni.pni_cn_ttl = &auxt->pvnr_cn_ttl;
76084d9c625SLionel Sambuc 
76184d9c625SLionel Sambuc 			if (buildpath) {
76284d9c625SLionel Sambuc 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
76384d9c625SLionel Sambuc 				if (error)
76484d9c625SLionel Sambuc 					break;
76584d9c625SLionel Sambuc 			}
76684d9c625SLionel Sambuc 
76784d9c625SLionel Sambuc 			error = pops->puffs_node_symlink(pu,
76884d9c625SLionel Sambuc 			    opcookie, &pni, &pcn,
76984d9c625SLionel Sambuc 			    &auxt->pvnr_va, auxt->pvnr_link);
77084d9c625SLionel Sambuc 
77184d9c625SLionel Sambuc 			if (buildpath) {
77284d9c625SLionel Sambuc 				if (error) {
77384d9c625SLionel Sambuc 					pu->pu_pathfree(pu, &pcn.pcn_po_full);
77484d9c625SLionel Sambuc 				} else {
77584d9c625SLionel Sambuc 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
77684d9c625SLionel Sambuc 					pn->pn_po = pcn.pcn_po_full;
77784d9c625SLionel Sambuc 				}
77884d9c625SLionel Sambuc 			}
77984d9c625SLionel Sambuc 
78084d9c625SLionel Sambuc 			if (pncookie && !error) {
78184d9c625SLionel Sambuc 				if (pn == NULL)
78284d9c625SLionel Sambuc 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
78384d9c625SLionel Sambuc 				pn->pn_nlookup++;
78484d9c625SLionel Sambuc 			}
78584d9c625SLionel Sambuc 			break;
78684d9c625SLionel Sambuc 		}
78784d9c625SLionel Sambuc 
78884d9c625SLionel Sambuc 		case PUFFS_VN_READDIR:
78984d9c625SLionel Sambuc 		{
79084d9c625SLionel Sambuc 			struct puffs_vnmsg_readdir *auxt = auxbuf;
79184d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
79284d9c625SLionel Sambuc 			struct dirent *dent;
79384d9c625SLionel Sambuc 			off_t *cookies;
79484d9c625SLionel Sambuc 			size_t res, origcookies;
79584d9c625SLionel Sambuc 
79684d9c625SLionel Sambuc 			if (pops->puffs_node_readdir == NULL) {
79784d9c625SLionel Sambuc 				error = 0;
79884d9c625SLionel Sambuc 				break;
79984d9c625SLionel Sambuc 			}
80084d9c625SLionel Sambuc 
80184d9c625SLionel Sambuc 			if (auxt->pvnr_ncookies) {
80284d9c625SLionel Sambuc 				/* LINTED: pvnr_data is __aligned() */
80384d9c625SLionel Sambuc 				cookies = (off_t *)auxt->pvnr_data;
80484d9c625SLionel Sambuc 				origcookies = auxt->pvnr_ncookies;
80584d9c625SLionel Sambuc 			} else {
80684d9c625SLionel Sambuc 				cookies = NULL;
80784d9c625SLionel Sambuc 				origcookies = 0;
80884d9c625SLionel Sambuc 			}
80984d9c625SLionel Sambuc 			/* LINTED: dentoff is aligned in the kernel */
81084d9c625SLionel Sambuc 			dent = (struct dirent *)
81184d9c625SLionel Sambuc 			    (auxt->pvnr_data + auxt->pvnr_dentoff);
81284d9c625SLionel Sambuc 
81384d9c625SLionel Sambuc 			res = auxt->pvnr_resid;
81484d9c625SLionel Sambuc 			error = pops->puffs_node_readdir(pu,
81584d9c625SLionel Sambuc 			    opcookie, dent, &auxt->pvnr_offset,
81684d9c625SLionel Sambuc 			    &auxt->pvnr_resid, pcr, &auxt->pvnr_eofflag,
81784d9c625SLionel Sambuc 			    cookies, &auxt->pvnr_ncookies);
81884d9c625SLionel Sambuc 
81984d9c625SLionel Sambuc 			/* much easier to track non-working NFS */
82084d9c625SLionel Sambuc 			assert(auxt->pvnr_ncookies <= origcookies);
82184d9c625SLionel Sambuc 
82284d9c625SLionel Sambuc 			/* need to move a bit more */
82384d9c625SLionel Sambuc 			preq->preq_buflen = sizeof(struct puffs_vnmsg_readdir)
82484d9c625SLionel Sambuc 			    + auxt->pvnr_dentoff + (res - auxt->pvnr_resid);
82584d9c625SLionel Sambuc 			break;
82684d9c625SLionel Sambuc 		}
82784d9c625SLionel Sambuc 
82884d9c625SLionel Sambuc 		case PUFFS_VN_READLINK:
82984d9c625SLionel Sambuc 		{
83084d9c625SLionel Sambuc 			struct puffs_vnmsg_readlink *auxt = auxbuf;
83184d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
83284d9c625SLionel Sambuc 
83384d9c625SLionel Sambuc 			if (pops->puffs_node_readlink == NULL) {
83484d9c625SLionel Sambuc 				error = EOPNOTSUPP;
83584d9c625SLionel Sambuc 				break;
83684d9c625SLionel Sambuc 			}
83784d9c625SLionel Sambuc 
83884d9c625SLionel Sambuc 			/*LINTED*/
83984d9c625SLionel Sambuc 			error = pops->puffs_node_readlink(pu, opcookie, pcr,
84084d9c625SLionel Sambuc 			    auxt->pvnr_link, &auxt->pvnr_linklen);
84184d9c625SLionel Sambuc 			break;
84284d9c625SLionel Sambuc 		}
84384d9c625SLionel Sambuc 
84484d9c625SLionel Sambuc 		case PUFFS_VN_RECLAIM:
84584d9c625SLionel Sambuc 		{
84684d9c625SLionel Sambuc 			struct puffs_vnmsg_reclaim *auxt = auxbuf;
84784d9c625SLionel Sambuc 			struct puffs_node *pn;
84884d9c625SLionel Sambuc 
84984d9c625SLionel Sambuc 			if (pops->puffs_node_reclaim2 != NULL) {
85084d9c625SLionel Sambuc 				error = pops->puffs_node_reclaim2(pu, opcookie,
85184d9c625SLionel Sambuc 					     auxt->pvnr_nlookup);
85284d9c625SLionel Sambuc 				break;
85384d9c625SLionel Sambuc 			}
85484d9c625SLionel Sambuc 
85584d9c625SLionel Sambuc 			if (pops->puffs_node_reclaim == NULL) {
85684d9c625SLionel Sambuc 				error = 0;
85784d9c625SLionel Sambuc 				break;
85884d9c625SLionel Sambuc 			}
85984d9c625SLionel Sambuc 
86084d9c625SLionel Sambuc 			/*
86184d9c625SLionel Sambuc 			 * This fixes a race condition,
86284d9c625SLionel Sambuc 			 * where a node in reclaimed by kernel
86384d9c625SLionel Sambuc 			 * after a lookup request is sent,
86484d9c625SLionel Sambuc 			 * but before the reply, leaving the kernel
86584d9c625SLionel Sambuc 			 * with a invalid vnode/cookie reference.
86684d9c625SLionel Sambuc 			 */
86784d9c625SLionel Sambuc 			if (pncookie) {
86884d9c625SLionel Sambuc 				pn = PU_CMAP(pu, opcookie);
86984d9c625SLionel Sambuc 				pn->pn_nlookup -= auxt->pvnr_nlookup;
87084d9c625SLionel Sambuc 				if (pn->pn_nlookup >= 1) {
87184d9c625SLionel Sambuc 					error = 0;
87284d9c625SLionel Sambuc 					break;
87384d9c625SLionel Sambuc 				}
87484d9c625SLionel Sambuc 			}
87584d9c625SLionel Sambuc 
87684d9c625SLionel Sambuc 			error = pops->puffs_node_reclaim(pu, opcookie);
87784d9c625SLionel Sambuc 			break;
87884d9c625SLionel Sambuc 		}
87984d9c625SLionel Sambuc 
88084d9c625SLionel Sambuc 		case PUFFS_VN_INACTIVE:
88184d9c625SLionel Sambuc 		{
88284d9c625SLionel Sambuc 
88384d9c625SLionel Sambuc 			if (pops->puffs_node_inactive == NULL) {
88484d9c625SLionel Sambuc 				error = EOPNOTSUPP;
88584d9c625SLionel Sambuc 				break;
88684d9c625SLionel Sambuc 			}
88784d9c625SLionel Sambuc 
88884d9c625SLionel Sambuc 			error = pops->puffs_node_inactive(pu, opcookie);
88984d9c625SLionel Sambuc 			break;
89084d9c625SLionel Sambuc 		}
89184d9c625SLionel Sambuc 
89284d9c625SLionel Sambuc 		case PUFFS_VN_PATHCONF:
89384d9c625SLionel Sambuc 		{
89484d9c625SLionel Sambuc 			struct puffs_vnmsg_pathconf *auxt = auxbuf;
89584d9c625SLionel Sambuc 			if (pops->puffs_node_pathconf == NULL) {
89684d9c625SLionel Sambuc 				error = 0;
89784d9c625SLionel Sambuc 				break;
89884d9c625SLionel Sambuc 			}
89984d9c625SLionel Sambuc 
90084d9c625SLionel Sambuc 			error = pops->puffs_node_pathconf(pu,
90184d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_name,
90284d9c625SLionel Sambuc 			    &auxt->pvnr_retval);
90384d9c625SLionel Sambuc 			break;
90484d9c625SLionel Sambuc 		}
90584d9c625SLionel Sambuc 
90684d9c625SLionel Sambuc 		case PUFFS_VN_ADVLOCK:
90784d9c625SLionel Sambuc 		{
90884d9c625SLionel Sambuc 			struct puffs_vnmsg_advlock *auxt = auxbuf;
90984d9c625SLionel Sambuc 			if (pops->puffs_node_advlock == NULL) {
91084d9c625SLionel Sambuc 				error = 0;
91184d9c625SLionel Sambuc 				break;
91284d9c625SLionel Sambuc 			}
91384d9c625SLionel Sambuc 
91484d9c625SLionel Sambuc 			error = pops->puffs_node_advlock(pu,
91584d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_id, auxt->pvnr_op,
91684d9c625SLionel Sambuc 			    &auxt->pvnr_fl, auxt->pvnr_flags);
91784d9c625SLionel Sambuc 			break;
91884d9c625SLionel Sambuc 		}
91984d9c625SLionel Sambuc 
92084d9c625SLionel Sambuc 		case PUFFS_VN_PRINT:
92184d9c625SLionel Sambuc 		{
92284d9c625SLionel Sambuc 			if (pops->puffs_node_print == NULL) {
92384d9c625SLionel Sambuc 				error = 0;
92484d9c625SLionel Sambuc 				break;
92584d9c625SLionel Sambuc 			}
92684d9c625SLionel Sambuc 
92784d9c625SLionel Sambuc 			error = pops->puffs_node_print(pu,
92884d9c625SLionel Sambuc 			    opcookie);
92984d9c625SLionel Sambuc 			break;
93084d9c625SLionel Sambuc 		}
93184d9c625SLionel Sambuc 
93284d9c625SLionel Sambuc 		case PUFFS_VN_ABORTOP:
93384d9c625SLionel Sambuc 		{
93484d9c625SLionel Sambuc 			struct puffs_vnmsg_abortop *auxt = auxbuf;
93584d9c625SLionel Sambuc 			struct puffs_cn pcn;
93684d9c625SLionel Sambuc 
93784d9c625SLionel Sambuc 			if (pops->puffs_node_abortop == NULL) {
93884d9c625SLionel Sambuc 				error = 0;
93984d9c625SLionel Sambuc 				break;
94084d9c625SLionel Sambuc 			}
94184d9c625SLionel Sambuc 
94284d9c625SLionel Sambuc 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
94384d9c625SLionel Sambuc 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
94484d9c625SLionel Sambuc 
94584d9c625SLionel Sambuc 			error = pops->puffs_node_abortop(pu, opcookie, &pcn);
94684d9c625SLionel Sambuc 
94784d9c625SLionel Sambuc 			break;
94884d9c625SLionel Sambuc 		}
94984d9c625SLionel Sambuc 
95084d9c625SLionel Sambuc 		case PUFFS_VN_READ:
95184d9c625SLionel Sambuc 		{
95284d9c625SLionel Sambuc 			struct puffs_vnmsg_read *auxt = auxbuf;
95384d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
95484d9c625SLionel Sambuc 			size_t res;
95584d9c625SLionel Sambuc 
95684d9c625SLionel Sambuc 			if (pops->puffs_node_read == NULL) {
95784d9c625SLionel Sambuc 				error = EIO;
95884d9c625SLionel Sambuc 				break;
95984d9c625SLionel Sambuc 			}
96084d9c625SLionel Sambuc 
96184d9c625SLionel Sambuc 			res = auxt->pvnr_resid;
96284d9c625SLionel Sambuc 			error = pops->puffs_node_read(pu,
96384d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_data,
96484d9c625SLionel Sambuc 			    auxt->pvnr_offset, &auxt->pvnr_resid,
96584d9c625SLionel Sambuc 			    pcr, auxt->pvnr_ioflag);
96684d9c625SLionel Sambuc 
96784d9c625SLionel Sambuc 			/* need to move a bit more */
96884d9c625SLionel Sambuc 			preq->preq_buflen = sizeof(struct puffs_vnmsg_read)
96984d9c625SLionel Sambuc 			    + (res - auxt->pvnr_resid);
97084d9c625SLionel Sambuc 			break;
97184d9c625SLionel Sambuc 		}
97284d9c625SLionel Sambuc 
97384d9c625SLionel Sambuc 		case PUFFS_VN_WRITE:
97484d9c625SLionel Sambuc 		{
97584d9c625SLionel Sambuc 			struct puffs_vnmsg_write *auxt = auxbuf;
97684d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
97784d9c625SLionel Sambuc 
97884d9c625SLionel Sambuc 			if (pops->puffs_node_write2 != NULL) {
97984d9c625SLionel Sambuc 				int xflag = 0;
98084d9c625SLionel Sambuc 
98184d9c625SLionel Sambuc 				if (!PUFFSOP_WANTREPLY(preq->preq_opclass))
98284d9c625SLionel Sambuc 					xflag |= PUFFS_SETATTR_FAF;
98384d9c625SLionel Sambuc 
98484d9c625SLionel Sambuc 				error = pops->puffs_node_write2(pu,
98584d9c625SLionel Sambuc 				    opcookie, auxt->pvnr_data,
98684d9c625SLionel Sambuc 				    auxt->pvnr_offset, &auxt->pvnr_resid,
98784d9c625SLionel Sambuc 				    pcr, auxt->pvnr_ioflag, xflag);
98884d9c625SLionel Sambuc 
98984d9c625SLionel Sambuc 			} else if (pops->puffs_node_write != NULL) {
99084d9c625SLionel Sambuc 				error = pops->puffs_node_write(pu,
99184d9c625SLionel Sambuc 				    opcookie, auxt->pvnr_data,
99284d9c625SLionel Sambuc 				    auxt->pvnr_offset, &auxt->pvnr_resid,
99384d9c625SLionel Sambuc 				    pcr, auxt->pvnr_ioflag);
99484d9c625SLionel Sambuc 			} else {
99584d9c625SLionel Sambuc 				error = EIO;
99684d9c625SLionel Sambuc 				break;
99784d9c625SLionel Sambuc 			}
99884d9c625SLionel Sambuc 
99984d9c625SLionel Sambuc 
100084d9c625SLionel Sambuc 			/* don't need to move data back to the kernel */
100184d9c625SLionel Sambuc 			preq->preq_buflen = sizeof(struct puffs_vnmsg_write);
100284d9c625SLionel Sambuc 			break;
100384d9c625SLionel Sambuc 		}
100484d9c625SLionel Sambuc 
100584d9c625SLionel Sambuc 		case PUFFS_VN_POLL:
100684d9c625SLionel Sambuc 		{
100784d9c625SLionel Sambuc 			struct puffs_vnmsg_poll *auxt = auxbuf;
100884d9c625SLionel Sambuc 
100984d9c625SLionel Sambuc 			if (pops->puffs_node_poll == NULL) {
101084d9c625SLionel Sambuc 				error = 0;
101184d9c625SLionel Sambuc 
101284d9c625SLionel Sambuc 				/* emulate genfs_poll() */
101384d9c625SLionel Sambuc 				auxt->pvnr_events &= (POLLIN | POLLOUT
101484d9c625SLionel Sambuc 						    | POLLRDNORM | POLLWRNORM);
101584d9c625SLionel Sambuc 
101684d9c625SLionel Sambuc 				break;
101784d9c625SLionel Sambuc 			}
101884d9c625SLionel Sambuc 
101984d9c625SLionel Sambuc 			error = pops->puffs_node_poll(pu,
102084d9c625SLionel Sambuc 			    opcookie, &auxt->pvnr_events);
102184d9c625SLionel Sambuc 			break;
102284d9c625SLionel Sambuc 		}
102384d9c625SLionel Sambuc 
102484d9c625SLionel Sambuc 		case PUFFS_VN_GETEXTATTR:
102584d9c625SLionel Sambuc 		{
102684d9c625SLionel Sambuc 			struct puffs_vnmsg_getextattr *auxt = auxbuf;
102784d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
102884d9c625SLionel Sambuc 			size_t res, *resp, *sizep;
102984d9c625SLionel Sambuc 			uint8_t *data;
103084d9c625SLionel Sambuc 
103184d9c625SLionel Sambuc 			if (pops->puffs_node_getextattr == NULL) {
103284d9c625SLionel Sambuc 				error = EOPNOTSUPP;
103384d9c625SLionel Sambuc 				break;
103484d9c625SLionel Sambuc 			}
103584d9c625SLionel Sambuc 
103684d9c625SLionel Sambuc 			if (auxt->pvnr_datasize)
103784d9c625SLionel Sambuc 				sizep = &auxt->pvnr_datasize;
103884d9c625SLionel Sambuc 			else
103984d9c625SLionel Sambuc 				sizep = NULL;
104084d9c625SLionel Sambuc 
104184d9c625SLionel Sambuc 			res = auxt->pvnr_resid;
104284d9c625SLionel Sambuc 			if (res > 0) {
104384d9c625SLionel Sambuc 				data = auxt->pvnr_data;
104484d9c625SLionel Sambuc 				resp = &auxt->pvnr_resid;
104584d9c625SLionel Sambuc 			} else {
104684d9c625SLionel Sambuc 				data = NULL;
104784d9c625SLionel Sambuc 				resp = NULL;
104884d9c625SLionel Sambuc 			}
104984d9c625SLionel Sambuc 
105084d9c625SLionel Sambuc 			error = pops->puffs_node_getextattr(pu,
105184d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_attrnamespace,
105284d9c625SLionel Sambuc 			    auxt->pvnr_attrname, sizep, data, resp, pcr);
105384d9c625SLionel Sambuc 
105484d9c625SLionel Sambuc 			/* need to move a bit more? */
105584d9c625SLionel Sambuc 			preq->preq_buflen =
105684d9c625SLionel Sambuc 			    sizeof(struct puffs_vnmsg_getextattr)
105784d9c625SLionel Sambuc 			    + (res - auxt->pvnr_resid);
105884d9c625SLionel Sambuc 			break;
105984d9c625SLionel Sambuc 		}
106084d9c625SLionel Sambuc 
106184d9c625SLionel Sambuc 		case PUFFS_VN_SETEXTATTR:
106284d9c625SLionel Sambuc 		{
106384d9c625SLionel Sambuc 			struct puffs_vnmsg_setextattr *auxt = auxbuf;
106484d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
106584d9c625SLionel Sambuc 			size_t *resp;
106684d9c625SLionel Sambuc 			uint8_t *data;
106784d9c625SLionel Sambuc 
106884d9c625SLionel Sambuc 			if (pops->puffs_node_setextattr == NULL) {
106984d9c625SLionel Sambuc 				error = EOPNOTSUPP;
107084d9c625SLionel Sambuc 				break;
107184d9c625SLionel Sambuc 			}
107284d9c625SLionel Sambuc 
107384d9c625SLionel Sambuc 			if (auxt->pvnr_resid > 0) {
107484d9c625SLionel Sambuc 				data = auxt->pvnr_data;
107584d9c625SLionel Sambuc 				resp = &auxt->pvnr_resid;
107684d9c625SLionel Sambuc 			} else {
107784d9c625SLionel Sambuc 				data = NULL;
107884d9c625SLionel Sambuc 				resp = NULL;
107984d9c625SLionel Sambuc 			}
108084d9c625SLionel Sambuc 
108184d9c625SLionel Sambuc 			error = pops->puffs_node_setextattr(pu,
108284d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_attrnamespace,
108384d9c625SLionel Sambuc 			    auxt->pvnr_attrname, data, resp, pcr);
108484d9c625SLionel Sambuc 			break;
108584d9c625SLionel Sambuc 		}
108684d9c625SLionel Sambuc 
108784d9c625SLionel Sambuc 		case PUFFS_VN_LISTEXTATTR:
108884d9c625SLionel Sambuc 		{
108984d9c625SLionel Sambuc 			struct puffs_vnmsg_listextattr *auxt = auxbuf;
109084d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
109184d9c625SLionel Sambuc 			size_t res, *resp, *sizep;
109284d9c625SLionel Sambuc 			int flag;
109384d9c625SLionel Sambuc 			uint8_t *data;
109484d9c625SLionel Sambuc 
109584d9c625SLionel Sambuc 			if (pops->puffs_node_listextattr == NULL) {
109684d9c625SLionel Sambuc 				error = EOPNOTSUPP;
109784d9c625SLionel Sambuc 				break;
109884d9c625SLionel Sambuc 			}
109984d9c625SLionel Sambuc 
110084d9c625SLionel Sambuc 			if (auxt->pvnr_datasize)
110184d9c625SLionel Sambuc 				sizep = &auxt->pvnr_datasize;
110284d9c625SLionel Sambuc 			else
110384d9c625SLionel Sambuc 				sizep = NULL;
110484d9c625SLionel Sambuc 
110584d9c625SLionel Sambuc 			res = auxt->pvnr_resid;
110684d9c625SLionel Sambuc 			if (res > 0) {
110784d9c625SLionel Sambuc 				data = auxt->pvnr_data;
110884d9c625SLionel Sambuc 				resp = &auxt->pvnr_resid;
110984d9c625SLionel Sambuc 			} else {
111084d9c625SLionel Sambuc 				data = NULL;
111184d9c625SLionel Sambuc 				resp = NULL;
111284d9c625SLionel Sambuc 			}
111384d9c625SLionel Sambuc 
111484d9c625SLionel Sambuc 			res = auxt->pvnr_resid;
111584d9c625SLionel Sambuc 			flag = auxt->pvnr_flag;
111684d9c625SLionel Sambuc 			error = pops->puffs_node_listextattr(pu,
111784d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_attrnamespace,
111884d9c625SLionel Sambuc 			    sizep, data, resp, flag, pcr);
111984d9c625SLionel Sambuc 
112084d9c625SLionel Sambuc 			/* need to move a bit more? */
112184d9c625SLionel Sambuc 			preq->preq_buflen =
112284d9c625SLionel Sambuc 			    sizeof(struct puffs_vnmsg_listextattr)
112384d9c625SLionel Sambuc 			    + (res - auxt->pvnr_resid);
112484d9c625SLionel Sambuc 			break;
112584d9c625SLionel Sambuc 		}
112684d9c625SLionel Sambuc 
112784d9c625SLionel Sambuc 		case PUFFS_VN_DELETEEXTATTR:
112884d9c625SLionel Sambuc 		{
112984d9c625SLionel Sambuc 			struct puffs_vnmsg_deleteextattr *auxt = auxbuf;
113084d9c625SLionel Sambuc 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
113184d9c625SLionel Sambuc 
113284d9c625SLionel Sambuc 			if (pops->puffs_node_deleteextattr == NULL) {
113384d9c625SLionel Sambuc 				error = EOPNOTSUPP;
113484d9c625SLionel Sambuc 				break;
113584d9c625SLionel Sambuc 			}
113684d9c625SLionel Sambuc 
113784d9c625SLionel Sambuc 			error = pops->puffs_node_deleteextattr(pu,
113884d9c625SLionel Sambuc 			    opcookie, auxt->pvnr_attrnamespace,
113984d9c625SLionel Sambuc 			    auxt->pvnr_attrname, pcr);
114084d9c625SLionel Sambuc 			break;
114184d9c625SLionel Sambuc 		}
114284d9c625SLionel Sambuc 
1143*0a6a1f1dSLionel Sambuc 		case PUFFS_VN_FALLOCATE:
1144*0a6a1f1dSLionel Sambuc 		{
1145*0a6a1f1dSLionel Sambuc 			struct puffs_vnmsg_fallocate *auxt = auxbuf;
1146*0a6a1f1dSLionel Sambuc 
1147*0a6a1f1dSLionel Sambuc 			if (pops->puffs_node_fallocate == NULL) {
1148*0a6a1f1dSLionel Sambuc 				error = EOPNOTSUPP;
1149*0a6a1f1dSLionel Sambuc 				break;
1150*0a6a1f1dSLionel Sambuc 			}
1151*0a6a1f1dSLionel Sambuc 
1152*0a6a1f1dSLionel Sambuc 			error = pops->puffs_node_fallocate(pu,
1153*0a6a1f1dSLionel Sambuc 			    opcookie, auxt->pvnr_off, auxt->pvnr_len);
1154*0a6a1f1dSLionel Sambuc 			break;
1155*0a6a1f1dSLionel Sambuc 		}
1156*0a6a1f1dSLionel Sambuc 
1157*0a6a1f1dSLionel Sambuc 		case PUFFS_VN_FDISCARD:
1158*0a6a1f1dSLionel Sambuc 		{
1159*0a6a1f1dSLionel Sambuc 			struct puffs_vnmsg_fdiscard *auxt = auxbuf;
1160*0a6a1f1dSLionel Sambuc 
1161*0a6a1f1dSLionel Sambuc 			if (pops->puffs_node_fdiscard == NULL) {
1162*0a6a1f1dSLionel Sambuc 				error = EOPNOTSUPP;
1163*0a6a1f1dSLionel Sambuc 				break;
1164*0a6a1f1dSLionel Sambuc 			}
1165*0a6a1f1dSLionel Sambuc 
1166*0a6a1f1dSLionel Sambuc 			error = pops->puffs_node_fdiscard(pu,
1167*0a6a1f1dSLionel Sambuc 			    opcookie, auxt->pvnr_off, auxt->pvnr_len);
1168*0a6a1f1dSLionel Sambuc 			break;
1169*0a6a1f1dSLionel Sambuc 		}
1170*0a6a1f1dSLionel Sambuc 
117184d9c625SLionel Sambuc 		default:
117284d9c625SLionel Sambuc 			printf("inval op %d\n", preq->preq_optype);
117384d9c625SLionel Sambuc 			error = EINVAL;
117484d9c625SLionel Sambuc 			break;
117584d9c625SLionel Sambuc 		}
117684d9c625SLionel Sambuc 
117784d9c625SLionel Sambuc #if 0
117884d9c625SLionel Sambuc 	/* not issued by kernel currently */
117984d9c625SLionel Sambuc 	} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_CACHE) {
118084d9c625SLionel Sambuc 		struct puffs_cacheinfo *pci = (void *)preq;
118184d9c625SLionel Sambuc 
118284d9c625SLionel Sambuc 		if (pu->pu_ops.puffs_cache_write) {
118384d9c625SLionel Sambuc 			pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie,
118484d9c625SLionel Sambuc 			    pci->pcache_nruns, pci->pcache_runs);
118584d9c625SLionel Sambuc 		}
118684d9c625SLionel Sambuc 		error = 0;
118784d9c625SLionel Sambuc #endif
118884d9c625SLionel Sambuc 
118984d9c625SLionel Sambuc 	} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_ERROR) {
119084d9c625SLionel Sambuc 		struct puffs_error *perr = (void *)preq;
119184d9c625SLionel Sambuc 
119284d9c625SLionel Sambuc 		pu->pu_errnotify(pu, preq->preq_optype,
119384d9c625SLionel Sambuc 		    perr->perr_error, perr->perr_str, preq->preq_cookie);
119484d9c625SLionel Sambuc 		error = 0;
119584d9c625SLionel Sambuc 	} else {
119684d9c625SLionel Sambuc 		/*
119784d9c625SLionel Sambuc 		 * I guess the kernel sees this one coming also
119884d9c625SLionel Sambuc 		 */
119984d9c625SLionel Sambuc 		error = EINVAL;
120084d9c625SLionel Sambuc 	}
120184d9c625SLionel Sambuc 
120284d9c625SLionel Sambuc  out:
120384d9c625SLionel Sambuc 	preq->preq_rv = error;
120484d9c625SLionel Sambuc 
120584d9c625SLionel Sambuc 	if (pu->pu_oppost)
120684d9c625SLionel Sambuc 		pu->pu_oppost(pu);
120784d9c625SLionel Sambuc 
120884d9c625SLionel Sambuc 	pcc->pcc_flags |= PCC_DONE;
120984d9c625SLionel Sambuc }
1210