[BACK]Return to puffs.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libpuffs

Annotation of src/lib/libpuffs/puffs.c, Revision 1.48

1.48    ! pooka       1: /*     $NetBSD: puffs.c,v 1.47 2007/05/15 16:45:22 pooka Exp $ */
1.1       pooka       2:
                      3: /*
1.44      pooka       4:  * Copyright (c) 2005, 2006, 2007  Antti Kantee.  All Rights Reserved.
1.1       pooka       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)
1.48    ! pooka      37: __RCSID("$NetBSD: puffs.c,v 1.47 2007/05/15 16:45:22 pooka Exp $");
1.1       pooka      38: #endif /* !lint */
                     39:
                     40: #include <sys/param.h>
                     41: #include <sys/mount.h>
                     42:
1.9       pooka      43: #include <assert.h>
1.12      pooka      44: #include <err.h>
1.1       pooka      45: #include <errno.h>
                     46: #include <fcntl.h>
1.21      pooka      47: #include <mntopts.h>
1.1       pooka      48: #include <puffs.h>
                     49: #include <stdio.h>
                     50: #include <stdlib.h>
                     51: #include <string.h>
                     52: #include <syslog.h>
                     53: #include <unistd.h>
                     54:
1.19      pooka      55: #include "puffs_priv.h"
                     56:
1.21      pooka      57: /* Most file systems want this for opts, so just give it to them */
                     58: const struct mntopt puffsmopts[] = {
                     59:        MOPT_STDOPTS,
                     60:        PUFFSMOPT_STD,
                     61:        MOPT_NULL,
                     62: };
                     63:
