[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.92.4.3

1.92.4.3! sborrill    1: /*     $NetBSD: puffs.c,v 1.92.4.2 2009/10/16 12:10:54 sborrill 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:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     20:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     21:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     22:  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     25:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  */
                     31:
                     32: #include <sys/cdefs.h>
                     33: #if !defined(lint)
1.92.4.3! sborrill   34: __RCSID("$NetBSD: puffs.c,v 1.92.4.2 2009/10/16 12:10:54 sborrill Exp $");
1.1       pooka      35: #endif /* !lint */
                     36:
                     37: #include <sys/param.h>
                     38: #include <sys/mount.h>
                     39:
1.9       pooka      40: #include <assert.h>
1.12      pooka      41: #include <err.h>
1.1       pooka      42: #include <errno.h>
                     43: #include <fcntl.h>
1.21      pooka      44: #include <mntopts.h>
1.58      pooka      45: #include <paths.h>
1.1       pooka      46: #include <puffs.h>
                     47: #include <stdio.h>
                     48: #include <stdlib.h>
                     49: #include <string.h>
                     50: #include <syslog.h>
                     51: #include <unistd.h>
                     52:
1.19      pooka      53: #include "puffs_priv.h"
                     54:
1.21      pooka      55: /* Most file systems want this for opts, so just give it to them */
                     56: const struct mntopt puffsmopts[] = {
                     57:        MOPT_STDOPTS,
                     58:        PUFFSMOPT_STD,
                     59:        MOPT_NULL,
                     60: };
                     61:
1.72      pooka      62: #ifdef PUFFS_WITH_THREADS
                     63: #include <pthread.h>
                     64: pthread_mutex_t pu_lock = PTHREAD_MUTEX_INITIALIZER;
                     65: #endif
                     66:
1.10      pooka      67: #define FILLOP(lower, upper)                                           \
                     68: do {                                                                   \
1.13      pooka      69:        if (pops->puffs_node_##lower)                                   \
1.10      pooka      70:                opmask[PUFFS_VN_##upper] = 1;                           \
                     71: } while (/*CONSTCOND*/0)
                     72: static void
1.13      pooka      73: fillvnopmask(struct puffs_ops *pops, uint8_t *opmask)
1.10      pooka      74: {
                     75:
                     76:        memset(opmask, 0, PUFFS_VN_MAX);
                     77:
                     78:        FILLOP(create,   CREATE);
                     79:        FILLOP(mknod,    MKNOD);
                     80:        FILLOP(open,     OPEN);
                     81:        FILLOP(close,    CLOSE);
                     82:        FILLOP(access,   ACCESS);
                     83:        FILLOP(getattr,  GETATTR);
                     84:        FILLOP(setattr,  SETATTR);
                     85:        FILLOP(poll,     POLL); /* XXX: not ready in kernel */
1.16      pooka      86:        FILLOP(mmap,     MMAP);
1.10      pooka      87:        FILLOP(fsync,    FSYNC);
                     88:        FILLOP(seek,     SEEK);
                     89:        FILLOP(remove,   REMOVE);
                     90:        FILLOP(link,     LINK);
                     91:        FILLOP(rename,   RENAME);
                     92:        FILLOP(mkdir,    MKDIR);
                     93:        FILLOP(rmdir,    RMDIR);
                     94:        FILLOP(symlink,  SYMLINK);
                     95:        FILLOP(readdir,  READDIR);
                     96:        FILLOP(readlink, READLINK);
                     97:        FILLOP(reclaim,  RECLAIM);
                     98:        FILLOP(inactive, INACTIVE);
                     99:        FILLOP(print,    PRINT);
                    100:        FILLOP(read,     READ);
                    101:        FILLOP(write,    WRITE);
1.92.4.3! sborrill  102:        FILLOP(abortop,  ABORTOP);
1.19      pooka     103: }
                    104: #undef FILLOP
                    105:
1.79      pooka     106: /*
                    107:  * Go over all framev entries and write everything we can.  This is
                    108:  * mostly for the benefit of delivering "unmount" to the kernel.
                    109:  */
                    110: static void
                    111: finalpush(struct puffs_usermount *pu)
                    112: {
                    113:        struct puffs_fctrl_io *fio;
                    114:
                    115:        LIST_FOREACH(fio, &pu->pu_ios, fio_entries) {
                    116:                if (fio->stat & FIO_WRGONE)
                    117:                        continue;
                    118:
1.89      pooka     119:                puffs__framev_output(pu, fio->fctrl, fio);
1.79      pooka     120:        }
                    121: }
                    122:
1.64      pooka     123: /*ARGSUSED*/
1.63      pooka     124: static void
                    125: puffs_defaulterror(struct puffs_usermount *pu, uint8_t type,
1.92      pooka     126:        int error, const char *str, puffs_cookie_t cookie)
1.63      pooka     127: {
                    128:
1.77      pooka     129:        fprintf(stderr, "abort: type %d, error %d, cookie %p (%s)\n",
                    130:            type, error, cookie, str);
1.63      pooka     131:        abort();
                    132: }
                    133:
1.19      pooka     134: int
                    135: puffs_getselectable(struct puffs_usermount *pu)
                    136: {
1.10      pooka     137:
1.60      pooka     138:        return pu->pu_fd;
1.10      pooka     139: }
1.19      pooka     140:
1.80      pooka     141: uint64_t
                    142: puffs__nextreq(struct puffs_usermount *pu)
                    143: {
                    144:        uint64_t rv;
                    145:
                    146:        PU_LOCK();
                    147:        rv = pu->pu_nextreq++;
                    148:        PU_UNLOCK();
                    149:
                    150:        return rv;
                    151: }
                    152:
1.19      pooka     153: int
                    154: puffs_setblockingmode(struct puffs_usermount *pu, int mode)
                    155: {
1.46      pooka     156:        int rv, x;
                    157:
1.74      pooka     158:        assert(puffs_getstate(pu) == PUFFS_STATE_RUNNING);
                    159:
1.46      pooka     160:        if (mode != PUFFSDEV_BLOCK && mode != PUFFSDEV_NONBLOCK) {
                    161:                errno = EINVAL;
                    162:                return -1;
                    163:        }
1.19      pooka     164:
                    165:        x = mode;
1.60      pooka     166:        rv = ioctl(pu->pu_fd, FIONBIO, &x);
1.46      pooka     167:
                    168:        if (rv == 0) {
                    169:                if (mode == PUFFSDEV_BLOCK)
                    170:                        pu->pu_state &= ~PU_ASYNCFD;
                    171:                else
                    172:                        pu->pu_state |= PU_ASYNCFD;
                    173:        }
                    174:
                    175:        return rv;
1.19      pooka     176: }
                    177:
                    178: int
                    179: puffs_getstate(struct puffs_usermount *pu)
                    180: {
                    181:
1.44      pooka     182:        return pu->pu_state & PU_STATEMASK;
1.19      pooka     183: }
                    184:
                    185: void
                    186: puffs_setstacksize(struct puffs_usermount *pu, size_t ss)
                    187: {
1.86      pooka     188:        long psize, minsize;
1.69      pooka     189:        int stackshift;
1.87      pooka     190:        int bonus;
1.78      pooka     191:
1.86      pooka     192:        assert(puffs_getstate(pu) == PUFFS_STATE_BEFOREMOUNT);
                    193:
1.78      pooka     194:        psize = sysconf(_SC_PAGESIZE);
1.87      pooka     195:        minsize = 4*psize;
1.86      pooka     196:        if (ss < minsize || ss == PUFFS_STACKSIZE_MIN) {
                    197:                if (ss != PUFFS_STACKSIZE_MIN)
                    198:                        fprintf(stderr, "puffs_setstacksize: adjusting "
                    199:                            "stacksize to minimum %ld\n", minsize);
1.87      pooka     200:                ss = 4*psize;
1.78      pooka     201:        }
1.69      pooka     202:
                    203:        stackshift = -1;
1.87      pooka     204:        bonus = 0;
1.69      pooka     205:        while (ss) {
1.87      pooka     206:                if (ss & 0x1)
                    207:                        bonus++;
1.69      pooka     208:                ss >>= 1;
                    209:                stackshift++;
                    210:        }
1.87      pooka     211:        if (bonus > 1) {
                    212:                stackshift++;
                    213:                fprintf(stderr, "puffs_setstacksize: using next power of two: "
1.88      pooka     214:                    "%d\n", 1<<stackshift);
1.87      pooka     215:        }
                    216:
1.69      pooka     217:        pu->pu_cc_stackshift = stackshift;
1.19      pooka     218: }
                    219:
1.24      pooka     220: struct puffs_pathobj *
                    221: puffs_getrootpathobj(struct puffs_usermount *pu)
1.19      pooka     222: {
                    223:        struct puffs_node *pnr;
                    224:
                    225:        pnr = pu->pu_pn_root;
                    226:        if (pnr == NULL) {
                    227:                errno = ENOENT;
1.24      pooka     228:                return NULL;
1.19      pooka     229:        }
                    230:
1.24      pooka     231:        return &pnr->pn_po;
                    232: }
                    233:
1.35      pooka     234: void
                    235: puffs_setroot(struct puffs_usermount *pu, struct puffs_node *pn)
                    236: {
                    237:
                    238:        pu->pu_pn_root = pn;
                    239: }
                    240:
                    241: struct puffs_node *
                    242: puffs_getroot(struct puffs_usermount *pu)
                    243: {
                    244:
                    245:        return pu->pu_pn_root;
                    246: }
                    247:
1.49      pooka     248: void
                    249: puffs_setrootinfo(struct puffs_usermount *pu, enum vtype vt,
                    250:        vsize_t vsize, dev_t rdev)
                    251: {
1.60      pooka     252:        struct puffs_kargs *pargs = pu->pu_kargp;
1.49      pooka     253:
1.60      pooka     254:        if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT) {
1.49      pooka     255:                warnx("puffs_setrootinfo: call has effect only "
                    256:                    "before mount\n");
1.60      pooka     257:                return;
                    258:        }
1.49      pooka     259:
                    260:        pargs->pa_root_vtype = vt;
                    261:        pargs->pa_root_vsize = vsize;
                    262:        pargs->pa_root_rdev = rdev;
                    263: }
                    264:
1.35      pooka     265: void *
                    266: puffs_getspecific(struct puffs_usermount *pu)
                    267: {
                    268:
                    269:        return pu->pu_privdata;
                    270: }
                    271:
1.92.4.1  sborrill  272: void
                    273: puffs_setspecific(struct puffs_usermount *pu, void *privdata)
                    274: {
                    275:
                    276:        pu->pu_privdata = privdata;
                    277: }
                    278:
1.35      pooka     279: size_t
                    280: puffs_getmaxreqlen(struct puffs_usermount *pu)
                    281: {
                    282:
1.60      pooka     283:        return pu->pu_maxreqlen;
1.35      pooka     284: }
1.24      pooka     285:
                    286: void
1.37      pooka     287: puffs_setmaxreqlen(struct puffs_usermount *pu, size_t reqlen)
                    288: {
                    289:
1.44      pooka     290:        if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT)
1.37      pooka     291:                warnx("puffs_setmaxreqlen: call has effect only "
                    292:                    "before mount\n");
                    293:
1.66      pooka     294:        pu->pu_kargp->pa_maxmsglen = reqlen;
1.37      pooka     295: }
                    296:
                    297: void
1.38      pooka     298: puffs_setfhsize(struct puffs_usermount *pu, size_t fhsize, int flags)
1.37      pooka     299: {
                    300:
1.44      pooka     301:        if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT)
1.37      pooka     302:                warnx("puffs_setfhsize: call has effect only before mount\n");
                    303:
1.60      pooka     304:        pu->pu_kargp->pa_fhsize = fhsize;
                    305:        pu->pu_kargp->pa_fhflags = flags;
1.37      pooka     306: }
                    307:
                    308: void
                    309: puffs_setncookiehash(struct puffs_usermount *pu, int nhash)
                    310: {
                    311:
1.44      pooka     312:        if (puffs_getstate(pu) != PUFFS_STATE_BEFOREMOUNT)
1.37      pooka     313:                warnx("puffs_setfhsize: call has effect only before mount\n");
                    314:
1.60      pooka     315:        pu->pu_kargp->pa_nhashbuckets = nhash;
1.37      pooka     316: }
                    317:
                    318: void
