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