Home | History | Annotate | Line # | Download | only in libpuffs
puffs.c revision 1.9
      1 /*	$NetBSD: puffs.c,v 1.9 2006/11/30 05:37:48 pooka Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2005, 2006  Antti Kantee.  All Rights Reserved.
      5  *
      6  * Development of this software was supported by the
      7  * Google Summer of Code program and the Ulla Tuominen Foundation.
      8  * The Google SoC project was mentored by Bill Studenmund.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. The name of the company nor the name of the author may be used to
     19  *    endorse or promote products derived from this software without specific
     20  *    prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     23  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     25  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32  * SUCH DAMAGE.
     33  */
     34 
     35 #include <sys/cdefs.h>
     36 #if !defined(lint)
     37 __RCSID("$NetBSD: puffs.c,v 1.9 2006/11/30 05:37:48 pooka Exp $");
     38 #endif /* !lint */
     39 
     40 #include <sys/param.h>
     41 #include <sys/mount.h>
     42 
     43 #include <assert.h>
     44 #include <errno.h>
     45 #include <fcntl.h>
     46 #include <puffs.h>
     47 #include <puffsdump.h>
     48 #include <stdio.h>
     49 #include <stdlib.h>
     50 #include <string.h>
     51 #include <syslog.h>
     52 #include <unistd.h>
     53 
     54 static int puffcall(struct puffs_usermount *, struct puffs_req *);
     55 
     56 struct puffs_usermount *
     57 puffs_mount(struct puffs_vfsops *pvfs, struct puffs_vnops *pvn,
     58 	const char *dir, int mntflags, const char *puffsname,
     59 	uint32_t pflags, size_t maxreqlen)
     60 {
     61 	struct puffs_startreq sreq;
     62 	struct puffs_args pargs;
     63 	struct puffs_usermount *pu;
     64 	int fd = 0, rv;
     65 
     66 	if (pvfs->puffs_mount == NULL) {
     67 		errno = EINVAL;
     68 		return NULL;
     69 	}
     70 
     71 	fd = open("/dev/puffs", O_RDONLY);
     72 	if (fd == -1)
     73 		return NULL;
     74 	assert(fd > 2);
     75 
     76 	pargs.pa_vers = 0; /* XXX: for now */
     77 	pargs.pa_flags = PUFFSFLAG_KERN(pflags);
     78 	pargs.pa_fd = fd;
     79 	pargs.pa_maxreqlen = maxreqlen;
     80 	(void)strlcpy(pargs.pa_name, puffsname, sizeof(pargs.pa_name));
     81 
     82 	pu = malloc(sizeof(struct puffs_usermount));
     83 	if (!pu)
     84 		return NULL;
     85 
     86 	pu->pu_flags = pflags;
     87 	pu->pu_pvfs = *pvfs;
     88 	pu->pu_pvn = *pvn;
     89 	pu->pu_fd = fd;
     90 	if ((pu->pu_rootpath = strdup(dir)) == NULL)
     91 		goto failfree;
     92 	LIST_INIT(&pu->pu_pnodelst);
     93 
     94 	if (mount(MOUNT_PUFFS, dir, mntflags, &pargs) == -1)
     95 		goto failfree;
     96 	pu->pu_maxreqlen = pargs.pa_maxreqlen;
     97 
     98 	if ((rv = pu->pu_pvfs.puffs_mount(pu, &sreq.psr_cookie)) != 0) {
     99 		errno = rv;
    100 		goto failfree;
    101 	}
    102 
    103 	if ((rv = pu->pu_pvfs.puffs_statvfs(pu, &sreq.psr_sb, 0)) != 0) {
    104 		errno = rv;
    105 		goto failfree;
    106 	}
    107 
    108 	/* tell kernel we're flying */
    109 	if (ioctl(pu->pu_fd, PUFFSSTARTOP, &sreq) == -1)
    110 		goto failfree;
    111 
    112 	return pu;
    113 
    114  failfree:
    115 	/* can't unmount() from here for obvious reasons */
    116 	if (fd)
    117 		close(fd);
    118 	free(pu);
    119 	return NULL;
    120 }
    121 
    122 int
    123 puffs_mainloop(struct puffs_usermount *pu, int flags)
    124 {
    125 	uint8_t *buf;
    126 	int rv;
    127 
    128 	buf = malloc(pu->pu_maxreqlen);
    129 	if (!buf)
    130 		return -1;
    131 
    132 	if ((flags & PUFFSLOOP_NODAEMON) == 0)
    133 		if (daemon(0, 0) == -1)
    134 			return -1;
    135 
    136 	for (;;)
    137 		if ((rv = puffs_oneop(pu, buf, pu->pu_maxreqlen)) != 0)
    138 			return rv;
    139 }
    140 
    141 int
    142 puffs_oneop(struct puffs_usermount *pu, uint8_t *buf, size_t buflen)
    143 {
    144 	struct puffs_req preq;
    145 	int rv;
    146 
    147 	preq.preq_aux = buf;
    148 	preq.preq_auxlen = buflen;
    149 
    150 	/* get op from kernel */
    151 	if (ioctl(pu->pu_fd, PUFFSGETOP, &preq) == -1)
    152 		return -1;
    153 
    154 	/* deal with it */
    155 	rv = puffcall(pu, &preq);
    156 
    157 	/* stuff result back to the kernel in case required */
    158 	if (PUFFSOP_WANTREPLY(preq.preq_opclass)) {
    159 		if (ioctl(pu->pu_fd, PUFFSPUTOP, &preq) == -1)
    160 			return -1;
    161 	}
    162 
    163 	return rv;
    164 }
    165 
    166 int
    167 puffs_getselectable(struct puffs_usermount *pu)
    168 {
    169 
    170 	return pu->pu_fd;
    171 }
    172 
    173 int
    174 puffs_setblockingmode(struct puffs_usermount *pu, int mode)
    175 {
    176 	int x;
    177 
    178 	x = mode;
    179 	return ioctl(pu->pu_fd, FIONBIO, &x);
    180 }
    181 
    182 static int
    183 puffcall(struct puffs_usermount *pu, struct puffs_req *preq)
    184 {
    185 	struct puffs_sizeop pop;
    186 	int error, rv;
    187 
    188 	rv = 0;
    189 
    190 	if (pu->pu_flags & PUFFSFLAG_OPDUMP)
    191 		puffsdump_req(preq);
    192 
    193 	if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VFS) {
    194 		switch (preq->preq_optype) {
    195 		case PUFFS_VFS_UNMOUNT:
    196 		{
    197 			struct puffs_vfsreq_unmount *auxt = preq->preq_aux;
    198 
    199 			error = pu->pu_pvfs.puffs_unmount(pu,
    200 			    auxt->pvfsr_flags, auxt->pvfsr_pid);
    201 			rv = 1;
    202 			break;
    203 		}
    204 		case PUFFS_VFS_STATVFS:
    205 		{
    206 			struct puffs_vfsreq_statvfs *auxt = preq->preq_aux;
    207 
    208 			error = pu->pu_pvfs.puffs_statvfs(pu,
    209 			    &auxt->pvfsr_sb, auxt->pvfsr_pid);
    210 			break;
    211 		}
    212 		case PUFFS_VFS_SYNC:
    213 		{
    214 			struct puffs_vfsreq_sync *auxt = preq->preq_aux;
    215 
    216 			error = pu->pu_pvfs.puffs_sync(pu,
    217 			    auxt->pvfsr_waitfor, &auxt->pvfsr_cred,
    218 			    auxt->pvfsr_pid);
    219 			break;
    220 		}
    221 		default:
    222 			/*
    223 			 * I guess the kernel sees this one coming
    224 			 */
    225 			error = EINVAL;
    226 			break;
    227 		}
    228 
    229 	/* XXX: audit return values */
    230 	} else if (PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN) {
    231 		switch (preq->preq_optype) {
    232 		case PUFFS_VN_LOOKUP:
    233 		{
    234 			struct puffs_vnreq_lookup *auxt = preq->preq_aux;
    235 
    236 			/* lookup *must* be present */
    237 			error = pu->pu_pvn.puffs_lookup(pu, preq->preq_cookie,
    238 			    &auxt->pvnr_newnode, &auxt->pvnr_vtype,
    239 			    &auxt->pvnr_size, &auxt->pvnr_rdev,
    240 			    &auxt->pvnr_cn);
    241 			break;
    242 		}
    243 
    244 		case PUFFS_VN_CREATE:
    245 		{
    246 			struct puffs_vnreq_create *auxt = preq->preq_aux;
    247 			if (pu->pu_pvn.puffs_create == NULL) {
    248 				error = 0;
    249 				break;
    250 			}
    251 
    252 			error = pu->pu_pvn.puffs_create(pu,
    253 			    preq->preq_cookie, &auxt->pvnr_newnode,
    254 			    &auxt->pvnr_cn, &auxt->pvnr_va);
    255 			break;
    256 		}
    257 
    258 		case PUFFS_VN_MKNOD:
    259 		{
    260 			struct puffs_vnreq_mknod *auxt = preq->preq_aux;
    261 			if (pu->pu_pvn.puffs_mknod == NULL) {
    262 				error = 0;
    263 				break;
    264 			}
    265 
    266 			error = pu->pu_pvn.puffs_mknod(pu,
    267 			    preq->preq_cookie, &auxt->pvnr_newnode,
    268 			    &auxt->pvnr_cn, &auxt->pvnr_va);
    269 			break;
    270 		}
    271 
    272 		case PUFFS_VN_OPEN:
    273 		{
    274 			struct puffs_vnreq_open *auxt = preq->preq_aux;
    275 			if (pu->pu_pvn.puffs_open == NULL) {
    276 				error = 0;
    277 				break;
    278 			}
    279 
    280 			error = pu->pu_pvn.puffs_open(pu,
    281 			    preq->preq_cookie, auxt->pvnr_mode,
    282 			    &auxt->pvnr_cred, auxt->pvnr_pid);
    283 			break;
    284 		}
    285 
    286 		case PUFFS_VN_CLOSE:
    287 		{
    288 			struct puffs_vnreq_close *auxt = preq->preq_aux;
    289 			if (pu->pu_pvn.puffs_close == NULL) {
    290 				error = 0;
    291 				break;
    292 			}
    293 
    294 			error = pu->pu_pvn.puffs_close(pu,
    295 			    preq->preq_cookie, auxt->pvnr_fflag,
    296 			    &auxt->pvnr_cred, auxt->pvnr_pid);
    297 			break;
    298 		}
    299 
    300 		case PUFFS_VN_ACCESS:
    301 		{
    302 			struct puffs_vnreq_access *auxt = preq->preq_aux;
    303 			if (pu->pu_pvn.puffs_access == NULL) {
    304 				error = 0;
    305 				break;
    306 			}
    307 
    308 			error = pu->pu_pvn.puffs_access(pu,
    309 			    preq->preq_cookie, auxt->pvnr_mode,
    310 			    &auxt->pvnr_cred, auxt->pvnr_pid);
    311 			break;
    312 		}
    313 
    314 		case PUFFS_VN_GETATTR:
    315 		{
    316 			struct puffs_vnreq_getattr *auxt = preq->preq_aux;
    317 			if (pu->pu_pvn.puffs_getattr == NULL) {
    318 				error = 0;
    319 				break;
    320 			}
    321 
    322 			error = pu->pu_pvn.puffs_getattr(pu,
    323 			    preq->preq_cookie, &auxt->pvnr_va,
    324 			    &auxt->pvnr_cred, auxt->pvnr_pid);
    325 			break;
    326 		}
    327 
    328 		case PUFFS_VN_SETATTR:
    329 		{
    330 			struct puffs_vnreq_setattr *auxt = preq->preq_aux;
    331 			if (pu->pu_pvn.puffs_setattr == NULL) {
    332 				error = 0;
    333 				break;
    334 			}
    335 
    336 			error = pu->pu_pvn.puffs_setattr(pu,
    337 			    preq->preq_cookie, &auxt->pvnr_va,
    338 			    &auxt->pvnr_cred, auxt->pvnr_pid);
    339 			break;
    340 		}
    341 
    342 /* notyet */
    343 #if 0
    344 		case PUFFS_VN_POLL:
    345 		{
    346 			struct puffs_vnreq_poll *auxt = preq->preq_aux;
    347 			if (pu->pu_pvn.puffs_poll == NULL) {
    348 				error = 0;
    349 				break;
    350 			}
    351 
    352 			error = pu->pu_pvn.puffs_poll(pu,
    353 			    preq->preq_cookie, preq-);
    354 			break;
    355 		}
    356 
    357 		case PUFFS_VN_KQFILTER:
    358 		{
    359 			struct puffs_vnreq_kqfilter *auxt = preq->preq_aux;
    360 			if (pu->pu_pvn.puffs_kqfilter == NULL) {
    361 				error = 0;
    362 				break;
    363 			}
    364 
    365 			error = pu->pu_pvn.puffs_kqfilter(pu,
    366 			    preq->preq_cookie, );
    367 			break;
    368 		}
    369 
    370 		case PUFFS_VN_MMAP:
    371 		{
    372 			struct puffs_vnreq_mmap *auxt = preq->preq_aux;
    373 			if (pu->pu_pvn.puffs_mmap == NULL) {
    374 				error = 0;
    375 				break;
    376 			}
    377 
    378 			error = pu->pu_pvn.puffs_mmap(pu,
    379 			    preq->preq_cookie, );
    380 			break;
    381 		}
    382 #endif
    383 
    384 		case PUFFS_VN_REVOKE:
    385 		{
    386 			struct puffs_vnreq_revoke *auxt = preq->preq_aux;
    387 			if (pu->pu_pvn.puffs_revoke == NULL) {
    388 				error = 0;
    389 				break;
    390 			}
    391 
    392 			error = pu->pu_pvn.puffs_revoke(pu,
    393 			    preq->preq_cookie, auxt->pvnr_flags);
    394 			break;
    395 		}
    396 
    397 		case PUFFS_VN_FSYNC:
    398 		{
    399 			struct puffs_vnreq_fsync *auxt = preq->preq_aux;
    400 			if (pu->pu_pvn.puffs_fsync == NULL) {
    401 				error = 0;
    402 				break;
    403 			}
    404 
    405 			error = pu->pu_pvn.puffs_fsync(pu,
    406 			    preq->preq_cookie, &auxt->pvnr_cred,
    407 			    auxt->pvnr_flags, auxt->pvnr_offlo,
    408 			    auxt->pvnr_offhi, auxt->pvnr_pid);
    409 			break;
    410 		}
    411 
    412 		case PUFFS_VN_SEEK:
    413 		{
    414 			struct puffs_vnreq_seek *auxt = preq->preq_aux;
    415 			if (pu->pu_pvn.puffs_seek == NULL) {
    416 				error = 0;
    417 				break;
    418 			}
    419 
    420 			error = pu->pu_pvn.puffs_seek(pu,
    421 			    preq->preq_cookie, auxt->pvnr_oldoff,
    422 			    auxt->pvnr_newoff, &auxt->pvnr_cred);
    423 			break;
    424 		}
    425 
    426 		case PUFFS_VN_REMOVE:
    427 		{
    428 			struct puffs_vnreq_remove *auxt = preq->preq_aux;
    429 			if (pu->pu_pvn.puffs_remove == NULL) {
    430 				error = 0;
    431 				break;
    432 			}
    433 
    434 			error = pu->pu_pvn.puffs_remove(pu,
    435 			    preq->preq_cookie, auxt->pvnr_cookie_targ,
    436 			    &auxt->pvnr_cn);
    437 			break;
    438 		}
    439 
    440 		case PUFFS_VN_LINK:
    441 		{
    442 			struct puffs_vnreq_link *auxt = preq->preq_aux;
    443 			if (pu->pu_pvn.puffs_link == NULL) {
    444 				error = 0;
    445 				break;
    446 			}
    447 
    448 			error = pu->pu_pvn.puffs_link(pu,
    449 			    preq->preq_cookie, auxt->pvnr_cookie_targ,
    450 			    &auxt->pvnr_cn);
    451 			break;
    452 		}
    453 
    454 		case PUFFS_VN_RENAME:
    455 		{
    456 			struct puffs_vnreq_rename *auxt = preq->preq_aux;
    457 			if (pu->pu_pvn.puffs_rename == NULL) {
    458 				error = 0;
    459 				break;
    460 			}
    461 
    462 			error = pu->pu_pvn.puffs_rename(pu,
    463 			    preq->preq_cookie, auxt->pvnr_cookie_src,
    464 			    &auxt->pvnr_cn_src, auxt->pvnr_cookie_targdir,
    465 			    auxt->pvnr_cookie_targ, &auxt->pvnr_cn_targ);
    466 			break;
    467 		}
    468 
    469 		case PUFFS_VN_MKDIR:
    470 		{
    471 			struct puffs_vnreq_mkdir *auxt = preq->preq_aux;
    472 			if (pu->pu_pvn.puffs_mkdir == NULL) {
    473 				error = 0;
    474 				break;
    475 			}
    476 
    477 			error = pu->pu_pvn.puffs_mkdir(pu,
    478 			    preq->preq_cookie, &auxt->pvnr_newnode,
    479 			    &auxt->pvnr_cn, &auxt->pvnr_va);
    480 			break;
    481 		}
    482 
    483 		case PUFFS_VN_RMDIR:
    484 		{
    485 			struct puffs_vnreq_rmdir *auxt = preq->preq_aux;
    486 			if (pu->pu_pvn.puffs_rmdir == NULL) {
    487 				error = 0;
    488 				break;
    489 			}
    490 
    491 			error = pu->pu_pvn.puffs_rmdir(pu,
    492 			    preq->preq_cookie, auxt->pvnr_cookie_targ,
    493 			    &auxt->pvnr_cn);
    494 			break;
    495 		}
    496 
    497 		case PUFFS_VN_SYMLINK:
    498 		{
    499 			struct puffs_vnreq_symlink *auxt = preq->preq_aux;
    500 			if (pu->pu_pvn.puffs_symlink == NULL) {
    501 				error = 0;
    502 				break;
    503 			}
    504 
    505 			error = pu->pu_pvn.puffs_symlink(pu,
    506 			    preq->preq_cookie, &auxt->pvnr_newnode,
    507 			    &auxt->pvnr_cn, &auxt->pvnr_va, auxt->pvnr_link);
    508 			break;
    509 		}
    510 
    511 		case PUFFS_VN_READDIR:
    512 		{
    513 			struct puffs_vnreq_readdir *auxt = preq->preq_aux;
    514 			size_t res;
    515 
    516 			if (pu->pu_pvn.puffs_readdir == NULL) {
    517 				error = 0;
    518 				break;
    519 			}
    520 
    521 			res = auxt->pvnr_resid;
    522 			error = pu->pu_pvn.puffs_readdir(pu,
    523 			    preq->preq_cookie, auxt->pvnr_dent,
    524 			    &auxt->pvnr_cred, &auxt->pvnr_offset,
    525 			    &auxt->pvnr_resid);
    526 
    527 			/* need to move a bit more */
    528 			preq->preq_auxlen += res - auxt->pvnr_resid;
    529 			break;
    530 		}
    531 
    532 		case PUFFS_VN_READLINK:
    533 		{
    534 			struct puffs_vnreq_readlink *auxt = preq->preq_aux;
    535 			if (pu->pu_pvn.puffs_readlink == NULL) {
    536 				error = EOPNOTSUPP;
    537 				break;
    538 			}
    539 
    540 			error = pu->pu_pvn.puffs_readlink(pu,
    541 			    preq->preq_cookie, &auxt->pvnr_cred,
    542 			    auxt->pvnr_link, &auxt->pvnr_linklen);
    543 			break;
    544 		}
    545 
    546 		case PUFFS_VN_RECLAIM:
    547 		{
    548 			struct puffs_vnreq_reclaim *auxt = preq->preq_aux;
    549 			if (pu->pu_pvn.puffs_reclaim == NULL) {
    550 				error = 0;
    551 				break;
    552 			}
    553 
    554 			error = pu->pu_pvn.puffs_reclaim(pu,
    555 			    preq->preq_cookie, auxt->pvnr_pid);
    556 			break;
    557 		}
    558 
    559 		case PUFFS_VN_INACTIVE:
    560 		{
    561 			struct puffs_vnreq_inactive *auxt = preq->preq_aux;
    562 			if (pu->pu_pvn.puffs_inactive == NULL) {
    563 				error = EOPNOTSUPP;
    564 				break;
    565 			}
    566 
    567 			error = pu->pu_pvn.puffs_inactive(pu,
    568 			    preq->preq_cookie, auxt->pvnr_pid,
    569 			    &auxt->pvnr_backendrefs);
    570 			break;
    571 		}
    572 
    573 		case PUFFS_VN_PATHCONF:
    574 		{
    575 			struct puffs_vnreq_pathconf *auxt = preq->preq_aux;
    576 			if (pu->pu_pvn.puffs_pathconf == NULL) {
    577 				error = 0;
    578 				break;
    579 			}
    580 
    581 			error = pu->pu_pvn.puffs_pathconf(pu,
    582 			    preq->preq_cookie, auxt->pvnr_name,
    583 			    &auxt->pvnr_retval);
    584 			break;
    585 		}
    586 
    587 		case PUFFS_VN_ADVLOCK:
    588 		{
    589 			struct puffs_vnreq_advlock *auxt = preq->preq_aux;
    590 			if (pu->pu_pvn.puffs_advlock == NULL) {
    591 				error = 0;
    592 				break;
    593 			}
    594 
    595 			error = pu->pu_pvn.puffs_advlock(pu,
    596 			    preq->preq_cookie, auxt->pvnr_id, auxt->pvnr_op,
    597 			    &auxt->pvnr_fl, auxt->pvnr_flags);
    598 			break;
    599 		}
    600 
    601 		case PUFFS_VN_PRINT:
    602 		{
    603 			if (pu->pu_pvn.puffs_print == NULL) {
    604 				error = 0;
    605 				break;
    606 			}
    607 
    608 			error = pu->pu_pvn.puffs_print(pu,
    609 			    preq->preq_cookie);
    610 			break;
    611 		}
    612 
    613 		case PUFFS_VN_READ:
    614 		{
    615 			struct puffs_vnreq_read *auxt = preq->preq_aux;
    616 			size_t res;
    617 
    618 			if (pu->pu_pvn.puffs_read == NULL) {
    619 				error = EIO;
    620 				break;
    621 			}
    622 
    623 			res = auxt->pvnr_resid;
    624 			error = pu->pu_pvn.puffs_read(pu,
    625 			    preq->preq_cookie, auxt->pvnr_data,
    626 			    auxt->pvnr_offset, &auxt->pvnr_resid,
    627 			    &auxt->pvnr_cred, auxt->pvnr_ioflag);
    628 
    629 			/* need to move a bit more */
    630 			preq->preq_auxlen += res - auxt->pvnr_resid;
    631 			break;
    632 		}
    633 
    634 		case PUFFS_VN_WRITE:
    635 		{
    636 			struct puffs_vnreq_write *auxt = preq->preq_aux;
    637 
    638 			if (pu->pu_pvn.puffs_write == NULL) {
    639 				error = EIO;
    640 				break;
    641 			}
    642 
    643 			error = pu->pu_pvn.puffs_write(pu,
    644 			    preq->preq_cookie, auxt->pvnr_data,
    645 			    auxt->pvnr_offset, &auxt->pvnr_resid,
    646 			    &auxt->pvnr_cred, auxt->pvnr_ioflag);
    647 
    648 			/* don't need to move data back to the kernel */
    649 			preq->preq_auxlen = sizeof(struct puffs_vnreq_write);
    650 			break;
    651 		}
    652 
    653 		case PUFFS_VN_IOCTL:
    654 			error = pu->pu_pvn.puffs_ioctl1(pu, preq->preq_cookie,
    655 			     (struct puffs_vnreq_ioctl *)preq->preq_aux, &pop);
    656 			if (error != 0)
    657 				break;
    658 			pop.pso_reqid = preq->preq_id;
    659 
    660 			/* let the kernel do it's intermediate duty */
    661 			error = ioctl(pu->pu_fd, PUFFSSIZEOP, &pop);
    662 			/*
    663 			 * XXX: I don't actually know what the correct
    664 			 * thing to do in case of an error is, so I'll
    665 			 * just ignore it for the time being.
    666 			 */
    667 			error = pu->pu_pvn.puffs_ioctl2(pu, preq->preq_cookie,
    668 			    (struct puffs_vnreq_ioctl *)preq->preq_aux, &pop);
    669 			break;
    670 
    671 		case PUFFS_VN_FCNTL:
    672 			error = pu->pu_pvn.puffs_fcntl1(pu, preq->preq_cookie,
    673 			     (struct puffs_vnreq_fcntl *)preq->preq_aux, &pop);
    674 			if (error != 0)
    675 				break;
    676 			pop.pso_reqid = preq->preq_id;
    677 
    678 			/* let the kernel do it's intermediate duty */
    679 			error = ioctl(pu->pu_fd, PUFFSSIZEOP, &pop);
    680 			/*
    681 			 * XXX: I don't actually know what the correct
    682 			 * thing to do in case of an error is, so I'll
    683 			 * just ignore it for the time being.
    684 			 */
    685 			error = pu->pu_pvn.puffs_fcntl2(pu, preq->preq_cookie,
    686 			    (struct puffs_vnreq_fcntl *)preq->preq_aux, &pop);
    687 			break;
    688 
    689 		default:
    690 			printf("inval op %d\n", preq->preq_optype);
    691 			error = EINVAL;
    692 			break;
    693 		}
    694 	} else {
    695 		/*
    696 		 * this one also
    697 		 */
    698 		error = EINVAL;
    699 	}
    700 
    701 	preq->preq_rv = error;
    702 	return rv;
    703 }
    704 
    705 
    706 #if 0
    707 		case PUFFS_VN_IOCTL:
    708 		{
    709 			struct puffs_vnreq_ioctl *auxt = preq->preq_aux;
    710 			if (pu->pu_pvn.puffs_ioctl == NULL) {
    711 				error = 0;
    712 				break;
    713 			}
    714 
    715 			error = pu->pu_pvn.puffs_ioctl(pu,
    716 			    preq->preq_cookie, );
    717 			break;
    718 		}
    719 
    720 		case PUFFS_VN_FCNTL:
    721 		{
    722 			struct puffs_vnreq_fcntl *auxt = preq->preq_aux;
    723 			if (pu->pu_pvn.puffs_fcntl == NULL) {
    724 				error = 0;
    725 				break;
    726 			}
    727 
    728 			error = pu->pu_pvn.puffs_fcntl(pu,
    729 			    preq->preq_cookie, );
    730 			break;
    731 		}
    732 
    733 
    734 		case PUFFS_VN_ABORTOP:
    735 		{
    736 			struct puffs_vnreq_abortop *auxt = preq->preq_aux;
    737 			if (pu->pu_pvn.puffs_abortop == NULL) {
    738 				error = 0;
    739 				break;
    740 			}
    741 
    742 			error = pu->pu_pvn.puffs_abortop(pu,
    743 			    preq->preq_cookie, );
    744 			break;
    745 		}
    746 
    747 		case PUFFS_VN_LOCK:
    748 		{
    749 			struct puffs_vnreq_lock *auxt = preq->preq_aux;
    750 			if (pu->pu_pvn.puffs_lock == NULL) {
    751 				error = 0;
    752 				break;
    753 			}
    754 
    755 			error = pu->pu_pvn.puffs_lock(pu,
    756 			    preq->preq_cookie, );
    757 			break;
    758 		}
    759 
    760 		case PUFFS_VN_UNLOCK:
    761 		{
    762 			struct puffs_vnreq_unlock *auxt = preq->preq_aux;
    763 			if (pu->pu_pvn.puffs_unlock == NULL) {
    764 				error = 0;
    765 				break;
    766 			}
    767 
    768 			error = pu->pu_pvn.puffs_unlock(pu,
    769 			    preq->preq_cookie, );
    770 			break;
    771 		}
    772 
    773 		case PUFFS_VN_ISLOCKED:
    774 		{
    775 			struct puffs_vnreq_islocked *auxt = preq->preq_aux;
    776 			if (pu->pu_pvn.puffs_islocked == NULL) {
    777 				error = 0;
    778 				break;
    779 			}
    780 
    781 			error = pu->pu_pvn.puffs_islocked(pu,
    782 			    preq->preq_cookie, );
    783 			break;
    784 		}
    785 
    786 		case PUFFS_VN_LEASE:
    787 		{
    788 			struct puffs_vnreq_lease *auxt = preq->preq_aux;
    789 			if (pu->pu_pvn.puffs_lease == NULL) {
    790 				error = 0;
    791 				break;
    792 			}
    793 
    794 			error = pu->pu_pvn.puffs_lease(pu,
    795 			    preq->preq_cookie, );
    796 			break;
    797 		}
    798 
    799 		case PUFFS_VN_WHITEOUT:
    800 		{
    801 			struct puffs_vnreq_whiteout *auxt = preq->preq_aux;
    802 			if (pu->pu_pvn.puffs_whiteout == NULL) {
    803 				error = 0;
    804 				break;
    805 			}
    806 
    807 			error = pu->pu_pvn.puffs_whiteout(pu,
    808 			    preq->preq_cookie, );
    809 			break;
    810 		}
    811 
    812 		case PUFFS_VN_CLOSEEXTATTR:
    813 		{
    814 			struct puffs_vnreq_closeextattr *auxt = preq->preq_aux;
    815 			if (pu->pu_pvn.puffs_closeextattr == NULL) {
    816 				error = 0;
    817 				break;
    818 			}
    819 
    820 			error = pu->pu_pvn.puffs_closeextattr(pu,
    821 			    preq->preq_cookie, );
    822 			break;
    823 		}
    824 
    825 		case PUFFS_VN_GETEXTATTR:
    826 		{
    827 			struct puffs_vnreq_getextattr *auxt = preq->preq_aux;
    828 			if (pu->pu_pvn.puffs_getextattr == NULL) {
    829 				error = 0;
    830 				break;
    831 			}
    832 
    833 			error = pu->pu_pvn.puffs_getextattr(pu,
    834 			    preq->preq_cookie, );
    835 			break;
    836 		}
    837 
    838 		case PUFFS_VN_LISTEXTATTR:
    839 		{
    840 			struct puffs_vnreq_listextattr *auxt = preq->preq_aux;
    841 			if (pu->pu_pvn.puffs_listextattr == NULL) {
    842 				error = 0;
    843 				break;
    844 			}
    845 
    846 			error = pu->pu_pvn.puffs_listextattr(pu,
    847 			    preq->preq_cookie, );
    848 			break;
    849 		}
    850 
    851 		case PUFFS_VN_OPENEXTATTR:
    852 		{
    853 			struct puffs_vnreq_openextattr *auxt = preq->preq_aux;
    854 			if (pu->pu_pvn.puffs_openextattr == NULL) {
    855 				error = 0;
    856 				break;
    857 			}
    858 
    859 			error = pu->pu_pvn.puffs_openextattr(pu,
    860 			    preq->preq_cookie, );
    861 			break;
    862 		}
    863 
    864 		case PUFFS_VN_DELETEEXTATTR:
    865 		{
    866 			struct puffs_vnreq_deleteextattr *auxt = preq->preq_aux;
    867 			if (pu->pu_pvn.puffs_deleteextattr == NULL) {
    868 				error = 0;
    869 				break;
    870 			}
    871 
    872 			error = pu->pu_pvn.puffs_deleteextattr(pu,
    873 			    preq->preq_cookie, );
    874 			break;
    875 		}
    876 
    877 		case PUFFS_VN_SETEXTATTR:
    878 		{
    879 			struct puffs_vnreq_setextattr *auxt = preq->preq_aux;
    880 			if (pu->pu_pvn.puffs_setextattr == NULL) {
    881 				error = 0;
    882 				break;
    883 			}
    884 
    885 			error = pu->pu_pvn.puffs_setextattr(pu,
    886 			    preq->preq_cookie, );
    887 			break;
    888 		}
    889 
    890 #endif
    891