1.24      pooka     319: puffs_set_pathbuild(struct puffs_usermount *pu, pu_pathbuild_fn fn)
                    320: {
                    321:
                    322:        pu->pu_pathbuild = fn;
                    323: }
                    324:
                    325: void
                    326: puffs_set_pathtransform(struct puffs_usermount *pu, pu_pathtransform_fn fn)
                    327: {
                    328:
                    329:        pu->pu_pathtransform = fn;
                    330: }
                    331:
                    332: void
                    333: puffs_set_pathcmp(struct puffs_usermount *pu, pu_pathcmp_fn fn)
                    334: {
                    335:
                    336:        pu->pu_pathcmp = fn;
                    337: }
                    338:
                    339: void
                    340: puffs_set_pathfree(struct puffs_usermount *pu, pu_pathfree_fn fn)
                    341: {
1.19      pooka     342:
1.24      pooka     343:        pu->pu_pathfree = fn;
1.19      pooka     344: }
                    345:
1.24      pooka     346: void
                    347: puffs_set_namemod(struct puffs_usermount *pu, pu_namemod_fn fn)
                    348: {
                    349:
                    350:        pu->pu_namemod = fn;
                    351: }
1.19      pooka     352:
1.40      pooka     353: void
1.63      pooka     354: puffs_set_errnotify(struct puffs_usermount *pu, pu_errnotify_fn fn)
                    355: {
                    356:
                    357:        pu->pu_errnotify = fn;
                    358: }
                    359:
                    360: void