1.10      pooka      64: #define FILLOP(lower, upper)                                           \
                     65: do {                                                                   \
1.13      pooka      66:        if (pops->puffs_node_##lower)                                   \
1.10      pooka      67:                opmask[PUFFS_VN_##upper] = 1;                           \
                     68: } while (/*CONSTCOND*/0)
                     69: static void
1.13      pooka      70: fillvnopmask(struct puffs_ops *pops, uint8_t *opmask)
1.10      pooka      71: {
                     72:
                     73:        memset(opmask, 0, PUFFS_VN_MAX);
                     74:
                     75:        FILLOP(create,   CREATE);
                     76:        FILLOP(mknod,    MKNOD);
                     77:        FILLOP(open,     OPEN);
                     78:        FILLOP(close,    CLOSE);
                     79:        FILLOP(access,   ACCESS);
                     80:        FILLOP(getattr,  GETATTR);
                     81:        FILLOP(setattr,  SETATTR);
                     82:        FILLOP(poll,     POLL); /* XXX: not ready in kernel */
1.16      pooka      83:        FILLOP(mmap,     MMAP);
1.10      pooka      84:        FILLOP(fsync,    FSYNC);
                     85:        FILLOP(seek,     SEEK);
                     86:        FILLOP(remove,   REMOVE);
                     87:        FILLOP(link,     LINK);
                     88:        FILLOP(rename,   RENAME);
                     89:        FILLOP(mkdir,    MKDIR);
                     90:        FILLOP(rmdir,    RMDIR);
                     91:        FILLOP(symlink,  SYMLINK);
                     92:        FILLOP(readdir,  READDIR);
                     93:        FILLOP(readlink, READLINK);
                     94:        FILLOP(reclaim,  RECLAIM);
                     95:        FILLOP(inactive, INACTIVE);
                     96:        FILLOP(print,    PRINT);
                     97:        FILLOP(read,     READ);
                     98:        FILLOP(write,    WRITE);
                     99:
                    100:        /* XXX: not implemented in the kernel */
                    101:        FILLOP(getextattr, GETEXTATTR);
                    102:        FILLOP(setextattr, SETEXTATTR);
                    103:        FILLOP(listextattr, LISTEXTATTR);
1.19      pooka     104: }
                    105: #undef FILLOP
                    106:
                    107: int
                    108: puffs_getselectable(struct puffs_usermount *pu)
                    109: {
1.10      pooka     110:
1.36      pooka     111:        return pu->pu_kargs.pa_fd;
1.10      pooka     112: }
1.19      pooka     113:
                    114: int
                    115: puffs_setblockingmode(struct puffs_usermount *pu, int mode)
                    116: {
1.46      pooka     117:        int rv, x;
                    118:
                    119:        if (mode != PUFFSDEV_BLOCK && mode != PUFFSDEV_NONBLOCK) {
                    120:                errno = EINVAL;
                    121:                return -1;
                    122:        }
1.19      pooka     123:
                    124:        x = mode;
1.46      pooka     125:        rv = ioctl(pu->pu_kargs.pa_fd, FIONBIO, &x);
                    126:
                    127:        if (rv == 0) {
                    128:                if (mode == PUFFSDEV_BLOCK)
                    129:                        pu->pu_state &= ~PU_ASYNCFD;
                    130:                else
                    131:                        pu->pu_state |= PU_ASYNCFD;
                    132:        }
                    133:
                    134:        return rv;
1.19      pooka     135: }
                    136:
                    137: int
                    138: puffs_getstate(struct puffs_usermount *pu)
                    139: {
                    140:
1.44      pooka     141:        return pu->pu_state & PU_STATEMASK;
1.19      pooka     142: }
                    143:
                    144: void
                    145: puffs_setstacksize(struct puffs_usermount *pu, size_t ss)
                    146: {
                    147:
                    148:        pu->pu_cc_stacksize = ss;
                    149: }
                    150:
1.24      pooka     151: struct puffs_pathobj *
                    152: puffs_getrootpathobj(struct puffs_usermount *pu)
1.19      pooka     153: {
                    154:        struct puffs_node *pnr;
                    155:
                    156:        pnr = pu->pu_pn_root;
                    157:        if (pnr == NULL) {
                    158:                errno = ENOENT;
1.24      pooka     159:                return NULL;
1.19      pooka     160:        }
                    161:
1.24      pooka     162:        return &pnr->pn_po;
                    163: }
                    164:
1.35      pooka     165: void
                    166: puffs_setroot(struct puffs_usermount *pu, struct puffs_node *pn)
                    167: {
                    168:
                    169:        pu->pu_pn_root = pn;
                    170: }
                    171:
                    172: struct puffs_node *
                    173: puffs_getroot(struct puffs_usermount *pu)
                    174: {
                    175:
                    176:        return pu->pu_pn_root;
                    177: }
                    178:
                    179: void *
                    180: puffs_getspecific(struct puffs_usermount *pu)
                    181: {
                    182:
                    183:        return pu->pu_privdata;
                    184: }
                    185:
                    186: size_t
                    187: puffs_getmaxreqlen(struct puffs_usermount *pu)
                    188: {
                    189:
1.36      pooka     190:        return pu->pu_kargs.pa_maxreqlen;
1.35      pooka     191: }
1.24      pooka     192:
                    193: void
1.37      pooka     194: puffs_setmaxreqlen(struct puffs_usermount *pu, size_t reqlen)
                    195: {
                    196:
1.44      pooka     197:        if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT)
1.37      pooka     198:                warnx("puffs_setmaxreqlen: call has effect only "
                    199:                    "before mount\n");
                    200:
                    201:        pu->pu_kargs.pa_maxreqlen = reqlen;
                    202: }
                    203:
                    204: void
1.38      pooka     205: puffs_setfhsize(struct puffs_usermount *pu, size_t fhsize, int flags)
1.37      pooka     206: {
                    207:
1.44      pooka     208:        if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT)
1.37      pooka     209:                warnx("puffs_setfhsize: call has effect only before mount\n");
                    210:
                    211:        pu->pu_kargs.pa_fhsize = fhsize;
1.38      pooka     212:        pu->pu_kargs.pa_fhflags = flags;
1.37      pooka     213: }
                    214:
                    215: void
                    216: puffs_setncookiehash(struct puffs_usermount *pu, int nhash)
                    217: {
                    218:
1.44      pooka     219:        if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT)
1.37      pooka     220:                warnx("puffs_setfhsize: call has effect only before mount\n");
                    221:
                    222:        pu->pu_kargs.pa_nhashbuckets = nhash;
                    223: }
                    224:
                    225: void
