Home | History | Annotate | Line # | Download | only in libpuffs
dispatcher.c revision 1.36.2.1
      1  1.36.2.1   yamt /*	$NetBSD: dispatcher.c,v 1.36.2.1 2012/04/17 00:05:31 yamt Exp $	*/
      2       1.1  pooka 
      3       1.1  pooka /*
      4      1.30  pooka  * Copyright (c) 2006, 2007, 2008 Antti Kantee.  All Rights Reserved.
      5       1.1  pooka  *
      6       1.1  pooka  * Development of this software was supported by the
      7      1.30  pooka  * Ulla Tuominen Foundation, the Finnish Cultural Foundation and
      8      1.30  pooka  * Research Foundation of Helsinki University of Technology.
      9       1.1  pooka  *
     10       1.1  pooka  * Redistribution and use in source and binary forms, with or without
     11       1.1  pooka  * modification, are permitted provided that the following conditions
     12       1.1  pooka  * are met:
     13       1.1  pooka  * 1. Redistributions of source code must retain the above copyright
     14       1.1  pooka  *    notice, this list of conditions and the following disclaimer.
     15       1.1  pooka  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1  pooka  *    notice, this list of conditions and the following disclaimer in the
     17       1.1  pooka  *    documentation and/or other materials provided with the distribution.
     18       1.1  pooka  *
     19       1.1  pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     20       1.1  pooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21       1.1  pooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22       1.1  pooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     23       1.1  pooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24       1.1  pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     25       1.1  pooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26       1.1  pooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27       1.1  pooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28       1.1  pooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29       1.1  pooka  * SUCH DAMAGE.
     30       1.1  pooka  */
     31       1.1  pooka 
     32       1.1  pooka #include <sys/cdefs.h>
     33       1.1  pooka #if !defined(lint)
     34  1.36.2.1   yamt __RCSID("$NetBSD: dispatcher.c,v 1.36.2.1 2012/04/17 00:05:31 yamt Exp $");
     35       1.1  pooka #endif /* !lint */
     36       1.1  pooka 
     37       1.1  pooka #include <sys/types.h>
     38       1.4  pooka #include <sys/poll.h>
     39       1.1  pooka 
     40       1.1  pooka #include <assert.h>
     41       1.1  pooka #include <errno.h>
     42      1.17  pooka #include <pthread.h>
     43       1.1  pooka #include <puffs.h>
     44       1.1  pooka #include <puffsdump.h>
     45       1.1  pooka #include <stdio.h>
     46       1.1  pooka #include <stdlib.h>
     47       1.1  pooka #include <unistd.h>
     48       1.1  pooka 
     49       1.1  pooka #include "puffs_priv.h"
     50       1.1  pooka 
     51  1.36.2.1   yamt #define PUFFS_USE_FS_TTL(pu) (pu->pu_flags & PUFFS_KFLAG_CACHE_FS_TTL)
     52  1.36.2.1   yamt 
     53      1.30  pooka static void dispatch(struct puffs_cc *);
     54      1.17  pooka 
     55  1.36.2.1   yamt static void
     56  1.36.2.1   yamt update_fs_ttl(struct puffs_usermount *pu, puffs_cookie_t opc,
     57  1.36.2.1   yamt 	      struct vattr *rvap,
     58  1.36.2.1   yamt 	      struct timespec *va_ttl, struct timespec *cn_ttl)
     59  1.36.2.1   yamt {
     60  1.36.2.1   yamt 	struct puffs_node *pn = NULL;
     61  1.36.2.1   yamt 
     62  1.36.2.1   yamt 	pn = PU_CMAP(pu, opc);
     63  1.36.2.1   yamt 
     64  1.36.2.1   yamt 	(void)memcpy(rvap, &pn->pn_va, sizeof(*rvap));
     65  1.36.2.1   yamt 
     66  1.36.2.1   yamt 	va_ttl->tv_sec =  pn->pn_va_ttl.tv_sec;
     67  1.36.2.1   yamt 	va_ttl->tv_nsec =  pn->pn_va_ttl.tv_nsec;
     68  1.36.2.1   yamt 
     69  1.36.2.1   yamt 	if (cn_ttl != NULL) {
     70  1.36.2.1   yamt 		cn_ttl->tv_sec =  pn->pn_cn_ttl.tv_sec;
     71  1.36.2.1   yamt 		cn_ttl->tv_nsec =  pn->pn_cn_ttl.tv_nsec;
     72  1.36.2.1   yamt 	}
     73  1.36.2.1   yamt }
     74  1.36.2.1   yamt 
     75      1.30  pooka /* for our eyes only */
     76      1.30  pooka void
     77      1.30  pooka puffs__ml_dispatch(struct puffs_usermount *pu, struct puffs_framebuf *pb)
     78      1.30  pooka {
     79      1.30  pooka 	struct puffs_cc *pcc = puffs_cc_getcc(pu);
     80      1.30  pooka 	struct puffs_req *preq;
     81      1.17  pooka 
     82      1.30  pooka 	pcc->pcc_pb = pb;
     83      1.30  pooka 	pcc->pcc_flags |= PCC_MLCONT;
     84      1.30  pooka 	dispatch(pcc);
     85      1.17  pooka 
     86      1.30  pooka 	/* Put result to kernel sendqueue if necessary */
     87      1.30  pooka 	preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
     88      1.30  pooka 	if (PUFFSOP_WANTREPLY(preq->preq_opclass)) {
     89      1.30  pooka 		if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
     90      1.30  pooka 			puffsdump_rv(preq);
     91      1.17  pooka 
     92      1.30  pooka 		puffs_framev_enqueue_justsend(pu, pu->pu_fd,
     93      1.30  pooka 		    pcc->pcc_pb, 0, 0);
     94      1.30  pooka 	} else {
     95      1.30  pooka 		puffs_framebuf_destroy(pcc->pcc_pb);
     96      1.30  pooka 	}
     97      1.17  pooka 
     98      1.30  pooka 	/* who needs information when you're living on borrowed time? */
     99      1.30  pooka 	if (pcc->pcc_flags & PCC_BORROWED) {
    100      1.30  pooka 		puffs_cc_yield(pcc); /* back to borrow source */
    101      1.17  pooka 	}
    102      1.30  pooka 	pcc->pcc_flags = 0;
    103      1.17  pooka }
    104      1.17  pooka 
    105      1.30  pooka /* public, but not really tested and only semi-supported */
    106       1.1  pooka int
    107      1.30  pooka puffs_dispatch_create(struct puffs_usermount *pu, struct puffs_framebuf *pb,
    108      1.30  pooka 	struct puffs_cc **pccp)
    109       1.1  pooka {
    110      1.30  pooka 	struct puffs_cc *pcc;
    111       1.1  pooka 
    112      1.30  pooka 	if (puffs__cc_create(pu, dispatch, &pcc) == -1)
    113      1.30  pooka 		return -1;
    114       1.1  pooka 
    115      1.30  pooka 	pcc->pcc_pb = pb;
    116      1.30  pooka 	*pccp = pcc;
    117       1.1  pooka 
    118      1.30  pooka 	return 0;
    119       1.1  pooka }
    120       1.1  pooka 
    121      1.30  pooka int
    122      1.30  pooka puffs_dispatch_exec(struct puffs_cc *pcc, struct puffs_framebuf **pbp)
    123       1.1  pooka {
    124      1.30  pooka 	int rv;
    125       1.1  pooka 
    126      1.30  pooka 	puffs_cc_continue(pcc);
    127      1.25  pooka 
    128      1.30  pooka 	if (pcc->pcc_flags & PCC_DONE) {
    129      1.30  pooka 		rv = 1;
    130      1.30  pooka 		*pbp = pcc->pcc_pb;
    131      1.30  pooka 		pcc->pcc_flags = 0;
    132      1.30  pooka 		puffs__cc_destroy(pcc, 0);
    133      1.30  pooka 	} else {
    134      1.30  pooka 		rv = 0;
    135       1.1  pooka 	}
    136      1.25  pooka 
    137      1.30  pooka 	return rv;
    138       1.1  pooka }
    139       1.1  pooka 
    140      1.30  pooka static void
    141      1.30  pooka dispatch(struct puffs_cc *pcc)
    142       1.1  pooka {
    143       1.1  pooka 	struct puffs_usermount *pu = pcc->pcc_pu;
    144       1.1  pooka 	struct puffs_ops *pops = &pu->pu_ops;
    145      1.25  pooka 	struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
    146      1.31  pooka 	void *auxbuf; /* help with typecasting */
    147      1.32  pooka 	puffs_cookie_t opcookie;
    148      1.31  pooka 	int error = 0, buildpath;
    149      1.31  pooka 
    150      1.31  pooka 	/* XXX: smaller hammer, please */
    151      1.31  pooka 	if ((PUFFSOP_OPCLASS(preq->preq_opclass == PUFFSOP_VFS &&
    152      1.31  pooka 	    preq->preq_optype == PUFFS_VFS_VPTOFH)) ||
    153      1.31  pooka 	    (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN &&
    154      1.31  pooka 	    (preq->preq_optype == PUFFS_VN_READDIR
    155      1.31  pooka 	    || preq->preq_optype == PUFFS_VN_READ))) {
    156      1.31  pooka 		if (puffs_framebuf_reserve_space(pcc->pcc_pb,
    157      1.31  pooka 		    PUFFS_MSG_MAXSIZE) == -1)
    158      1.31  pooka 			error = errno;
    159      1.31  pooka 		preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
    160      1.31  pooka 	}
    161      1.31  pooka 
    162      1.31  pooka 	auxbuf = preq;
    163      1.31  pooka 	opcookie = preq->preq_cookie;
    164       1.1  pooka 
    165      1.30  pooka 	assert((pcc->pcc_flags & PCC_DONE) == 0);
    166       1.1  pooka 
    167       1.1  pooka 	buildpath = pu->pu_flags & PUFFS_FLAG_BUILDPATH;
    168       1.1  pooka 	preq->preq_setbacks = 0;
    169       1.1  pooka 
    170      1.30  pooka 	if (pu->pu_flags & PUFFS_FLAG_OPDUMP)
    171      1.30  pooka 		puffsdump_req(preq);
    172      1.30  pooka 
    173      1.30  pooka 	puffs__cc_setcaller(pcc, preq->preq_pid, preq->preq_lid);
    174      1.30  pooka 
    175      1.30  pooka 	/* pre-operation */
    176      1.18  pooka 	if (pu->pu_oppre)
    177      1.24  pooka 		pu->pu_oppre(pu);
    178      1.18  pooka 
    179      1.31  pooka 	if (error)
    180      1.31  pooka 		goto out;
    181      1.31  pooka 
    182      1.30  pooka 	/* Execute actual operation */
    183       1.1  pooka 	if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
    184       1.1  pooka 		switch (preq->preq_optype) {
    185       1.1  pooka 		case PUFFS_VFS_UNMOUNT:
    186       1.1  pooka 		{
    187      1.15  pooka 			struct puffs_vfsmsg_unmount *auxt = auxbuf;
    188       1.1  pooka 
    189       1.1  pooka 			PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTING);
    190      1.24  pooka 			error = pops->puffs_fs_unmount(pu, auxt->pvfsr_flags);
    191       1.1  pooka 			if (!error)
    192       1.1  pooka 				PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED);
    193       1.1  pooka 			else
    194       1.1  pooka 				PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
    195       1.1  pooka 			break;
    196       1.1  pooka 		}
    197       1.1  pooka 
    198       1.1  pooka 		case PUFFS_VFS_STATVFS:
    199       1.1  pooka 		{
    200      1.15  pooka 			struct puffs_vfsmsg_statvfs *auxt = auxbuf;
    201       1.1  pooka 
    202      1.24  pooka 			error = pops->puffs_fs_statvfs(pu, &auxt->pvfsr_sb);
    203       1.1  pooka 			break;
    204       1.1  pooka 		}
    205       1.1  pooka 
    206       1.1  pooka 		case PUFFS_VFS_SYNC:
    207       1.1  pooka 		{
    208      1.15  pooka 			struct puffs_vfsmsg_sync *auxt = auxbuf;
    209       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvfsr_cred);
    210       1.1  pooka 
    211      1.24  pooka 			error = pops->puffs_fs_sync(pu,
    212      1.22  pooka 			    auxt->pvfsr_waitfor, pcr);
    213       1.1  pooka 			break;
    214       1.1  pooka 		}
    215       1.1  pooka 
    216       1.1  pooka 		case PUFFS_VFS_FHTOVP:
    217       1.1  pooka 		{
    218      1.15  pooka 			struct puffs_vfsmsg_fhtonode *auxt = auxbuf;
    219       1.9  pooka 			struct puffs_newinfo pni;
    220       1.9  pooka 
    221       1.9  pooka 			pni.pni_cookie = &auxt->pvfsr_fhcookie;
    222       1.9  pooka 			pni.pni_vtype = &auxt->pvfsr_vtype;
    223       1.9  pooka 			pni.pni_size = &auxt->pvfsr_size;
    224       1.9  pooka 			pni.pni_rdev = &auxt->pvfsr_rdev;
    225       1.1  pooka 
    226      1.24  pooka 			error = pops->puffs_fs_fhtonode(pu, auxt->pvfsr_data,
    227       1.9  pooka 			    auxt->pvfsr_dsize, &pni);
    228       1.1  pooka 
    229       1.1  pooka 			break;
    230       1.1  pooka 		}
    231       1.1  pooka 
    232       1.1  pooka 		case PUFFS_VFS_VPTOFH:
    233       1.1  pooka 		{
    234      1.15  pooka 			struct puffs_vfsmsg_nodetofh *auxt = auxbuf;
    235       1.1  pooka 
    236      1.24  pooka 			error = pops->puffs_fs_nodetofh(pu,
    237       1.1  pooka 			    auxt->pvfsr_fhcookie, auxt->pvfsr_data,
    238       1.1  pooka 			    &auxt->pvfsr_dsize);
    239       1.1  pooka 
    240       1.1  pooka 			break;
    241       1.1  pooka 		}
    242       1.1  pooka 
    243      1.34  pooka 		case PUFFS_VFS_EXTATTRCTL:
    244       1.1  pooka 		{
    245      1.34  pooka 			struct puffs_vfsmsg_extattrctl *auxt = auxbuf;
    246      1.34  pooka 			const char *attrname;
    247      1.34  pooka 			int flags;
    248       1.1  pooka 
    249      1.34  pooka 			if (pops->puffs_fs_extattrctl == NULL) {
    250      1.34  pooka 				error = EOPNOTSUPP;
    251       1.1  pooka 				break;
    252      1.34  pooka 			}
    253      1.34  pooka 
    254      1.34  pooka 			if (auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASATTRNAME)
    255      1.34  pooka 				attrname = auxt->pvfsr_attrname;
    256      1.34  pooka 			else
    257      1.34  pooka 				attrname = NULL;
    258       1.1  pooka 
    259      1.34  pooka 			flags = auxt->pvfsr_flags & PUFFS_EXTATTRCTL_HASNODE;
    260      1.34  pooka 			error = pops->puffs_fs_extattrctl(pu, auxt->pvfsr_cmd,
    261      1.34  pooka 			    opcookie, flags,
    262      1.34  pooka 			    auxt->pvfsr_attrnamespace, attrname);
    263       1.1  pooka 			break;
    264       1.1  pooka 		}
    265       1.1  pooka 
    266       1.1  pooka 		default:
    267       1.1  pooka 			/*
    268       1.1  pooka 			 * I guess the kernel sees this one coming
    269       1.1  pooka 			 */
    270       1.1  pooka 			error = EINVAL;
    271       1.1  pooka 			break;
    272       1.1  pooka 		}
    273       1.1  pooka 
    274       1.1  pooka 	/* XXX: audit return values */
    275       1.1  pooka 	/* XXX: sync with kernel */
    276       1.1  pooka 	} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
    277       1.1  pooka 		switch (preq->preq_optype) {
    278       1.1  pooka 		case PUFFS_VN_LOOKUP:
    279       1.1  pooka 		{
    280      1.15  pooka 			struct puffs_vnmsg_lookup *auxt = auxbuf;
    281       1.9  pooka 			struct puffs_newinfo pni;
    282       1.1  pooka 			struct puffs_cn pcn;
    283  1.36.2.1   yamt 			struct puffs_node *pn = NULL;
    284       1.1  pooka 
    285       1.1  pooka 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
    286       1.7  pooka 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
    287       1.9  pooka 			pni.pni_cookie = &auxt->pvnr_newnode;
    288       1.9  pooka 			pni.pni_vtype = &auxt->pvnr_vtype;
    289       1.9  pooka 			pni.pni_size = &auxt->pvnr_size;
    290       1.9  pooka 			pni.pni_rdev = &auxt->pvnr_rdev;
    291       1.7  pooka 
    292       1.1  pooka 			if (buildpath) {
    293       1.1  pooka 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
    294       1.1  pooka 				if (error)
    295       1.1  pooka 					break;
    296       1.1  pooka 			}
    297       1.1  pooka 
    298       1.1  pooka 			/* lookup *must* be present */
    299      1.24  pooka 			error = pops->puffs_node_lookup(pu, opcookie,
    300       1.9  pooka 			    &pni, &pcn);
    301       1.1  pooka 
    302       1.1  pooka 			if (buildpath) {
    303       1.1  pooka 				if (error) {
    304       1.1  pooka 					pu->pu_pathfree(pu, &pcn.pcn_po_full);
    305       1.1  pooka 				} else {
    306       1.1  pooka 					/*
    307       1.1  pooka 					 * did we get a new node or a
    308       1.1  pooka 					 * recycled node?
    309       1.1  pooka 					 */
    310       1.1  pooka 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
    311       1.1  pooka 					if (pn->pn_po.po_path == NULL)
    312       1.1  pooka 						pn->pn_po = pcn.pcn_po_full;
    313       1.1  pooka 					else
    314       1.1  pooka 						pu->pu_pathfree(pu,
    315       1.1  pooka 						    &pcn.pcn_po_full);
    316       1.1  pooka 				}
    317       1.1  pooka 			}
    318       1.1  pooka 
    319  1.36.2.1   yamt 			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
    320  1.36.2.1   yamt 				update_fs_ttl(pu, auxt->pvnr_newnode,
    321  1.36.2.1   yamt 					      &auxt->pvnr_va,
    322  1.36.2.1   yamt 					      &auxt->pvnr_va_ttl,
    323  1.36.2.1   yamt 					      &auxt->pvnr_cn_ttl);
    324  1.36.2.1   yamt 
    325       1.1  pooka 			break;
    326       1.1  pooka 		}
    327       1.1  pooka 
    328       1.1  pooka 		case PUFFS_VN_CREATE:
    329       1.1  pooka 		{
    330      1.15  pooka 			struct puffs_vnmsg_create *auxt = auxbuf;
    331       1.9  pooka 			struct puffs_newinfo pni;
    332       1.1  pooka 			struct puffs_cn pcn;
    333       1.9  pooka 
    334       1.1  pooka 			if (pops->puffs_node_create == NULL) {
    335       1.1  pooka 				error = 0;
    336       1.1  pooka 				break;
    337       1.1  pooka 			}
    338       1.1  pooka 
    339       1.1  pooka 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
    340       1.7  pooka 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
    341       1.7  pooka 
    342       1.9  pooka 			memset(&pni, 0, sizeof(pni));
    343       1.9  pooka 			pni.pni_cookie = &auxt->pvnr_newnode;
    344       1.9  pooka 
    345       1.1  pooka 			if (buildpath) {
    346       1.1  pooka 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
    347       1.1  pooka 				if (error)
    348       1.1  pooka 					break;
    349       1.1  pooka 			}
    350       1.1  pooka 
    351      1.24  pooka 			error = pops->puffs_node_create(pu,
    352       1.9  pooka 			    opcookie, &pni, &pcn, &auxt->pvnr_va);
    353       1.1  pooka 
    354       1.1  pooka 			if (buildpath) {
    355       1.1  pooka 				if (error) {
    356       1.1  pooka 					pu->pu_pathfree(pu, &pcn.pcn_po_full);
    357       1.1  pooka 				} else {
    358       1.1  pooka 					struct puffs_node *pn;
    359       1.1  pooka 
    360       1.1  pooka 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
    361       1.1  pooka 					pn->pn_po = pcn.pcn_po_full;
    362       1.1  pooka 				}
    363       1.1  pooka 			}
    364       1.1  pooka 
    365  1.36.2.1   yamt 			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
    366  1.36.2.1   yamt 				update_fs_ttl(pu, auxt->pvnr_newnode,
    367  1.36.2.1   yamt 					      &auxt->pvnr_va,
    368  1.36.2.1   yamt 					      &auxt->pvnr_va_ttl,
    369  1.36.2.1   yamt 					      &auxt->pvnr_cn_ttl);
    370  1.36.2.1   yamt 
    371       1.1  pooka 			break;
    372       1.1  pooka 		}
    373       1.1  pooka 
    374       1.1  pooka 		case PUFFS_VN_MKNOD:
    375       1.1  pooka 		{
    376      1.15  pooka 			struct puffs_vnmsg_mknod *auxt = auxbuf;
    377       1.9  pooka 			struct puffs_newinfo pni;
    378       1.1  pooka 			struct puffs_cn pcn;
    379       1.9  pooka 
    380       1.1  pooka 			if (pops->puffs_node_mknod == NULL) {
    381       1.1  pooka 				error = 0;
    382       1.1  pooka 				break;
    383       1.1  pooka 			}
    384       1.1  pooka 
    385       1.1  pooka 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
    386       1.7  pooka 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
    387       1.7  pooka 
    388       1.9  pooka 			memset(&pni, 0, sizeof(pni));
    389       1.9  pooka 			pni.pni_cookie = &auxt->pvnr_newnode;
    390       1.9  pooka 
    391       1.1  pooka 			if (buildpath) {
    392       1.1  pooka 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
    393       1.1  pooka 				if (error)
    394       1.1  pooka 					break;
    395       1.1  pooka 			}
    396       1.1  pooka 
    397      1.24  pooka 			error = pops->puffs_node_mknod(pu,
    398       1.9  pooka 			    opcookie, &pni, &pcn, &auxt->pvnr_va);
    399       1.1  pooka 
    400       1.1  pooka 			if (buildpath) {
    401       1.1  pooka 				if (error) {
    402       1.1  pooka 					pu->pu_pathfree(pu, &pcn.pcn_po_full);
    403       1.1  pooka 				} else {
    404       1.1  pooka 					struct puffs_node *pn;
    405       1.1  pooka 
    406       1.1  pooka 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
    407       1.1  pooka 					pn->pn_po = pcn.pcn_po_full;
    408       1.1  pooka 				}
    409       1.1  pooka 			}
    410       1.1  pooka 
    411  1.36.2.1   yamt 			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
    412  1.36.2.1   yamt 				update_fs_ttl(pu, auxt->pvnr_newnode,
    413  1.36.2.1   yamt 					      &auxt->pvnr_va,
    414  1.36.2.1   yamt 					      &auxt->pvnr_va_ttl,
    415  1.36.2.1   yamt 					      &auxt->pvnr_cn_ttl);
    416  1.36.2.1   yamt 
    417       1.1  pooka 			break;
    418       1.1  pooka 		}
    419       1.1  pooka 
    420       1.1  pooka 		case PUFFS_VN_OPEN:
    421       1.1  pooka 		{
    422      1.15  pooka 			struct puffs_vnmsg_open *auxt = auxbuf;
    423       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    424       1.7  pooka 
    425       1.1  pooka 			if (pops->puffs_node_open == NULL) {
    426       1.1  pooka 				error = 0;
    427       1.1  pooka 				break;
    428       1.1  pooka 			}
    429       1.1  pooka 
    430      1.24  pooka 			error = pops->puffs_node_open(pu,
    431      1.22  pooka 			    opcookie, auxt->pvnr_mode, pcr);
    432       1.1  pooka 			break;
    433       1.1  pooka 		}
    434       1.1  pooka 
    435       1.1  pooka 		case PUFFS_VN_CLOSE:
    436       1.1  pooka 		{
    437      1.15  pooka 			struct puffs_vnmsg_close *auxt = auxbuf;
    438       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    439       1.7  pooka 
    440       1.1  pooka 			if (pops->puffs_node_close == NULL) {
    441       1.1  pooka 				error = 0;
    442       1.1  pooka 				break;
    443       1.1  pooka 			}
    444       1.1  pooka 
    445      1.24  pooka 			error = pops->puffs_node_close(pu,
    446      1.22  pooka 			    opcookie, auxt->pvnr_fflag, pcr);
    447       1.1  pooka 			break;
    448       1.1  pooka 		}
    449       1.1  pooka 
    450       1.1  pooka 		case PUFFS_VN_ACCESS:
    451       1.1  pooka 		{
    452      1.15  pooka 			struct puffs_vnmsg_access *auxt = auxbuf;
    453       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    454       1.7  pooka 
    455       1.1  pooka 			if (pops->puffs_node_access == NULL) {
    456       1.1  pooka 				error = 0;
    457       1.1  pooka 				break;
    458       1.1  pooka 			}
    459       1.1  pooka 
    460      1.24  pooka 			error = pops->puffs_node_access(pu,
    461      1.22  pooka 			    opcookie, auxt->pvnr_mode, pcr);
    462       1.1  pooka 			break;
    463       1.1  pooka 		}
    464       1.1  pooka 
    465       1.1  pooka 		case PUFFS_VN_GETATTR:
    466       1.1  pooka 		{
    467      1.15  pooka 			struct puffs_vnmsg_getattr *auxt = auxbuf;
    468       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    469       1.7  pooka 
    470       1.1  pooka 			if (pops->puffs_node_getattr == NULL) {
    471       1.1  pooka 				error = EOPNOTSUPP;
    472       1.1  pooka 				break;
    473       1.1  pooka 			}
    474       1.1  pooka 
    475      1.24  pooka 			error = pops->puffs_node_getattr(pu,
    476      1.22  pooka 			    opcookie, &auxt->pvnr_va, pcr);
    477  1.36.2.1   yamt 
    478  1.36.2.1   yamt 			if ((error == 0) && PUFFS_USE_FS_TTL(pu)) {
    479  1.36.2.1   yamt 				struct puffs_node *pn;
    480  1.36.2.1   yamt 
    481  1.36.2.1   yamt 				pn = PU_CMAP(pu, opcookie);
    482  1.36.2.1   yamt 				auxt->pvnr_va_ttl = pn->pn_va_ttl;
    483  1.36.2.1   yamt 			}
    484  1.36.2.1   yamt 
    485  1.36.2.1   yamt 			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
    486  1.36.2.1   yamt 				update_fs_ttl(pu, opcookie,
    487  1.36.2.1   yamt 					      &auxt->pvnr_va,
    488  1.36.2.1   yamt 					      &auxt->pvnr_va_ttl,
    489  1.36.2.1   yamt 					      NULL);
    490  1.36.2.1   yamt 
    491       1.1  pooka 			break;
    492       1.1  pooka 		}
    493       1.1  pooka 
    494       1.1  pooka 		case PUFFS_VN_SETATTR:
    495       1.1  pooka 		{
    496      1.15  pooka 			struct puffs_vnmsg_setattr *auxt = auxbuf;
    497       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    498       1.7  pooka 
    499       1.1  pooka 			if (pops->puffs_node_setattr == NULL) {
    500       1.1  pooka 				error = EOPNOTSUPP;
    501       1.1  pooka 				break;
    502       1.1  pooka 			}
    503       1.1  pooka 
    504      1.24  pooka 			error = pops->puffs_node_setattr(pu,
    505      1.22  pooka 			    opcookie, &auxt->pvnr_va, pcr);
    506  1.36.2.1   yamt 
    507  1.36.2.1   yamt 			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
    508  1.36.2.1   yamt 				update_fs_ttl(pu, opcookie,
    509  1.36.2.1   yamt 					      &auxt->pvnr_va,
    510  1.36.2.1   yamt 					      &auxt->pvnr_va_ttl,
    511  1.36.2.1   yamt 					      NULL);
    512       1.1  pooka 			break;
    513       1.1  pooka 		}
    514       1.1  pooka 
    515       1.1  pooka 		case PUFFS_VN_MMAP:
    516       1.1  pooka 		{
    517      1.15  pooka 			struct puffs_vnmsg_mmap *auxt = auxbuf;
    518       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    519       1.7  pooka 
    520       1.1  pooka 			if (pops->puffs_node_mmap == NULL) {
    521       1.1  pooka 				error = 0;
    522       1.1  pooka 				break;
    523       1.1  pooka 			}
    524       1.1  pooka 
    525      1.24  pooka 			error = pops->puffs_node_mmap(pu,
    526      1.22  pooka 			    opcookie, auxt->pvnr_prot, pcr);
    527       1.1  pooka 			break;
    528       1.1  pooka 		}
    529       1.1  pooka 
    530       1.1  pooka 		case PUFFS_VN_FSYNC:
    531       1.1  pooka 		{
    532      1.15  pooka 			struct puffs_vnmsg_fsync *auxt = auxbuf;
    533       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    534       1.7  pooka 
    535       1.1  pooka 			if (pops->puffs_node_fsync == NULL) {
    536       1.1  pooka 				error = 0;
    537       1.1  pooka 				break;
    538       1.1  pooka 			}
    539       1.1  pooka 
    540      1.24  pooka 			error = pops->puffs_node_fsync(pu, opcookie, pcr,
    541       1.1  pooka 			    auxt->pvnr_flags, auxt->pvnr_offlo,
    542      1.22  pooka 			    auxt->pvnr_offhi);
    543       1.1  pooka 			break;
    544       1.1  pooka 		}
    545       1.1  pooka 
    546       1.1  pooka 		case PUFFS_VN_SEEK:
    547       1.1  pooka 		{
    548      1.15  pooka 			struct puffs_vnmsg_seek *auxt = auxbuf;
    549       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    550       1.7  pooka 
    551       1.1  pooka 			if (pops->puffs_node_seek == NULL) {
    552       1.1  pooka 				error = 0;
    553       1.1  pooka 				break;
    554       1.1  pooka 			}
    555       1.1  pooka 
    556      1.24  pooka 			error = pops->puffs_node_seek(pu,
    557       1.1  pooka 			    opcookie, auxt->pvnr_oldoff,
    558       1.7  pooka 			    auxt->pvnr_newoff, pcr);
    559       1.1  pooka 			break;
    560       1.1  pooka 		}
    561       1.1  pooka 
    562       1.1  pooka 		case PUFFS_VN_REMOVE:
    563       1.1  pooka 		{
    564      1.15  pooka 			struct puffs_vnmsg_remove *auxt = auxbuf;
    565       1.1  pooka 			struct puffs_cn pcn;
    566       1.1  pooka 			if (pops->puffs_node_remove == NULL) {
    567       1.1  pooka 				error = 0;
    568       1.1  pooka 				break;
    569       1.1  pooka 			}
    570       1.1  pooka 
    571       1.1  pooka 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
    572       1.7  pooka 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
    573       1.1  pooka 
    574      1.24  pooka 			error = pops->puffs_node_remove(pu,
    575       1.1  pooka 			    opcookie, auxt->pvnr_cookie_targ, &pcn);
    576       1.1  pooka 			break;
    577       1.1  pooka 		}
    578       1.1  pooka 
    579       1.1  pooka 		case PUFFS_VN_LINK:
    580       1.1  pooka 		{
    581      1.15  pooka 			struct puffs_vnmsg_link *auxt = auxbuf;
    582       1.1  pooka 			struct puffs_cn pcn;
    583       1.1  pooka 			if (pops->puffs_node_link == NULL) {
    584       1.1  pooka 				error = 0;
    585       1.1  pooka 				break;
    586       1.1  pooka 			}
    587       1.1  pooka 
    588       1.1  pooka 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
    589       1.7  pooka 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
    590       1.7  pooka 
    591       1.1  pooka 			if (buildpath) {
    592       1.1  pooka 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
    593       1.1  pooka 				if (error)
    594       1.1  pooka 					break;
    595       1.1  pooka 			}
    596       1.1  pooka 
    597      1.24  pooka 			error = pops->puffs_node_link(pu,
    598       1.1  pooka 			    opcookie, auxt->pvnr_cookie_targ, &pcn);
    599       1.1  pooka 			if (buildpath)
    600       1.1  pooka 				pu->pu_pathfree(pu, &pcn.pcn_po_full);
    601       1.1  pooka 
    602       1.1  pooka 			break;
    603       1.1  pooka 		}
    604       1.1  pooka 
    605       1.1  pooka 		case PUFFS_VN_RENAME:
    606       1.1  pooka 		{
    607      1.15  pooka 			struct puffs_vnmsg_rename *auxt = auxbuf;
    608       1.1  pooka 			struct puffs_cn pcn_src, pcn_targ;
    609       1.1  pooka 			struct puffs_node *pn_src;
    610       1.1  pooka 
    611       1.1  pooka 			if (pops->puffs_node_rename == NULL) {
    612       1.1  pooka 				error = 0;
    613       1.1  pooka 				break;
    614       1.1  pooka 			}
    615       1.1  pooka 
    616       1.1  pooka 			pcn_src.pcn_pkcnp = &auxt->pvnr_cn_src;
    617       1.7  pooka 			PUFFS_KCREDTOCRED(pcn_src.pcn_cred,
    618       1.7  pooka 			    &auxt->pvnr_cn_src_cred);
    619       1.8  pooka 
    620       1.1  pooka 			pcn_targ.pcn_pkcnp = &auxt->pvnr_cn_targ;
    621       1.7  pooka 			PUFFS_KCREDTOCRED(pcn_targ.pcn_cred,
    622       1.7  pooka 			    &auxt->pvnr_cn_targ_cred);
    623       1.7  pooka 
    624       1.1  pooka 			if (buildpath) {
    625       1.1  pooka 				pn_src = auxt->pvnr_cookie_src;
    626       1.1  pooka 				pcn_src.pcn_po_full = pn_src->pn_po;
    627       1.1  pooka 
    628       1.1  pooka 				error = puffs_path_pcnbuild(pu, &pcn_targ,
    629       1.1  pooka 				    auxt->pvnr_cookie_targdir);
    630       1.1  pooka 				if (error)
    631       1.1  pooka 					break;
    632       1.1  pooka 			}
    633       1.1  pooka 
    634      1.24  pooka 			error = pops->puffs_node_rename(pu,
    635       1.1  pooka 			    opcookie, auxt->pvnr_cookie_src,
    636       1.1  pooka 			    &pcn_src, auxt->pvnr_cookie_targdir,
    637       1.1  pooka 			    auxt->pvnr_cookie_targ, &pcn_targ);
    638       1.1  pooka 
    639       1.1  pooka 			if (buildpath) {
    640       1.1  pooka 				if (error) {
    641       1.1  pooka 					pu->pu_pathfree(pu,
    642       1.1  pooka 					    &pcn_targ.pcn_po_full);
    643       1.1  pooka 				} else {
    644       1.1  pooka 					struct puffs_pathinfo pi;
    645       1.1  pooka 					struct puffs_pathobj po_old;
    646       1.1  pooka 
    647       1.1  pooka 					/* handle this node */
    648       1.1  pooka 					po_old = pn_src->pn_po;
    649       1.1  pooka 					pn_src->pn_po = pcn_targ.pcn_po_full;
    650       1.1  pooka 
    651       1.1  pooka 					if (pn_src->pn_va.va_type != VDIR) {
    652       1.1  pooka 						pu->pu_pathfree(pu, &po_old);
    653       1.1  pooka 						break;
    654       1.1  pooka 					}
    655       1.1  pooka 
    656       1.1  pooka 					/* handle all child nodes for DIRs */
    657       1.1  pooka 					pi.pi_old = &pcn_src.pcn_po_full;
    658       1.1  pooka 					pi.pi_new = &pcn_targ.pcn_po_full;
    659       1.1  pooka 
    660      1.19  pooka 					PU_LOCK();
    661       1.1  pooka 					if (puffs_pn_nodewalk(pu,
    662       1.1  pooka 					    puffs_path_prefixadj, &pi) != NULL)
    663       1.1  pooka 						error = ENOMEM;
    664      1.19  pooka 					PU_UNLOCK();
    665       1.1  pooka 					pu->pu_pathfree(pu, &po_old);
    666       1.1  pooka 				}
    667       1.1  pooka 			}
    668       1.1  pooka 			break;
    669       1.1  pooka 		}
    670       1.1  pooka 
    671       1.1  pooka 		case PUFFS_VN_MKDIR:
    672       1.1  pooka 		{
    673      1.15  pooka 			struct puffs_vnmsg_mkdir *auxt = auxbuf;
    674       1.9  pooka 			struct puffs_newinfo pni;
    675       1.1  pooka 			struct puffs_cn pcn;
    676       1.9  pooka 
    677       1.1  pooka 			if (pops->puffs_node_mkdir == NULL) {
    678       1.1  pooka 				error = 0;
    679       1.1  pooka 				break;
    680       1.1  pooka 			}
    681       1.1  pooka 
    682       1.1  pooka 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
    683       1.7  pooka 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
    684       1.7  pooka 
    685       1.9  pooka 			memset(&pni, 0, sizeof(pni));
    686       1.9  pooka 			pni.pni_cookie = &auxt->pvnr_newnode;
    687       1.9  pooka 
    688       1.1  pooka 			if (buildpath) {
    689       1.1  pooka 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
    690       1.1  pooka 				if (error)
    691       1.1  pooka 					break;
    692       1.1  pooka 			}
    693       1.1  pooka 
    694      1.24  pooka 			error = pops->puffs_node_mkdir(pu,
    695       1.9  pooka 			    opcookie, &pni, &pcn, &auxt->pvnr_va);
    696       1.1  pooka 
    697       1.1  pooka 			if (buildpath) {
    698       1.1  pooka 				if (error) {
    699       1.1  pooka 					pu->pu_pathfree(pu, &pcn.pcn_po_full);
    700       1.1  pooka 				} else {
    701       1.1  pooka 					struct puffs_node *pn;
    702       1.1  pooka 
    703       1.1  pooka 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
    704       1.1  pooka 					pn->pn_po = pcn.pcn_po_full;
    705       1.1  pooka 				}
    706       1.1  pooka 			}
    707       1.1  pooka 
    708  1.36.2.1   yamt 			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
    709  1.36.2.1   yamt 				update_fs_ttl(pu, auxt->pvnr_newnode,
    710  1.36.2.1   yamt 					      &auxt->pvnr_va,
    711  1.36.2.1   yamt 					      &auxt->pvnr_va_ttl,
    712  1.36.2.1   yamt 					      &auxt->pvnr_cn_ttl);
    713  1.36.2.1   yamt 
    714       1.1  pooka 			break;
    715       1.1  pooka 		}
    716       1.1  pooka 
    717       1.1  pooka 		case PUFFS_VN_RMDIR:
    718       1.1  pooka 		{
    719      1.15  pooka 			struct puffs_vnmsg_rmdir *auxt = auxbuf;
    720       1.1  pooka 			struct puffs_cn pcn;
    721       1.1  pooka 			if (pops->puffs_node_rmdir == NULL) {
    722       1.1  pooka 				error = 0;
    723       1.1  pooka 				break;
    724       1.1  pooka 			}
    725       1.1  pooka 
    726       1.1  pooka 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
    727       1.7  pooka 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
    728       1.1  pooka 
    729      1.24  pooka 			error = pops->puffs_node_rmdir(pu,
    730       1.1  pooka 			    opcookie, auxt->pvnr_cookie_targ, &pcn);
    731       1.1  pooka 			break;
    732       1.1  pooka 		}
    733       1.1  pooka 
    734       1.1  pooka 		case PUFFS_VN_SYMLINK:
    735       1.1  pooka 		{
    736      1.15  pooka 			struct puffs_vnmsg_symlink *auxt = auxbuf;
    737       1.9  pooka 			struct puffs_newinfo pni;
    738       1.1  pooka 			struct puffs_cn pcn;
    739       1.9  pooka 
    740       1.1  pooka 			if (pops->puffs_node_symlink == NULL) {
    741       1.1  pooka 				error = 0;
    742       1.1  pooka 				break;
    743       1.1  pooka 			}
    744       1.1  pooka 
    745       1.1  pooka 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
    746       1.7  pooka 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
    747       1.7  pooka 
    748       1.9  pooka 			memset(&pni, 0, sizeof(pni));
    749       1.9  pooka 			pni.pni_cookie = &auxt->pvnr_newnode;
    750       1.9  pooka 
    751       1.1  pooka 			if (buildpath) {
    752       1.1  pooka 				error = puffs_path_pcnbuild(pu, &pcn, opcookie);
    753       1.1  pooka 				if (error)
    754       1.1  pooka 					break;
    755       1.1  pooka 			}
    756       1.1  pooka 
    757      1.24  pooka 			error = pops->puffs_node_symlink(pu,
    758       1.9  pooka 			    opcookie, &pni, &pcn,
    759       1.9  pooka 			    &auxt->pvnr_va, auxt->pvnr_link);
    760       1.1  pooka 
    761       1.1  pooka 			if (buildpath) {
    762       1.1  pooka 				if (error) {
    763       1.1  pooka 					pu->pu_pathfree(pu, &pcn.pcn_po_full);
    764       1.1  pooka 				} else {
    765       1.1  pooka 					struct puffs_node *pn;
    766       1.1  pooka 
    767       1.1  pooka 					pn = PU_CMAP(pu, auxt->pvnr_newnode);
    768       1.1  pooka 					pn->pn_po = pcn.pcn_po_full;
    769       1.1  pooka 				}
    770       1.1  pooka 			}
    771       1.1  pooka 
    772  1.36.2.1   yamt 			if ((error == 0) && PUFFS_USE_FS_TTL(pu))
    773  1.36.2.1   yamt 				update_fs_ttl(pu, auxt->pvnr_newnode,
    774  1.36.2.1   yamt 					      &auxt->pvnr_va,
    775  1.36.2.1   yamt 					      &auxt->pvnr_va_ttl,
    776  1.36.2.1   yamt 					      &auxt->pvnr_cn_ttl);
    777  1.36.2.1   yamt 
    778       1.1  pooka 			break;
    779       1.1  pooka 		}
    780       1.1  pooka 
    781       1.1  pooka 		case PUFFS_VN_READDIR:
    782       1.1  pooka 		{
    783      1.15  pooka 			struct puffs_vnmsg_readdir *auxt = auxbuf;
    784       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    785       1.1  pooka 			struct dirent *dent;
    786       1.1  pooka 			off_t *cookies;
    787       1.1  pooka 			size_t res, origcookies;
    788       1.1  pooka 
    789       1.1  pooka 			if (pops->puffs_node_readdir == NULL) {
    790       1.1  pooka 				error = 0;
    791       1.1  pooka 				break;
    792       1.1  pooka 			}
    793       1.1  pooka 
    794       1.1  pooka 			if (auxt->pvnr_ncookies) {
    795       1.1  pooka 				/* LINTED: pvnr_data is __aligned() */
    796       1.1  pooka 				cookies = (off_t *)auxt->pvnr_data;
    797       1.1  pooka 				origcookies = auxt->pvnr_ncookies;
    798       1.1  pooka 			} else {
    799       1.1  pooka 				cookies = NULL;
    800       1.1  pooka 				origcookies = 0;
    801       1.1  pooka 			}
    802       1.1  pooka 			/* LINTED: dentoff is aligned in the kernel */
    803       1.1  pooka 			dent = (struct dirent *)
    804       1.1  pooka 			    (auxt->pvnr_data + auxt->pvnr_dentoff);
    805       1.1  pooka 
    806       1.1  pooka 			res = auxt->pvnr_resid;
    807      1.24  pooka 			error = pops->puffs_node_readdir(pu,
    808       1.1  pooka 			    opcookie, dent, &auxt->pvnr_offset,
    809       1.7  pooka 			    &auxt->pvnr_resid, pcr, &auxt->pvnr_eofflag,
    810       1.7  pooka 			    cookies, &auxt->pvnr_ncookies);
    811       1.1  pooka 
    812       1.1  pooka 			/* much easier to track non-working NFS */
    813       1.1  pooka 			assert(auxt->pvnr_ncookies <= origcookies);
    814       1.1  pooka 
    815       1.1  pooka 			/* need to move a bit more */
    816      1.15  pooka 			preq->preq_buflen = sizeof(struct puffs_vnmsg_readdir)
    817       1.1  pooka 			    + auxt->pvnr_dentoff + (res - auxt->pvnr_resid);
    818       1.1  pooka 			break;
    819       1.1  pooka 		}
    820       1.1  pooka 
    821       1.1  pooka 		case PUFFS_VN_READLINK:
    822       1.1  pooka 		{
    823      1.15  pooka 			struct puffs_vnmsg_readlink *auxt = auxbuf;
    824       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    825       1.7  pooka 
    826       1.1  pooka 			if (pops->puffs_node_readlink == NULL) {
    827       1.1  pooka 				error = EOPNOTSUPP;
    828       1.1  pooka 				break;
    829       1.1  pooka 			}
    830       1.1  pooka 
    831       1.7  pooka 			/*LINTED*/
    832      1.24  pooka 			error = pops->puffs_node_readlink(pu, opcookie, pcr,
    833       1.1  pooka 			    auxt->pvnr_link, &auxt->pvnr_linklen);
    834       1.1  pooka 			break;
    835       1.1  pooka 		}
    836       1.1  pooka 
    837       1.1  pooka 		case PUFFS_VN_RECLAIM:
    838       1.1  pooka 		{
    839       1.8  pooka 
    840       1.1  pooka 			if (pops->puffs_node_reclaim == NULL) {
    841       1.1  pooka 				error = 0;
    842       1.1  pooka 				break;
    843       1.1  pooka 			}
    844       1.1  pooka 
    845      1.24  pooka 			error = pops->puffs_node_reclaim(pu, opcookie);
    846       1.1  pooka 			break;
    847       1.1  pooka 		}
    848       1.1  pooka 
    849       1.1  pooka 		case PUFFS_VN_INACTIVE:
    850       1.1  pooka 		{
    851       1.8  pooka 
    852       1.1  pooka 			if (pops->puffs_node_inactive == NULL) {
    853       1.1  pooka 				error = EOPNOTSUPP;
    854       1.1  pooka 				break;
    855       1.1  pooka 			}
    856       1.1  pooka 
    857      1.24  pooka 			error = pops->puffs_node_inactive(pu, opcookie);
    858       1.1  pooka 			break;
    859       1.1  pooka 		}
    860       1.1  pooka 
    861       1.1  pooka 		case PUFFS_VN_PATHCONF:
    862       1.1  pooka 		{
    863      1.15  pooka 			struct puffs_vnmsg_pathconf *auxt = auxbuf;
    864       1.1  pooka 			if (pops->puffs_node_pathconf == NULL) {
    865       1.1  pooka 				error = 0;
    866       1.1  pooka 				break;
    867       1.1  pooka 			}
    868       1.1  pooka 
    869      1.24  pooka 			error = pops->puffs_node_pathconf(pu,
    870       1.1  pooka 			    opcookie, auxt->pvnr_name,
    871       1.1  pooka 			    &auxt->pvnr_retval);
    872       1.1  pooka 			break;
    873       1.1  pooka 		}
    874       1.1  pooka 
    875       1.1  pooka 		case PUFFS_VN_ADVLOCK:
    876       1.1  pooka 		{
    877      1.15  pooka 			struct puffs_vnmsg_advlock *auxt = auxbuf;
    878       1.1  pooka 			if (pops->puffs_node_advlock == NULL) {
    879       1.1  pooka 				error = 0;
    880       1.1  pooka 				break;
    881       1.1  pooka 			}
    882       1.1  pooka 
    883      1.24  pooka 			error = pops->puffs_node_advlock(pu,
    884       1.1  pooka 			    opcookie, auxt->pvnr_id, auxt->pvnr_op,
    885       1.1  pooka 			    &auxt->pvnr_fl, auxt->pvnr_flags);
    886       1.1  pooka 			break;
    887       1.1  pooka 		}
    888       1.1  pooka 
    889       1.1  pooka 		case PUFFS_VN_PRINT:
    890       1.1  pooka 		{
    891       1.1  pooka 			if (pops->puffs_node_print == NULL) {
    892       1.1  pooka 				error = 0;
    893       1.1  pooka 				break;
    894       1.1  pooka 			}
    895       1.1  pooka 
    896      1.24  pooka 			error = pops->puffs_node_print(pu,
    897       1.1  pooka 			    opcookie);
    898       1.1  pooka 			break;
    899       1.1  pooka 		}
    900       1.1  pooka 
    901      1.33  pooka 		case PUFFS_VN_ABORTOP:
    902      1.33  pooka 		{
    903      1.33  pooka 			struct puffs_vnmsg_abortop *auxt = auxbuf;
    904      1.33  pooka 			struct puffs_cn pcn;
    905      1.33  pooka 
    906      1.33  pooka 			if (pops->puffs_node_abortop == NULL) {
    907      1.33  pooka 				error = 0;
    908      1.33  pooka 				break;
    909      1.33  pooka 			}
    910      1.33  pooka 
    911      1.33  pooka 			pcn.pcn_pkcnp = &auxt->pvnr_cn;
    912      1.33  pooka 			PUFFS_KCREDTOCRED(pcn.pcn_cred, &auxt->pvnr_cn_cred);
    913      1.33  pooka 
    914      1.33  pooka 			error = pops->puffs_node_abortop(pu, opcookie, &pcn);
    915      1.33  pooka 
    916      1.33  pooka 			break;
    917      1.33  pooka 		}
    918      1.33  pooka 
    919       1.1  pooka 		case PUFFS_VN_READ:
    920       1.1  pooka 		{
    921      1.15  pooka 			struct puffs_vnmsg_read *auxt = auxbuf;
    922       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    923       1.1  pooka 			size_t res;
    924       1.1  pooka 
    925       1.1  pooka 			if (pops->puffs_node_read == NULL) {
    926       1.1  pooka 				error = EIO;
    927       1.1  pooka 				break;
    928       1.1  pooka 			}
    929       1.1  pooka 
    930       1.1  pooka 			res = auxt->pvnr_resid;
    931      1.24  pooka 			error = pops->puffs_node_read(pu,
    932       1.1  pooka 			    opcookie, auxt->pvnr_data,
    933       1.1  pooka 			    auxt->pvnr_offset, &auxt->pvnr_resid,
    934       1.7  pooka 			    pcr, auxt->pvnr_ioflag);
    935       1.1  pooka 
    936       1.1  pooka 			/* need to move a bit more */
    937      1.15  pooka 			preq->preq_buflen = sizeof(struct puffs_vnmsg_read)
    938       1.1  pooka 			    + (res - auxt->pvnr_resid);
    939       1.1  pooka 			break;
    940       1.1  pooka 		}
    941       1.1  pooka 
    942       1.1  pooka 		case PUFFS_VN_WRITE:
    943       1.1  pooka 		{
    944      1.15  pooka 			struct puffs_vnmsg_write *auxt = auxbuf;
    945       1.7  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    946       1.1  pooka 
    947       1.1  pooka 			if (pops->puffs_node_write == NULL) {
    948       1.1  pooka 				error = EIO;
    949       1.1  pooka 				break;
    950       1.1  pooka 			}
    951       1.1  pooka 
    952      1.24  pooka 			error = pops->puffs_node_write(pu,
    953       1.1  pooka 			    opcookie, auxt->pvnr_data,
    954       1.1  pooka 			    auxt->pvnr_offset, &auxt->pvnr_resid,
    955       1.7  pooka 			    pcr, auxt->pvnr_ioflag);
    956       1.1  pooka 
    957       1.1  pooka 			/* don't need to move data back to the kernel */
    958      1.15  pooka 			preq->preq_buflen = sizeof(struct puffs_vnmsg_write);
    959       1.1  pooka 			break;
    960       1.1  pooka 		}
    961       1.1  pooka 
    962       1.4  pooka 		case PUFFS_VN_POLL:
    963       1.4  pooka 		{
    964      1.15  pooka 			struct puffs_vnmsg_poll *auxt = auxbuf;
    965       1.8  pooka 
    966       1.4  pooka 			if (pops->puffs_node_poll == NULL) {
    967       1.4  pooka 				error = 0;
    968       1.4  pooka 
    969       1.4  pooka 				/* emulate genfs_poll() */
    970       1.4  pooka 				auxt->pvnr_events &= (POLLIN | POLLOUT
    971       1.4  pooka 						    | POLLRDNORM | POLLWRNORM);
    972       1.4  pooka 
    973       1.4  pooka 				break;
    974       1.4  pooka 			}
    975       1.4  pooka 
    976      1.24  pooka 			error = pops->puffs_node_poll(pu,
    977      1.22  pooka 			    opcookie, &auxt->pvnr_events);
    978       1.4  pooka 			break;
    979       1.4  pooka 		}
    980       1.4  pooka 
    981      1.34  pooka 		case PUFFS_VN_GETEXTATTR:
    982      1.34  pooka 		{
    983      1.34  pooka 			struct puffs_vnmsg_getextattr *auxt = auxbuf;
    984      1.34  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
    985      1.34  pooka 			size_t res, *resp, *sizep;
    986      1.34  pooka 			uint8_t *data;
    987      1.34  pooka 
    988      1.34  pooka 			if (pops->puffs_node_getextattr == NULL) {
    989      1.34  pooka 				error = EOPNOTSUPP;
    990      1.34  pooka 				break;
    991      1.34  pooka 			}
    992      1.34  pooka 
    993      1.34  pooka 			if (auxt->pvnr_datasize)
    994      1.34  pooka 				sizep = &auxt->pvnr_datasize;
    995      1.34  pooka 			else
    996      1.34  pooka 				sizep = NULL;
    997      1.34  pooka 
    998      1.34  pooka 			res = auxt->pvnr_resid;
    999      1.34  pooka 			if (res > 0) {
   1000      1.34  pooka 				data = auxt->pvnr_data;
   1001      1.34  pooka 				resp = &auxt->pvnr_resid;
   1002      1.34  pooka 			} else {
   1003      1.34  pooka 				data = NULL;
   1004      1.34  pooka 				resp = NULL;
   1005      1.34  pooka 			}
   1006      1.34  pooka 
   1007      1.34  pooka 			error = pops->puffs_node_getextattr(pu,
   1008      1.34  pooka 			    opcookie, auxt->pvnr_attrnamespace,
   1009      1.34  pooka 			    auxt->pvnr_attrname, sizep, data, resp, pcr);
   1010      1.34  pooka 
   1011      1.34  pooka 			/* need to move a bit more? */
   1012      1.34  pooka 			preq->preq_buflen =
   1013      1.34  pooka 			    sizeof(struct puffs_vnmsg_getextattr)
   1014      1.34  pooka 			    + (res - auxt->pvnr_resid);
   1015      1.34  pooka 			break;
   1016      1.34  pooka 		}
   1017      1.34  pooka 
   1018      1.34  pooka 		case PUFFS_VN_SETEXTATTR:
   1019      1.34  pooka 		{
   1020      1.34  pooka 			struct puffs_vnmsg_setextattr *auxt = auxbuf;
   1021      1.34  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
   1022      1.34  pooka 			size_t *resp;
   1023      1.34  pooka 			uint8_t *data;
   1024      1.34  pooka 
   1025      1.34  pooka 			if (pops->puffs_node_setextattr == NULL) {
   1026      1.34  pooka 				error = EOPNOTSUPP;
   1027      1.34  pooka 				break;
   1028      1.34  pooka 			}
   1029      1.34  pooka 
   1030      1.34  pooka 			if (auxt->pvnr_resid > 0) {
   1031      1.34  pooka 				data = auxt->pvnr_data;
   1032      1.34  pooka 				resp = &auxt->pvnr_resid;
   1033      1.34  pooka 			} else {
   1034      1.34  pooka 				data = NULL;
   1035      1.34  pooka 				resp = NULL;
   1036      1.34  pooka 			}
   1037      1.34  pooka 
   1038      1.34  pooka 			error = pops->puffs_node_setextattr(pu,
   1039      1.34  pooka 			    opcookie, auxt->pvnr_attrnamespace,
   1040      1.34  pooka 			    auxt->pvnr_attrname, data, resp, pcr);
   1041      1.34  pooka 			break;
   1042      1.34  pooka 		}
   1043      1.34  pooka 
   1044      1.34  pooka 		case PUFFS_VN_LISTEXTATTR:
   1045      1.34  pooka 		{
   1046      1.34  pooka 			struct puffs_vnmsg_listextattr *auxt = auxbuf;
   1047      1.34  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
   1048      1.34  pooka 			size_t res, *resp, *sizep;
   1049      1.36   manu 			int flag;
   1050      1.34  pooka 			uint8_t *data;
   1051      1.34  pooka 
   1052      1.34  pooka 			if (pops->puffs_node_listextattr == NULL) {
   1053      1.34  pooka 				error = EOPNOTSUPP;
   1054      1.34  pooka 				break;
   1055      1.34  pooka 			}
   1056      1.34  pooka 
   1057      1.34  pooka 			if (auxt->pvnr_datasize)
   1058      1.34  pooka 				sizep = &auxt->pvnr_datasize;
   1059      1.34  pooka 			else
   1060      1.34  pooka 				sizep = NULL;
   1061      1.34  pooka 
   1062      1.34  pooka 			res = auxt->pvnr_resid;
   1063      1.34  pooka 			if (res > 0) {
   1064      1.34  pooka 				data = auxt->pvnr_data;
   1065      1.34  pooka 				resp = &auxt->pvnr_resid;
   1066      1.34  pooka 			} else {
   1067      1.34  pooka 				data = NULL;
   1068      1.34  pooka 				resp = NULL;
   1069      1.34  pooka 			}
   1070      1.34  pooka 
   1071      1.34  pooka 			res = auxt->pvnr_resid;
   1072      1.36   manu 			flag = auxt->pvnr_flag;
   1073      1.34  pooka 			error = pops->puffs_node_listextattr(pu,
   1074      1.34  pooka 			    opcookie, auxt->pvnr_attrnamespace,
   1075      1.36   manu 			    sizep, data, resp, flag, pcr);
   1076      1.34  pooka 
   1077      1.34  pooka 			/* need to move a bit more? */
   1078      1.34  pooka 			preq->preq_buflen =
   1079      1.34  pooka 			    sizeof(struct puffs_vnmsg_listextattr)
   1080      1.34  pooka 			    + (res - auxt->pvnr_resid);
   1081      1.34  pooka 			break;
   1082      1.34  pooka 		}
   1083      1.34  pooka 
   1084      1.34  pooka 		case PUFFS_VN_DELETEEXTATTR:
   1085      1.34  pooka 		{
   1086      1.34  pooka 			struct puffs_vnmsg_deleteextattr *auxt = auxbuf;
   1087      1.34  pooka 			PUFFS_MAKECRED(pcr, &auxt->pvnr_cred);
   1088      1.34  pooka 
   1089      1.34  pooka 			if (pops->puffs_node_deleteextattr == NULL) {
   1090      1.34  pooka 				error = EOPNOTSUPP;
   1091      1.34  pooka 				break;
   1092      1.34  pooka 			}
   1093      1.34  pooka 
   1094      1.34  pooka 			error = pops->puffs_node_deleteextattr(pu,
   1095      1.34  pooka 			    opcookie, auxt->pvnr_attrnamespace,
   1096      1.34  pooka 			    auxt->pvnr_attrname, pcr);
   1097      1.34  pooka 			break;
   1098      1.34  pooka 		}
   1099      1.34  pooka 
   1100       1.1  pooka 		default:
   1101       1.1  pooka 			printf("inval op %d\n", preq->preq_optype);
   1102       1.1  pooka 			error = EINVAL;
   1103       1.1  pooka 			break;
   1104       1.1  pooka 		}
   1105      1.30  pooka 
   1106      1.33  pooka #if 0
   1107      1.33  pooka 	/* not issued by kernel currently */
   1108      1.30  pooka 	} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_CACHE) {
   1109      1.30  pooka 		struct puffs_cacheinfo *pci = (void *)preq;
   1110      1.30  pooka 
   1111      1.30  pooka 		if (pu->pu_ops.puffs_cache_write) {
   1112      1.30  pooka 			pu->pu_ops.puffs_cache_write(pu, preq->preq_cookie,
   1113      1.30  pooka 			    pci->pcache_nruns, pci->pcache_runs);
   1114      1.30  pooka 		}
   1115      1.30  pooka 		error = 0;
   1116      1.33  pooka #endif
   1117      1.30  pooka 
   1118      1.30  pooka 	} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_ERROR) {
   1119      1.30  pooka 		struct puffs_error *perr = (void *)preq;
   1120      1.30  pooka 
   1121      1.30  pooka 		pu->pu_errnotify(pu, preq->preq_optype,
   1122      1.30  pooka 		    perr->perr_error, perr->perr_str, preq->preq_cookie);
   1123      1.30  pooka 		error = 0;
   1124       1.1  pooka 	} else {
   1125       1.1  pooka 		/*
   1126      1.30  pooka 		 * I guess the kernel sees this one coming also
   1127       1.1  pooka 		 */
   1128       1.1  pooka 		error = EINVAL;
   1129       1.1  pooka 	}
   1130      1.31  pooka 
   1131      1.31  pooka  out:
   1132       1.1  pooka 	preq->preq_rv = error;
   1133       1.1  pooka 
   1134      1.18  pooka 	if (pu->pu_oppost)
   1135      1.24  pooka 		pu->pu_oppost(pu);
   1136      1.18  pooka 
   1137      1.30  pooka 	pcc->pcc_flags |= PCC_DONE;
   1138       1.1  pooka }
   1139