1.81      pooka     361: puffs_set_cmap(struct puffs_usermount *pu, pu_cmap_fn fn)
                    362: {
                    363:
                    364:        pu->pu_cmap = fn;
                    365: }
                    366:
                    367: void
1.46      pooka     368: puffs_ml_setloopfn(struct puffs_usermount *pu, puffs_ml_loop_fn lfn)
                    369: {
                    370:
                    371:        pu->pu_ml_lfn = lfn;
                    372: }
                    373:
                    374: void
                    375: puffs_ml_settimeout(struct puffs_usermount *pu, struct timespec *ts)
                    376: {
                    377:
                    378:        if (ts == NULL) {
                    379:                pu->pu_ml_timep = NULL;
                    380:        } else {
                    381:                pu->pu_ml_timeout = *ts;
                    382:                pu->pu_ml_timep = &pu->pu_ml_timeout;
                    383:        }
                    384: }
                    385:
                    386: void
1.71      pooka     387: puffs_set_prepost(struct puffs_usermount *pu,
                    388:        pu_prepost_fn pre, pu_prepost_fn pst)
                    389: {
                    390:
                    391:        pu->pu_oppre = pre;
                    392:        pu->pu_oppost = pst;
                    393: }
                    394:
                    395: void
1.40      pooka     396: puffs_setback(struct puffs_cc *pcc, int whatback)
                    397: {
1.79      pooka     398:        struct puffs_req *preq = puffs__framebuf_getdataptr(pcc->pcc_pb);
1.40      pooka     399:
                    400:        assert(PUFFSOP_OPCLASS(preq->preq_opclass) == PUFFSOP_VN && (
                    401:            preq->preq_optype == PUFFS_VN_OPEN ||
                    402:            preq->preq_optype == PUFFS_VN_MMAP ||
                    403:            preq->preq_optype == PUFFS_VN_REMOVE ||
1.54      pooka     404:            preq->preq_optype == PUFFS_VN_RMDIR ||
                    405:            preq->preq_optype == PUFFS_VN_INACTIVE));
1.40      pooka     406:
                    407:        preq->preq_setbacks |= whatback & PUFFS_SETBACK_MASK;
                    408: }
                    409:
1.36      pooka     410: int
1.75      pooka     411: puffs_daemon(struct puffs_usermount *pu, int nochdir, int noclose)
                    412: {
                    413:        ssize_t n;
                    414:        int parent, value, fd;
                    415:
                    416:        if (pipe(pu->pu_dpipe) == -1)
                    417:                return -1;
                    418:
                    419:        switch (fork()) {
                    420:        case -1:
                    421:                return -1;
                    422:        case 0:
                    423:                parent = 0;
                    424:                break;
                    425:        default:
                    426:                parent = 1;
                    427:                break;
                    428:        }
                    429:        pu->pu_state |= PU_PUFFSDAEMON;
                    430:
                    431:        if (parent) {
                    432:                n = read(pu->pu_dpipe[0], &value, sizeof(int));
                    433:                if (n == -1)
                    434:                        err(1, "puffs_daemon");
                    435:                assert(n == sizeof(value));
                    436:                if (value) {
                    437:                        errno = value;
                    438:                        err(1, "puffs_daemon");
                    439:                }
                    440:                exit(0);
                    441:        } else {
                    442:                if (setsid() == -1)
                    443:                        goto fail;
                    444:
                    445:                if (!nochdir)
                    446:                        chdir("/");
                    447:
                    448:                if (!noclose) {
                    449:                        fd = open(_PATH_DEVNULL, O_RDWR, 0);
                    450:                        if (fd == -1)
                    451:                                goto fail;
                    452:                        dup2(fd, STDIN_FILENO);
                    453:                        dup2(fd, STDOUT_FILENO);
                    454:                        dup2(fd, STDERR_FILENO);
                    455:                        if (fd > STDERR_FILENO)
                    456:                                close(fd);
                    457:                }
                    458:                return 0;
                    459:        }
                    460:
                    461:  fail:
                    462:        n = write(pu->pu_dpipe[1], &errno, sizeof(int));
                    463:        assert(n == 4);
                    464:        return -1;
                    465: }
                    466:
1.92.4.2  sborrill  467: static void
                    468: shutdaemon(struct puffs_usermount *pu, int error)
                    469: {
                    470:        ssize_t n;
                    471:
                    472:        n = write(pu->pu_dpipe[1], &error, sizeof(int));
                    473:        assert(n == 4);
                    474:        close(pu->pu_dpipe[0]);
                    475:        close(pu->pu_dpipe[1]);
                    476:        pu->pu_state &= ~PU_PUFFSDAEMON;
                    477: }
                    478:
1.75      pooka     479: int
1.49      pooka     480: puffs_mount(struct puffs_usermount *pu, const char *dir, int mntflags,
1.92      pooka     481:        puffs_cookie_t cookie)
1.36      pooka     482: {
1.62      pooka     483:        char rp[MAXPATHLEN];
1.75      pooka     484:        int rv, fd, sverrno;
1.82      pooka     485:        char *comfd;
                    486:
                    487:        pu->pu_kargp->pa_root_cookie = cookie;
1.36      pooka     488:
                    489:        /* XXXkludgehere */
                    490:        /* kauth doesn't provide this service any longer */
                    491:        if (geteuid() != 0)
                    492:                mntflags |= MNT_NOSUID | MNT_NODEV;
                    493:
1.76      pooka     494:        if (realpath(dir, rp) == NULL) {
                    495:                rv = -1;
                    496:                goto out;
                    497:        }
1.62      pooka     498:
                    499:        if (strcmp(dir, rp) != 0) {
                    500:                warnx("puffs_mount: \"%s\" is a relative path.", dir);
                    501:                warnx("puffs_mount: using \"%s\" instead.", rp);
                    502:        }
                    503:
1.82      pooka     504:        /*
                    505:         * Undocumented...  Well, documented only here.
                    506:         *
                    507:         * This is used for imaginative purposes.  If the env variable is
                    508:         * set, puffs_mount() doesn't do the regular mount procedure.
                    509:         * Rather, it crams the mount data down the comfd and sets comfd as
                    510:         * the puffs descriptor.
                    511:         *
                    512:         * This shouldn't be used unless you can read my mind ( ... or write
                    513:         * it, not to mention execute it, but that's starting to get silly).
                    514:         */
                    515:        if ((comfd = getenv("PUFFS_COMFD")) != NULL) {
                    516:                size_t len;
                    517:
                    518:                if (sscanf(comfd, "%d", &pu->pu_fd) != 1) {
                    519:                        errno = EINVAL;
                    520:                        rv = -1;
                    521:                        goto out;
                    522:                }
                    523:                /* check that what we got at least resembles an fd */
                    524:                if (fcntl(pu->pu_fd, F_GETFL) == -1) {
                    525:                        rv = -1;
                    526:                        goto out;
                    527:                }
                    528:
                    529:                len = strlen(dir)+1;
                    530:
                    531: #define allwrite(buf, len)                                             \
                    532: do {                                                                   \
                    533:        ssize_t al_rv;                                                  \
                    534:        al_rv = write(pu->pu_fd, buf, len);                             \
                    535:        if (al_rv != len) {                                             \
                    536:                if (al_rv != -1)                                        \
                    537:                        errno = EIO;                                    \
                    538:                rv = -1;                                                \
                    539:                abort();\
                    540:                goto out;                                               \
                    541:        }                                                               \
                    542: } while (/*CONSTCOND*/0)
                    543:                allwrite(&len, sizeof(len));
                    544:                allwrite(dir, len);
1.84      pooka     545:                len = strlen(pu->pu_kargp->pa_mntfromname)+1;
1.83      pooka     546:                allwrite(&len, sizeof(len));
                    547:                allwrite(pu->pu_kargp->pa_mntfromname, len);
1.82      pooka     548:                allwrite(&mntflags, sizeof(mntflags));
                    549:                allwrite(pu->pu_kargp, sizeof(*pu->pu_kargp));
                    550:                allwrite(&pu->pu_flags, sizeof(pu->pu_flags));
                    551: #undef allwrite
                    552:
                    553:                rv = 0;
                    554:        } else {
                    555:                fd = open(_PATH_PUFFS, O_RDWR);
                    556:                if (fd == -1) {
                    557:                        warnx("puffs_mount: cannot open %s", _PATH_PUFFS);
                    558:                        rv = -1;
                    559:                        goto out;
                    560:                }
                    561:                if (fd <= 2)
                    562:                        warnx("puffs_mount: device fd %d (<= 2), sure this is "
                    563:                            "what you want?", fd);
                    564:
                    565:                pu->pu_kargp->pa_fd = pu->pu_fd = fd;
                    566:                if ((rv = mount(MOUNT_PUFFS, rp, mntflags,
                    567:                    pu->pu_kargp, sizeof(struct puffs_kargs))) == -1)
                    568:                        goto out;
1.74      pooka     569:        }
                    570:
1.49      pooka     571:        PU_SETSTATE(pu, PUFFS_STATE_RUNNING);
1.36      pooka     572:
1.60      pooka     573:  out:
1.76      pooka     574:        if (rv != 0)
                    575:                sverrno = errno;
                    576:        else
                    577:                sverrno = 0;
1.60      pooka     578:        free(pu->pu_kargp);
                    579:        pu->pu_kargp = NULL;
                    580:
1.92.4.2  sborrill  581:        if (pu->pu_state & PU_PUFFSDAEMON)
                    582:                shutdaemon(pu, sverrno);
1.75      pooka     583:
                    584:        errno = sverrno;
1.60      pooka     585:        return rv;
1.36      pooka     586: }
1.10      pooka     587:
1.92.4.3! sborrill  588: /*ARGSUSED*/
1.1       pooka     589: struct puffs_usermount *
1.92.4.3! sborrill  590: _puffs_init(int dummy, struct puffs_ops *pops, const char *mntfromname,
1.58      pooka     591:        const char *puffsname, void *priv, uint32_t pflags)
1.1       pooka     592: {
                    593:        struct puffs_usermount *pu;
1.36      pooka     594:        struct puffs_kargs *pargs;
1.74      pooka     595:        int sverrno;
1.1       pooka     596:
1.36      pooka     597:        pu = malloc(sizeof(struct puffs_usermount));
                    598:        if (pu == NULL)
                    599:                goto failfree;
1.47      pooka     600:        memset(pu, 0, sizeof(struct puffs_usermount));
1.1       pooka     601:
1.60      pooka     602:        pargs = pu->pu_kargp = malloc(sizeof(struct puffs_kargs));
                    603:        if (pargs == NULL)
                    604:                goto failfree;
                    605:        memset(pargs, 0, sizeof(struct puffs_kargs));
                    606:
1.36      pooka     607:        pargs->pa_vers = PUFFSDEVELVERS | PUFFSVERSION;
                    608:        pargs->pa_flags = PUFFS_FLAG_KERN(pflags);
                    609:        fillvnopmask(pops, pargs->pa_vnopmask);
1.58      pooka     610:        (void)strlcpy(pargs->pa_typename, puffsname,
                    611:            sizeof(pargs->pa_typename));
                    612:        (void)strlcpy(pargs->pa_mntfromname, mntfromname,
                    613:            sizeof(pargs->pa_mntfromname));
1.1       pooka     614:
1.49      pooka     615:        puffs_zerostatvfs(&pargs->pa_svfsb);
                    616:        pargs->pa_root_cookie = NULL;
                    617:        pargs->pa_root_vtype = VDIR;
                    618:        pargs->pa_root_vsize = 0;
                    619:        pargs->pa_root_rdev = 0;
1.66      pooka     620:        pargs->pa_maxmsglen = 0;
1.49      pooka     621:
1.1       pooka     622:        pu->pu_flags = pflags;
1.13      pooka     623:        pu->pu_ops = *pops;
1.21      pooka     624:        free(pops); /* XXX */
1.36      pooka     625:
1.19      pooka     626:        pu->pu_privdata = priv;
1.69      pooka     627:        pu->pu_cc_stackshift = PUFFS_CC_STACKSHIFT_DEFAULT;
1.1       pooka     628:        LIST_INIT(&pu->pu_pnodelst);
1.79      pooka     629:        LIST_INIT(&pu->pu_ios);
                    630:        LIST_INIT(&pu->pu_ios_rmlist);
1.88      pooka     631:        LIST_INIT(&pu->pu_ccmagazin);
1.67      pooka     632:        TAILQ_INIT(&pu->pu_sched);
1.1       pooka     633:
1.89      pooka     634:        pu->pu_framectrl[PU_FRAMECTRL_FS].rfb = puffs__fsframe_read;
                    635:        pu->pu_framectrl[PU_FRAMECTRL_FS].wfb = puffs__fsframe_write;
                    636:        pu->pu_framectrl[PU_FRAMECTRL_FS].cmpfb = puffs__fsframe_cmp;
                    637:        pu->pu_framectrl[PU_FRAMECTRL_FS].gotfb = puffs__fsframe_gotframe;
1.79      pooka     638:        pu->pu_framectrl[PU_FRAMECTRL_FS].fdnotfn = puffs_framev_unmountonclose;
                    639:
1.24      pooka     640:        /* defaults for some user-settable translation functions */
                    641:        pu->pu_cmap = NULL; /* identity translation */
                    642:
1.30      pooka     643:        pu->pu_pathbuild = puffs_stdpath_buildpath;
                    644:        pu->pu_pathfree = puffs_stdpath_freepath;
                    645:        pu->pu_pathcmp = puffs_stdpath_cmppath;
1.24      pooka     646:        pu->pu_pathtransform = NULL;
                    647:        pu->pu_namemod = NULL;
                    648:
1.63      pooka     649:        pu->pu_errnotify = puffs_defaulterror;
                    650:
1.44      pooka     651:        PU_SETSTATE(pu, PUFFS_STATE_BEFOREMOUNT);
1.1       pooka     652:
                    653:        return pu;
1.6       pooka     654:
1.1       pooka     655:  failfree:
1.6       pooka     656:        /* can't unmount() from here for obvious reasons */
1.60      pooka     657:        sverrno = errno;
1.1       pooka     658:        free(pu);
1.60      pooka     659:        errno = sverrno;
1.1       pooka     660:        return NULL;
                    661: }
                    662:
1.92.4.2  sborrill  663: void
                    664: puffs_cancel(struct puffs_usermount *pu, int error)
                    665: {
                    666:
                    667:        assert(puffs_getstate(pu) < PUFFS_STATE_RUNNING);
                    668:        shutdaemon(pu, error);
                    669:        free(pu);
                    670: }
                    671:
1.21      pooka     672: /*
                    673:  * XXX: there's currently no clean way to request unmount from
                    674:  * within the user server, so be very brutal about it.
                    675:  */
1.36      pooka     676: /*ARGSUSED1*/
1.21      pooka     677: int
                    678: puffs_exit(struct puffs_usermount *pu, int force)
                    679: {
1.44      pooka     680:        struct puffs_node *pn;
1.21      pooka     681:
                    682:        force = 1; /* currently */
1.92.4.2  sborrill  683:        assert((pu->pu_state & PU_PUFFSDAEMON) == 0);
1.21      pooka     684:
1.60      pooka     685:        if (pu->pu_fd)
                    686:                close(pu->pu_fd);
1.21      pooka     687:
1.44      pooka     688:        while ((pn = LIST_FIRST(&pu->pu_pnodelst)) != NULL)
1.24      pooka     689:                puffs_pn_put(pn);
1.44      pooka     690:
1.79      pooka     691:        finalpush(pu);
1.89      pooka     692:        puffs__framev_exit(pu);
1.91      pooka     693:        puffs__cc_exit(pu);
1.68      pooka     694:        if (pu->pu_state & PU_HASKQ)
1.44      pooka     695:                close(pu->pu_kq);
1.21      pooka     696:        free(pu);
                    697:
                    698:        return 0; /* always succesful for now, WILL CHANGE */
                    699: }
                    700:
1.89      pooka     701: /*
                    702:  * Actual mainloop.  This is called from a context which can block.
                    703:  * It is called either from puffs_mainloop (indirectly, via
                    704:  * puffs_cc_continue() or from puffs_cc_yield()).
                    705:  */
                    706: void
                    707: puffs__theloop(struct puffs_cc *pcc)