1.24      pooka     226: puffs_set_pathbuild(struct puffs_usermount *pu, pu_pathbuild_fn fn)
                    227: {
                    228:
                    229:        pu->pu_pathbuild = fn;
                    230: }
                    231:
                    232: void
                    233: puffs_set_pathtransform(struct puffs_usermount *pu, pu_pathtransform_fn fn)
                    234: {
                    235:
                    236:        pu->pu_pathtransform = fn;
                    237: }
                    238:
                    239: void
                    240: puffs_set_pathcmp(struct puffs_usermount *pu, pu_pathcmp_fn fn)
                    241: {
                    242:
                    243:        pu->pu_pathcmp = fn;
                    244: }
                    245:
                    246: void
                    247: puffs_set_pathfree(struct puffs_usermount *pu, pu_pathfree_fn fn)
                    248: {
1.19      pooka     249:
1.24      pooka     250:        pu->pu_pathfree = fn;
1.19      pooka     251: }
                    252:
1.24      pooka     253: void
                    254: puffs_set_namemod(struct puffs_usermount *pu, pu_namemod_fn fn)
                    255: {
                    256:
                    257:        pu->pu_namemod = fn;
                    258: }
1.19      pooka     259:
1.40      pooka     260: void
1.46      pooka     261: puffs_ml_setloopfn(struct puffs_usermount *pu, puffs_ml_loop_fn lfn)
                    262: {
                    263:
                    264:        pu->pu_ml_lfn = lfn;
                    265: }
                    266:
                    267: void
                    268: puffs_ml_settimeout(struct puffs_usermount *pu, struct timespec *ts)
                    269: {
                    270:
                    271:        if (ts == NULL) {
                    272:                pu->pu_ml_timep = NULL;
                    273:        } else {
                    274:                pu->pu_ml_timeout = *ts;
                    275:                pu->pu_ml_timep = &pu->pu_ml_timeout;
                    276:        }
                    277: }
                    278:
                    279: void
1.40      pooka     280: puffs_setback(struct puffs_cc *pcc, int whatback)
                    281: {
                    282:        struct puffs_req *preq = pcc->pcc_preq;
                    283:
                    284:        assert(PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN && (
                    285:            preq->preq_optype == PUFFS_VN_OPEN ||
                    286:            preq->preq_optype == PUFFS_VN_MMAP ||
                    287:            preq->preq_optype == PUFFS_VN_REMOVE ||
                    288:            preq->preq_optype == PUFFS_VN_RMDIR));
                    289:
                    290:        preq->preq_setbacks |= whatback & PUFFS_SETBACK_MASK;
                    291: }
                    292:
1.36      pooka     293: int
                    294: puffs_domount(struct puffs_usermount *pu, const char *dir, int mntflags)
                    295: {
                    296:
                    297: #if 1
                    298:        /* XXXkludgehere */
                    299:        /* kauth doesn't provide this service any longer */
                    300:        if (geteuid() != 0)
                    301:                mntflags |= MNT_NOSUID | MNT_NODEV;
                    302: #endif
                    303:
                    304:        if (mount(MOUNT_PUFFS, dir, mntflags, &pu->pu_kargs) == -1)
                    305:                return -1;
1.44      pooka     306:        PU_SETSTATE(pu, PUFFS_STATE_MOUNTING);
1.36      pooka     307:
                    308:        return 0;
                    309: }