1.1       pooka     708: {
1.89      pooka     709:        struct puffs_usermount *pu = pcc->pcc_pu;
1.79      pooka     710:        struct puffs_framectrl *pfctrl;
1.44      pooka     711:        struct puffs_fctrl_io *fio;
1.79      pooka     712:        struct kevent *curev;
1.44      pooka     713:        size_t nchanges;
1.89      pooka     714:        int ndone;
1.44      pooka     715:
1.89      pooka     716:        while (puffs_getstate(pu) != PUFFS_STATE_UNMOUNTED) {
                    717:                /*
                    718:                 * Schedule existing requests.
                    719:                 */
                    720:                while ((pcc = TAILQ_FIRST(&pu->pu_sched)) != NULL) {
                    721:                        TAILQ_REMOVE(&pu->pu_sched, pcc, pcc_schedent);
                    722:                        puffs__goto(pcc);
                    723:                }
1.19      pooka     724:
1.46      pooka     725:                if (pu->pu_ml_lfn)
                    726:                        pu->pu_ml_lfn(pu);
                    727:
1.79      pooka     728:                /* XXX: can we still do these optimizations? */
                    729: #if 0
1.55      pooka     730:                /*
                    731:                 * Do this here, because:
                    732:                 *  a) loopfunc might generate some results
                    733:                 *  b) it's still "after" event handling (except for round 1)
                    734:                 */
                    735:                if (puffs_req_putput(ppr) == -1)
                    736:                        goto out;
                    737:                puffs_req_resetput(ppr);
                    738:
1.46      pooka     739:                /* micro optimization: skip kevent syscall if possible */
1.79      pooka     740:                if (pu->pu_nfds == 1 && pu->pu_ml_timep == NULL
1.46      pooka     741:                    && (pu->pu_state & PU_ASYNCFD) == 0) {
1.79      pooka     742:                        pfctrl = XXX->fctrl;
                    743:                        puffs_framev_input(pu, pfctrl, XXX);
1.46      pooka     744:                        continue;
                    745:                }
1.79      pooka     746: #endif
1.55      pooka     747:
1.46      pooka     748:                /* else: do full processing */
1.79      pooka     749:                /* Don't bother worrying about O(n) for now */
                    750:                LIST_FOREACH(fio, &pu->pu_ios, fio_entries) {
1.46      pooka     751:                        if (fio->stat & FIO_WRGONE)
                    752:                                continue;
                    753:
1.79      pooka     754:                        pfctrl = fio->fctrl;
                    755:
1.44      pooka     756:                        /*
                    757:                         * Try to write out everything to avoid the
                    758:                         * need for enabling EVFILT_WRITE.  The likely
                    759:                         * case is that we can fit everything into the
                    760:                         * socket buffer.
                    761:                         */
1.89      pooka     762:                        puffs__framev_output(pu, pfctrl, fio);
1.79      pooka     763:                }
                    764:
                    765:                /*
                    766:                 * Build list of which to enable/disable in writecheck.
                    767:                 */
1.80      pooka     768:                nchanges = 0;
1.79      pooka     769:                LIST_FOREACH(fio, &pu->pu_ios, fio_entries) {
                    770:                        if (fio->stat & FIO_WRGONE)
                    771:                                continue;
1.19      pooka     772:
1.46      pooka     773:                        /* en/disable write checks for kqueue as needed */
1.44      pooka     774:                        assert((FIO_EN_WRITE(fio) && FIO_RM_WRITE(fio)) == 0);
                    775:                        if (FIO_EN_WRITE(fio)) {
1.79      pooka     776:                                EV_SET(&pu->pu_evs[nchanges], fio->io_fd,
1.44      pooka     777:                                    EVFILT_WRITE, EV_ENABLE, 0, 0,
                    778:                                    (uintptr_t)fio);
1.46      pooka     779:                                fio->stat |= FIO_WR;
1.44      pooka     780:                                nchanges++;
                    781:                        }
                    782:                        if (FIO_RM_WRITE(fio)) {
1.79      pooka     783:                                EV_SET(&pu->pu_evs[nchanges], fio->io_fd,
1.44      pooka     784:                                    EVFILT_WRITE, EV_DISABLE, 0, 0,
                    785:                                    (uintptr_t)fio);
1.46      pooka     786:                                fio->stat &= ~FIO_WR;
1.44      pooka     787:                                nchanges++;
                    788:                        }
1.79      pooka     789:                        assert(nchanges <= pu->pu_nfds);
1.19      pooka     790:                }
1.44      pooka     791:
1.79      pooka     792:                ndone = kevent(pu->pu_kq, pu->pu_evs, nchanges,
                    793:                    pu->pu_evs, 2*pu->pu_nfds, pu->pu_ml_timep);
1.50      pooka     794:
                    795:                if (ndone == -1) {
                    796:                        if (errno != EINTR)
1.89      pooka     797:                                break;
1.50      pooka     798:                        else
                    799:                                continue;
                    800:                }
                    801:
                    802:                /* uoptimize */
1.46      pooka     803:                if (ndone == 0)
                    804:                        continue;
1.44      pooka     805:
                    806:                /* iterate over the results */
1.79      pooka     807:                for (curev = pu->pu_evs; ndone--; curev++) {
1.61      pooka     808:                        int what;
                    809:
1.79      pooka     810: #if 0
1.44      pooka     811:                        /* get & possibly dispatch events from kernel */
                    812:                        if (curev->ident == puffsfd) {
                    813:                                if (puffs_req_handle(pgr, ppr, 0) == -1)
                    814:                                        goto out;
                    815:                                continue;
                    816:                        }
1.79      pooka     817: #endif
1.44      pooka     818:
1.46      pooka     819:                        fio = (void *)curev->udata;
1.79      pooka     820:                        pfctrl = fio->fctrl;
1.46      pooka     821:                        if (curev->flags & EV_ERROR) {
                    822:                                assert(curev->filter == EVFILT_WRITE);
                    823:                                fio->stat &= ~FIO_WR;
                    824:
                    825:                                /* XXX: how to know if it's a transient error */
1.89      pooka     826:                                puffs__framev_writeclose(pu, fio,
1.46      pooka     827:                                    (int)curev->data);
1.89      pooka     828:                                puffs__framev_notify(fio, PUFFS_FBIO_ERROR);
1.46      pooka     829:                                continue;
1.44      pooka     830:                        }
                    831:
1.61      pooka     832:                        what = 0;
                    833:                        if (curev->filter == EVFILT_READ) {
1.89      pooka     834:                                puffs__framev_input(pu, pfctrl, fio);
1.61      pooka     835:                                what |= PUFFS_FBIO_READ;
                    836:                        }
1.56      pooka     837:
1.61      pooka     838:                        else if (curev->filter == EVFILT_WRITE) {
1.89      pooka     839:                                puffs__framev_output(pu, pfctrl, fio);
1.61      pooka     840:                                what |= PUFFS_FBIO_WRITE;
                    841:                        }
                    842:                        if (what)
1.89      pooka     843:                                puffs__framev_notify(fio, what);
1.67      pooka     844:                }
                    845:
                    846:                /*
1.46      pooka     847:                 * Really free fd's now that we don't have references
                    848:                 * to them.
                    849:                 */
1.79      pooka     850:                while ((fio = LIST_FIRST(&pu->pu_ios_rmlist)) != NULL) {
1.46      pooka     851:                        LIST_REMOVE(fio, fio_entries);
                    852:                        free(fio);
                    853:                }
1.18      alc       854:        }
1.90      pooka     855:
                    856:        if (puffs__cc_restoremain(pu) == -1)
                    857:                warn("cannot restore main context.  impending doom");
1.89      pooka     858: }
                    859:
                    860: int
                    861: puffs_mainloop(struct puffs_usermount *pu)
                    862: {
                    863:        struct puffs_fctrl_io *fio;
                    864:        struct puffs_cc *pcc;
                    865:        struct kevent *curev;
1.90      pooka     866:        int sverrno;
1.89      pooka     867:
                    868:        assert(puffs_getstate(pu) >= PUFFS_STATE_RUNNING);
                    869:
                    870:        pu->pu_kq = kqueue();
                    871:        if (pu->pu_kq == -1)
                    872:                goto out;
                    873:        pu->pu_state |= PU_HASKQ;
                    874:
                    875:        puffs_setblockingmode(pu, PUFFSDEV_NONBLOCK);
                    876:        if (puffs__framev_addfd_ctrl(pu, puffs_getselectable(pu),
                    877:            PUFFS_FBIO_READ | PUFFS_FBIO_WRITE,
                    878:            &pu->pu_framectrl[PU_FRAMECTRL_FS]) == -1)
                    879:                goto out;
                    880:
                    881:        curev = realloc(pu->pu_evs, (2*pu->pu_nfds)*sizeof(struct kevent));
                    882:        if (curev == NULL)
                    883:                goto out;
                    884:        pu->pu_evs = curev;
                    885:
                    886:        LIST_FOREACH(fio, &pu->pu_ios, fio_entries) {
                    887:                EV_SET(curev, fio->io_fd, EVFILT_READ, EV_ADD,
                    888:                    0, 0, (uintptr_t)fio);
                    889:                curev++;
                    890:                EV_SET(curev, fio->io_fd, EVFILT_WRITE, EV_ADD | EV_DISABLE,
                    891:                    0, 0, (uintptr_t)fio);
                    892:                curev++;
                    893:        }
                    894:        if (kevent(pu->pu_kq, pu->pu_evs, 2*pu->pu_nfds, NULL, 0, NULL) == -1)
                    895:                goto out;
                    896:
                    897:        pu->pu_state |= PU_INLOOP;
                    898:
1.90      pooka     899:        /*
                    900:         * Create alternate execution context and jump to it.  Note
                    901:         * that we come "out" of savemain twice.  Where we come out
                    902:         * of it depends on the architecture.  If the return address is
                    903:         * stored on the stack, we jump out from puffs_cc_continue(),
                    904:         * for a register return address from puffs__cc_savemain().
                    905:         * PU_MAINRESTORE makes sure we DTRT in both cases.
                    906:         */
                    907:        if (puffs__cc_create(pu, puffs__theloop, &pcc) == -1) {
1.89      pooka     908:                goto out;
1.90      pooka     909:        }
                    910:        if (puffs__cc_savemain(pu) == -1) {
                    911:                goto out;
                    912:        }
                    913:        if ((pu->pu_state & PU_MAINRESTORE) == 0)
                    914:                puffs_cc_continue(pcc);
1.89      pooka     915:
1.79      pooka     916:        finalpush(pu);
1.44      pooka     917:        errno = 0;
1.18      alc       918:
1.19      pooka     919:  out:
1.44      pooka     920:        /* store the real error for a while */
                    921:        sverrno = errno;
                    922:
                    923:        errno = sverrno;
                    924:        if (errno)
                    925:                return -1;
                    926:        else
                    927:                return 0;
1.1       pooka     928: }

CVSweb <webmaster@jp.NetBSD.org>