1.10      pooka     310:
1.1       pooka     311: struct puffs_usermount *
1.36      pooka     312: _puffs_init(int develv, struct puffs_ops *pops, const char *puffsname,
                    313:        void *priv, uint32_t pflags)
1.1       pooka     314: {
                    315:        struct puffs_usermount *pu;
1.36      pooka     316:        struct puffs_kargs *pargs;
                    317:        int fd;
1.1       pooka     318:
1.20      pooka     319:        if (develv != PUFFS_DEVEL_LIBVERSION) {
                    320:                warnx("puffs_mount: mounting with lib version %d, need %d",
                    321:                    develv, PUFFS_DEVEL_LIBVERSION);
                    322:                errno = EINVAL;
                    323:                return NULL;
                    324:        }
                    325:
1.1       pooka     326:        fd = open("/dev/puffs", O_RDONLY);
                    327:        if (fd == -1)
                    328:                return NULL;
1.12      pooka     329:        if (fd <= 2)
                    330:                warnx("puffs_mount: device fd %d (<= 2), sure this is "
                    331:                    "what you want?", fd);
1.1       pooka     332:
1.36      pooka     333:        pu = malloc(sizeof(struct puffs_usermount));
                    334:        if (pu == NULL)
                    335:                goto failfree;
1.47      pooka     336:        memset(pu, 0, sizeof(struct puffs_usermount));
1.1       pooka     337:
1.36      pooka     338:        pargs = &pu->pu_kargs;
                    339:        pargs->pa_vers = PUFFSDEVELVERS | PUFFSVERSION;
                    340:        pargs->pa_flags = PUFFS_FLAG_KERN(pflags);
                    341:        pargs->pa_fd = fd;
                    342:        fillvnopmask(pops, pargs->pa_vnopmask);
                    343:        (void)strlcpy(pargs->pa_name, puffsname, sizeof(pargs->pa_name));
1.1       pooka     344:
                    345:        pu->pu_flags = pflags;
1.13      pooka     346:        pu->pu_ops = *pops;
1.21      pooka     347:        free(pops); /* XXX */
1.36      pooka     348:
1.19      pooka     349:        pu->pu_privdata = priv;
                    350:        pu->pu_cc_stacksize = PUFFS_CC_STACKSIZE_DEFAULT;
1.1       pooka     351:        LIST_INIT(&pu->pu_pnodelst);
1.44      pooka     352:        LIST_INIT(&pu->pu_framectrl.fb_ios);
1.46      pooka     353:        LIST_INIT(&pu->pu_ccnukelst);
1.1       pooka     354:
1.24      pooka     355:        /* defaults for some user-settable translation functions */
                    356:        pu->pu_cmap = NULL; /* identity translation */
                    357:
1.30      pooka     358:        pu->pu_pathbuild = puffs_stdpath_buildpath;
                    359:        pu->pu_pathfree = puffs_stdpath_freepath;
                    360:        pu->pu_pathcmp = puffs_stdpath_cmppath;
1.24      pooka     361:        pu->pu_pathtransform = NULL;
                    362:        pu->pu_namemod = NULL;
                    363:
1.44      pooka     364:        PU_SETSTATE(pu, PUFFS_STATE_BEFOREMOUNT);
1.1       pooka     365:
                    366:        return pu;
1.6       pooka     367:
1.1       pooka     368:  failfree:
1.6       pooka     369:        /* can't unmount() from here for obvious reasons */
1.36      pooka     370:        close(fd);
1.1       pooka     371:        free(pu);
                    372:        return NULL;
                    373: }
                    374:
1.36      pooka     375: struct puffs_usermount *
                    376: _puffs_mount(int develv, struct puffs_ops *pops, const char *dir, int mntflags,
                    377:        const char *puffsname, void *priv, uint32_t pflags)
                    378: {
                    379:        struct puffs_usermount *pu;
                    380:        int sverrno;
                    381:
                    382:        pu = _puffs_init(develv, pops, puffsname, priv, pflags);
                    383:        if (pu == NULL)
                    384:                return NULL;
                    385:
                    386:        if (puffs_domount(pu, dir, mntflags) == -1) {
                    387:                sverrno = errno;
                    388:                puffs_exit(pu, 1);
                    389:                errno = sverrno;
                    390:                return NULL;
                    391:        }
                    392:
                    393:        return pu;
                    394: }
                    395:
1.1       pooka     396: int
1.21      pooka     397: puffs_start(struct puffs_usermount *pu, void *rootcookie, struct statvfs *sbp)
                    398: {
                    399:        struct puffs_startreq sreq;
                    400:
                    401:        memset(&sreq, 0, sizeof(struct puffs_startreq));
                    402:        sreq.psr_cookie = rootcookie;
                    403:        sreq.psr_sb = *sbp;
                    404:
                    405:        /* tell kernel we're flying */
1.36      pooka     406:        if (ioctl(pu->pu_kargs.pa_fd, PUFFSSTARTOP, &sreq) == -1)
1.21      pooka     407:                return -1;
                    408:
1.44      pooka     409:        PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
1.21      pooka     410:
                    411:        return 0;
                    412: }
                    413:
                    414: /*
                    415:  * XXX: there's currently no clean way to request unmount from
                    416:  * within the user server, so be very brutal about it.
                    417:  */
1.36      pooka     418: /*ARGSUSED1*/
1.21      pooka     419: int
                    420: puffs_exit(struct puffs_usermount *pu, int force)
                    421: {
1.44      pooka     422:        struct puffs_node *pn;
1.21      pooka     423:
                    424:        force = 1; /* currently */
                    425:
1.36      pooka     426:        if (pu->pu_kargs.pa_fd)
                    427:                close(pu->pu_kargs.pa_fd);
1.21      pooka     428:
1.44      pooka     429:        while ((pn = LIST_FIRST(&pu->pu_pnodelst)) != NULL)
1.24      pooka     430:                puffs_pn_put(pn);
1.44      pooka     431:
1.46      pooka     432:        puffs_framev_exit(pu);
1.44      pooka     433:        if (pu->pu_haskq)
                    434:                close(pu->pu_kq);
1.21      pooka     435:        free(pu);
                    436:
                    437:        return 0; /* always succesful for now, WILL CHANGE */
                    438: }
                    439:
                    440: int
1.9       pooka     441: puffs_mainloop(struct puffs_usermount *pu, int flags)
1.1       pooka     442: {
1.44      pooka     443:        struct puffs_getreq *pgr = NULL;
                    444:        struct puffs_putreq *ppr = NULL;
                    445:        struct puffs_framectrl *pfctrl = &pu->pu_framectrl;
                    446:        struct puffs_fctrl_io *fio;
                    447:        struct kevent *curev, *newevs;
                    448:        size_t nchanges;
                    449:        int puffsfd, sverrno;
                    450:        int ndone;
                    451:
                    452:        assert(puffs_getstate(pu) >= PUFFS_STATE_RUNNING);
1.1       pooka     453:
1.36      pooka     454:        pgr = puffs_req_makeget(pu, puffs_getmaxreqlen(pu), 0);
1.19      pooka     455:        if (pgr == NULL)
1.44      pooka     456:                goto out;
1.18      alc       457:
1.26      pooka     458:        ppr = puffs_req_makeput(pu);
1.44      pooka     459:        if (ppr == NULL)
                    460:                goto out;
                    461:
                    462:        newevs = realloc(pfctrl->evs, (2*pfctrl->nfds+1)*sizeof(struct kevent));
                    463:        if (newevs == NULL)
                    464:                goto out;
                    465:        pfctrl->evs = newevs;
1.19      pooka     466:
                    467:        if ((flags & PUFFSLOOP_NODAEMON) == 0)
1.22      pooka     468:                if (daemon(1, 0) == -1)
1.19      pooka     469:                        goto out;
1.44      pooka     470:        pu->pu_state |= PU_INLOOP;
                    471:
                    472:        pu->pu_kq = kqueue();
                    473:        if (pu->pu_kq == -1)
                    474:                goto out;
                    475:        pu->pu_haskq = 1;
                    476:
                    477:        curev = pfctrl->evs;
                    478:        LIST_FOREACH(fio, &pfctrl->fb_ios, fio_entries) {
                    479:                EV_SET(curev, fio->io_fd, EVFILT_READ, EV_ADD,
                    480:                    0, 0, (uintptr_t)fio);
                    481:                curev++;
                    482:                EV_SET(curev, fio->io_fd, EVFILT_WRITE, EV_ADD | EV_DISABLE,
                    483:                    0, 0, (uintptr_t)fio);
                    484:                curev++;
                    485:        }
                    486:        puffsfd = puffs_getselectable(pu);
                    487:        EV_SET(curev, puffsfd, EVFILT_READ, EV_ADD, 0, 0, 0);
                    488:        if (kevent(pu->pu_kq, pfctrl->evs, 2*pfctrl->nfds+1,
                    489:            NULL, 0, NULL) == -1)
                    490:                goto out;
                    491:
                    492:        while (puffs_getstate(pu) != PUFFS_STATE_UNMOUNTED) {
1.46      pooka     493:                if (pu->pu_ml_lfn)
                    494:                        pu->pu_ml_lfn(pu);
                    495:
                    496:                /* micro optimization: skip kevent syscall if possible */
                    497:                if (pfctrl->nfds == 0 && pu->pu_ml_timep == NULL
                    498:                    && (pu->pu_state & PU_ASYNCFD) == 0) {
                    499:                        if (puffs_req_handle(pgr, ppr, 0) == -1)
                    500:                                goto out;
                    501:                        if (puffs_req_putput(ppr) == -1)
                    502:                                goto out;
                    503:                        puffs_req_resetput(ppr);
                    504:                        continue;
                    505:                }
                    506:                /* else: do full processing */
1.1       pooka     507:
1.44      pooka     508:                /*
                    509:                 * Build list of which to enable/disable in writecheck.
                    510:                 * Don't bother worrying about O(n) for now.
                    511:                 */
                    512:                nchanges = 0;
                    513:                LIST_FOREACH(fio, &pfctrl->fb_ios, fio_entries) {
1.46      pooka     514:                        if (fio->stat & FIO_WRGONE)
                    515:                                continue;
                    516:
1.44      pooka     517:                        /*
                    518:                         * Try to write out everything to avoid the
                    519:                         * need for enabling EVFILT_WRITE.  The likely
                    520:                         * case is that we can fit everything into the
                    521:                         * socket buffer.
                    522:                         */
1.46      pooka     523:                        if (puffs_framev_output(pu, pfctrl, fio)) {
                    524:                                /* need kernel notify? (error condition) */
                    525:                                if (puffs_req_putput(ppr) == -1)
                    526:                                        goto out;
                    527:                                puffs_req_resetput(ppr);
                    528:                        }
1.19      pooka     529:
1.46      pooka     530:                        /* en/disable write checks for kqueue as needed */
1.44      pooka     531:                        assert((FIO_EN_WRITE(fio) && FIO_RM_WRITE(fio)) == 0);
                    532:                        if (FIO_EN_WRITE(fio)) {
1.46      pooka     533:                                EV_SET(&pfctrl->evs[nchanges], fio->io_fd,
1.44      pooka     534:                                    EVFILT_WRITE, EV_ENABLE, 0, 0,
                    535:                                    (uintptr_t)fio);
1.46      pooka     536:                                fio->stat |= FIO_WR;
1.44      pooka     537:                                nchanges++;
                    538:                        }
                    539:                        if (FIO_RM_WRITE(fio)) {
1.46      pooka     540:                                EV_SET(&pfctrl->evs[nchanges], fio->io_fd,
1.44      pooka     541:                                    EVFILT_WRITE, EV_DISABLE, 0, 0,
                    542:                                    (uintptr_t)fio);
1.46      pooka     543:                                fio->stat &= ~FIO_WR;
1.44      pooka     544:                                nchanges++;
                    545:                        }
1.46      pooka     546:                        assert(nchanges <= pfctrl->nfds);
1.19      pooka     547:                }
1.44      pooka     548:
1.46      pooka     549:                ndone = kevent(pu->pu_kq, pfctrl->evs, nchanges,
                    550:                    pfctrl->evs, pfctrl->nfds+1, pu->pu_ml_timep);
1.44      pooka     551:                if (ndone == -1)
                    552:                        goto out;
1.46      pooka     553:                /* micro optimize */
                    554:                if (ndone == 0)
                    555:                        continue;
1.44      pooka     556:
                    557:                /* iterate over the results */
                    558:                for (curev = pfctrl->evs; ndone--; curev++) {
                    559:                        /* get & possibly dispatch events from kernel */
                    560:                        if (curev->ident == puffsfd) {
                    561:                                if (puffs_req_handle(pgr, ppr, 0) == -1)
                    562:                                        goto out;
                    563:                                continue;
                    564:                        }
                    565:
1.46      pooka     566:                        fio = (void *)curev->udata;
                    567:                        if (curev->flags & EV_ERROR) {
                    568:                                assert(curev->filter == EVFILT_WRITE);
                    569:                                fio->stat &= ~FIO_WR;
                    570:
                    571:                                /* XXX: how to know if it's a transient error */
                    572:                                puffs_framev_writeclose(pu, fio,
                    573:                                    (int)curev->data);
                    574:                                continue;
1.44      pooka     575:                        }
                    576:
1.46      pooka     577:                        if (curev->filter == EVFILT_READ) {
                    578:                                if (curev->flags & EV_EOF)
                    579:                                        puffs_framev_readclose(pu, fio,
1.48    ! pooka     580:                                            ECONNRESET);
1.46      pooka     581:                                else
                    582:                                        puffs_framev_input(pu, pfctrl,
                    583:                                            fio, ppr);
                    584:
                    585:                        } else if (curev->filter == EVFILT_WRITE) {
                    586:                                if (curev->flags & EV_EOF)
                    587:                                        puffs_framev_writeclose(pu, fio,
1.48    ! pooka     588:                                            ECONNRESET);
1.46      pooka     589:                                else
                    590:                                        puffs_framev_output(pu, pfctrl, fio);
1.44      pooka     591:                        }
1.19      pooka     592:                }
1.44      pooka     593:
                    594:                /* stuff all replies from both of the above into kernel */
                    595:                if (puffs_req_putput(ppr) == -1)
                    596:                        goto out;
                    597:                puffs_req_resetput(ppr);
1.46      pooka     598:
                    599:                /*
                    600:                 * Really free fd's now that we don't have references
                    601:                 * to them.
                    602:                 */
                    603:                while ((fio = LIST_FIRST(&pfctrl->fb_ios_rmlist)) != NULL) {
                    604:                        LIST_REMOVE(fio, fio_entries);
                    605:                        free(fio);
                    606:                }
1.18      alc       607:        }
1.44      pooka     608:        errno = 0;
1.18      alc       609:
1.19      pooka     610:  out:
1.44      pooka     611:        /* store the real error for a while */
                    612:        sverrno = errno;
                    613:
                    614:        if (ppr)
                    615:                puffs_req_destroyput(ppr);
                    616:        if (pgr)
                    617:                puffs_req_destroyget(pgr);
                    618:
                    619:        errno = sverrno;
                    620:        if (errno)
                    621:                return -1;
                    622:        else
                    623:                return 0;
1.1       pooka     624: }

CVSweb <webmaster@jp.NetBSD.org>