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

Annotation of src/lib/libperfuse/perfuse.c, Revision 1.37.2.1

1.37.2.1! pgoyette    1: /*  $NetBSD: perfuse.c,v 1.40 2016/10/19 01:30:35 christos Exp $ */
1.1       manu        2:
                      3: /*-
1.12      manu        4:  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
1.1       manu        5:  *
                      6:  *  Redistribution and use in source and binary forms, with or without
                      7:  *  modification, are permitted provided that the following conditions
                      8:  *  are met:
                      9:  *  1. Redistributions of source code must retain the above copyright
                     10:  *     notice, this list of conditions and the following disclaimer.
                     11:  *  2. Redistributions in binary form must reproduce the above copyright
                     12:  *     notice, this list of conditions and the following disclaimer in the
                     13:  *     documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  *  THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     16:  *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     17:  *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     18:  *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     19:  *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     20:  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     21:  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     22:  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     23:  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     24:  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     25:  *  POSSIBILITY OF SUCH DAMAGE.
                     26:  */
                     27:
                     28: #include <stdio.h>
                     29: #include <unistd.h>
                     30: #include <stdlib.h>
                     31: #include <fcntl.h>
                     32: #include <string.h>
                     33: #include <errno.h>
                     34: #include <puffs.h>
1.37.2.1! pgoyette   35: #include <inttypes.h>
1.1       manu       36: #include <sys/types.h>
1.19      manu       37: #include <sys/mman.h>
1.22      manu       38: #include <sys/resource.h>
1.1       manu       39: #include <sys/socket.h>
1.16      manu       40: #include <sys/extattr.h>
1.29      manu       41: #include <sys/hash.h>
1.1       manu       42: #include <sys/un.h>
1.6       manu       43: #include <machine/vmparam.h>
1.1       manu       44:
                     45: #define LIBPERFUSE
                     46: #include "perfuse.h"
                     47: #include "perfuse_if.h"
                     48: #include "perfuse_priv.h"
                     49:
                     50: int perfuse_diagflags = 0; /* global used only in DPRINTF/DERR/DWARN */
1.12      manu       51: extern char **environ;
1.1       manu       52:
                     53: static struct perfuse_state *init_state(void);
                     54: static int get_fd(const char *);
                     55:
                     56: static struct perfuse_state *
                     57: init_state(void)
                     58: {
                     59:        struct perfuse_state *ps;
1.29      manu       60:        size_t len;
1.12      manu       61:        char opts[1024];
1.29      manu       62:        int i;
1.1       manu       63:
                     64:        if ((ps = malloc(sizeof(*ps))) == NULL)
1.29      manu       65:                DERR(EX_OSERR, "%s:%d malloc failed", __func__, __LINE__);
1.1       manu       66:
                     67:        (void)memset(ps, 0, sizeof(*ps));
                     68:        ps->ps_max_write = UINT_MAX;
                     69:        ps->ps_max_readahead = UINT_MAX;
1.24      manu       70:        TAILQ_INIT(&ps->ps_trace);
1.29      manu       71:
                     72:        ps->ps_nnidhash = PUFFS_PNODEBUCKETS;
                     73:        len = sizeof(*ps->ps_nidhash) * ps->ps_nnidhash;
                     74:        if ((ps->ps_nidhash = malloc(len)) == NULL)
                     75:                DERR(EX_OSERR, "%s:%d malloc failed", __func__, __LINE__);
                     76:        for (i = 0; i < ps->ps_nnidhash; i++)
                     77:                LIST_INIT(&ps->ps_nidhash[i]);
1.1       manu       78:
1.12      manu       79:        /*
                     80:         * Most of the time, access() is broken because the filesystem
                     81:         * performs the check with root privileges. glusterfs will do that
                     82:         * if the Linux-specific setfsuid() is missing, for instance.
                     83:         */
                     84:        ps->ps_flags |= PS_NO_ACCESS;
                     85:
                     86:        /*
                     87:         * This is a temporary way to toggle access and creat usage.
                     88:         * It would be nice if that could be provided as mount options,
                     89:         * but that will not be obvious to do.
                     90:         */
                     91:        if (getenv_r("PERFUSE_OPTIONS", opts, sizeof(opts)) != -1) {
                     92:                char *optname;
                     93:                char *last;
                     94:
                     95:                 for ((optname = strtok_r(opts, ",", &last));
                     96:                      optname != NULL;
                     97:                      (optname = strtok_r(NULL, ",", &last))) {
                     98:                        if (strcmp(optname, "enable_access") == 0)
                     99:                                ps->ps_flags &= ~PS_NO_ACCESS;
                    100:
                    101:                        if (strcmp(optname, "disable_access") == 0)
                    102:                                ps->ps_flags |= PS_NO_ACCESS;
                    103:
                    104:                        if (strcmp(optname, "enable_creat") == 0)
                    105:                                ps->ps_flags &= ~PS_NO_CREAT;
                    106:
                    107:                        if (strcmp(optname, "disable_creat") == 0)
                    108:                                ps->ps_flags |= PS_NO_CREAT;
                    109:                }
                    110:        }
                    111:
                    112:
1.1       manu      113:        return ps;
                    114: }
                    115:
                    116:
                    117: static int
1.26      matt      118: get_fd(const char *data)
1.1       manu      119: {
                    120:        char *string;
                    121:        const char fdopt[] = "fd=";
                    122:        char *lastp;
                    123:        char *opt;
                    124:        int fd = -1;
                    125:
                    126:        if ((string = strdup(data)) == NULL)
                    127:                return -1;
                    128:
                    129:        for (opt = strtok_r(string, ",", &lastp);
                    130:             opt != NULL;
                    131:             opt = strtok_r(NULL, ",", &lastp)) {
                    132:                if (strncmp(opt, fdopt, strlen(fdopt)) == 0) {
                    133:                        fd =  atoi(opt + strlen(fdopt));
                    134:                        break;
                    135:                }
                    136:        }
                    137:
                    138:        /*
                    139:         * No file descriptor found
                    140:         */
                    141:        if (fd == -1)
                    142:                errno = EINVAL;
                    143:
                    144:        free(string);
                    145:        return fd;
                    146:
                    147: }
                    148:
1.37.2.1! pgoyette  149: uint32_t
        !           150: perfuse_bufvar_from_env(const char *name, uint32_t defval)
        !           151: {
        !           152:        char valstr[1024];
        !           153:        int e;
        !           154:        uint32_t retval;
        !           155:
        !           156:        if (getenv_r(name, valstr, sizeof(valstr)) == -1)
        !           157:                return defval;
        !           158:
        !           159:        retval = (uint32_t)strtoi(valstr, NULL, 0, 0, UINT32_MAX, &e);
        !           160:        if (!e)
        !           161:                return retval;
        !           162:
        !           163:        DWARNC(e, "conversion from `%s' to uint32_t failed, using %u",
        !           164:            valstr, defval);
        !           165:        return defval;
        !           166: }
        !           167:
1.1       manu      168: int
1.26      matt      169: perfuse_open(const char *path, int flags, mode_t mode)
1.1       manu      170: {
1.2       manu      171:        int sv[2];
1.1       manu      172:        struct sockaddr_un sun;
                    173:        struct sockaddr *sa;
1.2       manu      174:        char progname[] = _PATH_PERFUSED;
                    175:        char minus_i[] = "-i";
                    176:        char fdstr[16];
                    177:        char *const argv[] = { progname, minus_i, fdstr, NULL};
1.6       manu      178:        uint32_t opt;
1.12      manu      179:        uint32_t optlen;
1.15      manu      180:        int sock_type = SOCK_SEQPACKET;
1.1       manu      181:
                    182:        if (strcmp(path, _PATH_FUSE) != 0)
                    183:                return open(path, flags, mode);
                    184:
1.15      manu      185:        /*
                    186:         * Try SOCK_SEQPACKET then SOCK_DGRAM if unavailable
                    187:         */
                    188:        if ((sv[0] = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) == -1) {
                    189:                sock_type = SOCK_DGRAM;
                    190:                 DWARNX("SEQPACKET local sockets unavailable, using less "
                    191:                       "reliable DGRAM sockets. Expect file operation hangs.");
                    192:
                    193:                if ((sv[0] = socket(PF_LOCAL, SOCK_DGRAM, 0)) == -1) {
1.1       manu      194: #ifdef PERFUSE_DEBUG
1.18      christos  195:                        DWARN("%s: %d socket failed", __func__, __LINE__);
1.1       manu      196: #endif
1.15      manu      197:                        return -1;
                    198:                }
1.1       manu      199:        }
                    200:
1.6       manu      201:        /*
1.37.2.1! pgoyette  202:         * Set a buffer lentgh large enough so that enough FUSE packets
1.6       manu      203:         * will fit.
                    204:         */
1.37.2.1! pgoyette  205:        opt = perfuse_bufvar_from_env("PERFUSE_BUFSIZE",
        !           206:            (uint32_t)(16 * FUSE_BUFSIZE));
1.12      manu      207:        optlen = sizeof(opt);
                    208:        if (setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &opt, optlen) != 0)
1.6       manu      209:                DWARN("%s: setsockopt SO_SNDBUF to %d failed", __func__, opt);
                    210:
1.12      manu      211:        if (setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &opt, optlen) != 0)
1.6       manu      212:                DWARN("%s: setsockopt SO_RCVBUF to %d failed", __func__, opt);
                    213:
1.1       manu      214:        sa = (struct sockaddr *)(void *)&sun;
                    215:        sun.sun_len = sizeof(sun);
                    216:        sun.sun_family = AF_LOCAL;
                    217:        (void)strcpy(sun.sun_path, path);
                    218:
1.15      manu      219:        if (connect(sv[0], sa, (socklen_t)sun.sun_len) == 0)
1.2       manu      220:                return sv[0];
                    221:
                    222:        /*
                    223:         * Attempt to run perfused on our own
                    224:         * if it does not run yet; In that case
                    225:         * we will talk using a socketpair
                    226:         * instead of /dev/fuse.
                    227:         */
1.15      manu      228:        if (socketpair(PF_LOCAL, sock_type, 0, sv) != 0) {
1.5       manu      229:                DWARN("%s:%d: socketpair failed", __func__, __LINE__);
1.1       manu      230:                return -1;
                    231:        }
                    232:
1.6       manu      233:        /*
1.37.2.1! pgoyette  234:         * Set a buffer lentgh large enough so that enough FUSE packets
1.6       manu      235:         * will fit.
                    236:         */
1.37.2.1! pgoyette  237:        opt = perfuse_bufvar_from_env("PERFUSE_BUFSIZE",
        !           238:            (uint32_t)(16 * FUSE_BUFSIZE));
1.12      manu      239:        optlen = sizeof(opt);
                    240:        if (setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &opt, optlen) != 0)
1.6       manu      241:                DWARN("%s: setsockopt SO_SNDBUF to %d failed", __func__, opt);
                    242:
1.12      manu      243:        if (setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &opt, optlen) != 0)
1.6       manu      244:                DWARN("%s: setsockopt SO_RCVBUF to %d failed", __func__, opt);
                    245:
1.12      manu      246:        if (setsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &opt, optlen) != 0)
1.6       manu      247:                DWARN("%s: setsockopt SO_SNDBUF to %d failed", __func__, opt);
                    248:
1.12      manu      249:        if (setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &opt, optlen) != 0)
1.6       manu      250:                DWARN("%s: setsockopt SO_RCVBUF to %d failed", __func__, opt);
                    251:
                    252:        /*
                    253:         * Request peer credentials. This musr be done before first
                    254:         * frame is sent.
                    255:         */
                    256:        opt = 1;
1.12      manu      257:        optlen = sizeof(opt);
                    258:        if (setsockopt(sv[1], 0, LOCAL_CREDS, &opt, optlen) != 0)
1.6       manu      259:                DWARN("%s: setsockopt LOCAL_CREDS failed", __func__);
                    260:
1.2       manu      261:        (void)sprintf(fdstr, "%d", sv[1]);
                    262:
                    263:        switch(fork()) {
                    264:        case -1:
                    265: #ifdef PERFUSE_DEBUG
1.5       manu      266:                DWARN("%s:%d: fork failed", __func__, __LINE__);
1.2       manu      267: #endif
                    268:                return -1;
                    269:                /* NOTREACHED */
                    270:                break;
                    271:        case 0:
1.25      manu      272:                (void)close(sv[0]);
1.12      manu      273:                (void)execve(argv[0], argv, environ);
1.2       manu      274: #ifdef PERFUSE_DEBUG
1.5       manu      275:                DWARN("%s:%d: execve failed", __func__, __LINE__);
1.2       manu      276: #endif
                    277:                return -1;
                    278:                /* NOTREACHED */
                    279:                break;
                    280:        default:
                    281:                break;
                    282:        }
                    283:
1.25      manu      284:        (void)close(sv[1]);
1.2       manu      285:        return sv[0];
1.1       manu      286: }
                    287:
                    288: int
1.26      matt      289: perfuse_mount(const char *source, const char *target,
                    290:        const char *filesystemtype, long mountflags, const void *data)
1.1       manu      291: {
                    292:        int s;
                    293:        size_t len;
1.6       manu      294:        struct perfuse_mount_out *pmo;
                    295:        struct sockaddr_storage ss;
1.7       manu      296:        struct sockaddr_un *sun;
1.6       manu      297:        struct sockaddr *sa;
                    298:        socklen_t sa_len;
                    299:        size_t sock_len;
                    300:        char *frame;
                    301:        char *cp;
1.1       manu      302:
                    303: #ifdef PERFUSE_DEBUG
1.5       manu      304:        if (perfuse_diagflags & PDF_MISC)
                    305:                DPRINTF("%s(\"%s\", \"%s\", \"%s\", 0x%lx, \"%s\")\n",
                    306:                        __func__, source, target, filesystemtype,
                    307:                        mountflags, (const char *)data);
1.1       manu      308: #endif
                    309:
                    310:        if ((s = get_fd(data)) == -1)
                    311:                return -1;
                    312:
1.6       manu      313:        /*
                    314:         * If we are connected to /dev/fuse, we need a second
                    315:         * socket to get replies from perfused.
                    316:         * XXX This socket is not removed at exit time yet
                    317:         */
                    318:        sock_len = 0;
                    319:        sa = (struct sockaddr *)(void *)&ss;
1.7       manu      320:        sun = (struct sockaddr_un *)(void *)&ss;
1.6       manu      321:        sa_len = sizeof(ss);
                    322:        if ((getpeername(s, sa, &sa_len) == 0) &&
                    323:            (sa->sa_family = AF_LOCAL) &&
1.7       manu      324:            (strcmp(sun->sun_path, _PATH_FUSE) == 0)) {
1.6       manu      325:
1.7       manu      326:                sun->sun_len = sizeof(*sun);
                    327:                sun->sun_family = AF_LOCAL;
                    328:                (void)sprintf(sun->sun_path, "%s/%s-%d",
1.6       manu      329:                              _PATH_TMP, getprogname(), getpid());
                    330:
1.7       manu      331:                if (bind(s, sa, (socklen_t)sa->sa_len) != 0)
1.6       manu      332:                        DERR(EX_OSERR, "%s:%d bind to \"%s\" failed",
1.7       manu      333:                             __func__, __LINE__, sun->sun_path);
1.6       manu      334:
1.7       manu      335:                sock_len = strlen(sun->sun_path) + 1;
1.6       manu      336:        }
                    337:
                    338:        len = sizeof(*pmo);
                    339:        len += source ? (uint32_t)strlen(source) + 1 : 0;
                    340:        len += target ? (uint32_t)strlen(target) + 1 : 0;
                    341:        len += filesystemtype ? (uint32_t)strlen(filesystemtype) + 1 : 0;
                    342:        len += data ? (uint32_t)strlen(data) + 1 : 0;
                    343:        len += sock_len;
                    344:
                    345:        if ((frame = malloc(len)) == NULL) {
1.1       manu      346: #ifdef PERFUSE_DEBUG
1.5       manu      347:                if (perfuse_diagflags & PDF_MISC)
1.6       manu      348:                        DWARN("%s:%d malloc failed", __func__, __LINE__);
1.1       manu      349: #endif
                    350:                return -1;
                    351:        }
1.6       manu      352:
                    353:        pmo = (struct perfuse_mount_out *)(void *)frame;
1.12      manu      354:        pmo->pmo_len = (uint32_t)len;
1.6       manu      355:        pmo->pmo_error = 0;
                    356:        pmo->pmo_unique = (uint64_t)-1;
                    357:        (void)strcpy(pmo->pmo_magic, PERFUSE_MOUNT_MAGIC);
                    358:
                    359:        pmo->pmo_source_len = source ? (uint32_t)strlen(source) + 1 : 0;
                    360:        pmo->pmo_target_len = target ? (uint32_t)strlen(target) + 1: 0;
                    361:        pmo->pmo_filesystemtype_len =
                    362:            filesystemtype ? (uint32_t)strlen(filesystemtype) + 1 : 0;
                    363:        pmo->pmo_mountflags = (uint32_t)mountflags;
                    364:        pmo->pmo_data_len = data ? (uint32_t)strlen(data) + 1 : 0;
1.12      manu      365:        pmo->pmo_sock_len = (uint32_t)sock_len;
1.1       manu      366:
1.6       manu      367:        cp = (char *)(void *)(pmo + 1);
                    368:
1.1       manu      369:        if (source) {
1.6       manu      370:                (void)strcpy(cp, source);
                    371:                cp += pmo->pmo_source_len;
1.1       manu      372:        }
                    373:
                    374:        if (target) {
1.6       manu      375:                (void)strcpy(cp, target);
                    376:                cp += pmo->pmo_target_len;
1.1       manu      377:        }
1.6       manu      378:
1.1       manu      379:        if (filesystemtype) {
1.6       manu      380:                (void)strcpy(cp, filesystemtype);
                    381:                cp += pmo->pmo_filesystemtype_len;
1.1       manu      382:        }
                    383:
                    384:        if (data) {
1.6       manu      385:                (void)strcpy(cp, data);
                    386:                cp += pmo->pmo_data_len;
                    387:        }
                    388:
                    389:        if (sock_len != 0) {
1.7       manu      390:                (void)strcpy(cp, sun->sun_path);
1.6       manu      391:                cp += pmo->pmo_sock_len;
                    392:        }
                    393:
1.12      manu      394:        if (send(s, frame, len, MSG_NOSIGNAL) != (ssize_t)len) {
1.1       manu      395: #ifdef PERFUSE_DEBUG
1.6       manu      396:                DWARN("%s:%d sendto failed", __func__, __LINE__);
1.1       manu      397: #endif
1.6       manu      398:                return -1;
1.1       manu      399:        }
                    400:
                    401:        return 0;
                    402: }
                    403:
                    404:
                    405: uint64_t
1.26      matt      406: perfuse_next_unique(struct puffs_usermount *pu)
1.1       manu      407: {
                    408:        struct perfuse_state *ps;
                    409:
                    410:        ps = puffs_getspecific(pu);
                    411:
                    412:        return ps->ps_unique++;
                    413: }
                    414:
1.37      christos  415: static void
                    416: updatelimit(const char *func, int lim, const char *name)
                    417: {
                    418:        struct rlimit rl;
                    419:
                    420:        /* Try infinity but that will fail unless we are root */
                    421:        rl.rlim_cur = RLIM_INFINITY;
                    422:        rl.rlim_max = RLIM_INFINITY;
                    423:        if (setrlimit(lim, &rl) != -1)
                    424:                return;
                    425:
                    426:        /* Get and set to the maximum allowed */
                    427:        if (getrlimit(lim, &rl) == -1)
                    428:                DERR(EX_OSERR, "%s: getrlimit %s failed", func, name);
                    429:
                    430:        rl.rlim_cur = rl.rlim_max;
                    431:        if (setrlimit(lim, &rl) == -1)
                    432:                DERR(EX_OSERR, "%s: setrlimit %s to %ju failed", func,
                    433:                    name, (uintmax_t)rl.rlim_cur);
                    434: }
                    435:
1.1       manu      436: struct puffs_usermount *
1.26      matt      437: perfuse_init(struct perfuse_callbacks *pc, struct perfuse_mount_info *pmi)
1.1       manu      438: {
                    439:        struct perfuse_state *ps;
                    440:        struct puffs_usermount *pu;
                    441:        struct puffs_ops *pops;
1.13      manu      442:        const char *source = _PATH_PUFFS;
                    443:        char *fstype;
1.1       manu      444:        unsigned int puffs_flags;
                    445:        struct puffs_node *pn_root;
                    446:        struct puffs_pathobj *po_root;
1.22      manu      447:
                    448:        /*
                    449:         * perfused can grow quite large, let assume there's enough ram ...
                    450:         */
1.37      christos  451:        updatelimit(__func__, RLIMIT_DATA, "RLIMIT_DATA");
                    452:        updatelimit(__func__, RLIMIT_AS, "RLIMIT_AS");
1.1       manu      453:
                    454:        ps = init_state();
1.2       manu      455:        ps->ps_owner_uid = pmi->pmi_uid;
1.1       manu      456:
1.13      manu      457:        if (pmi->pmi_source) {
                    458:                if ((ps->ps_source = strdup(pmi->pmi_source)) == NULL)
1.18      christos  459:                        DERR(EX_OSERR, "%s: strdup failed", __func__);
1.13      manu      460:
                    461:                source = ps->ps_source;
                    462:        }
                    463:
                    464:        if (pmi->pmi_filesystemtype) {
                    465:                size_t len;
                    466:
1.1       manu      467:                ps->ps_filesystemtype = strdup(pmi->pmi_filesystemtype);
1.13      manu      468:                if (ps->ps_filesystemtype == NULL)
1.18      christos  469:                        DERR(EX_OSERR, "%s: strdup failed", __func__);
1.13      manu      470:
                    471:                len = sizeof("perfuse|") + strlen(ps->ps_filesystemtype) + 1;
                    472:                if ((fstype = malloc(len)) == NULL)
1.18      christos  473:                        DERR(EX_OSERR, "%s: malloc failed", __func__);
1.13      manu      474:
                    475:                (void)sprintf(fstype, "perfuse|%s", ps->ps_filesystemtype);
                    476:        } else {
                    477:                if ((fstype = strdup("perfuse")) == NULL)
1.18      christos  478:                        DERR(EX_OSERR, "%s: strdup failed", __func__);
1.13      manu      479:        }
                    480:
                    481:        if ((ps->ps_target = strdup(pmi->pmi_target)) == NULL)
1.18      christos  482:                DERR(EX_OSERR, "%s: strdup failed", __func__);
1.13      manu      483:
1.1       manu      484:        ps->ps_mountflags = pmi->pmi_mountflags;
                    485:
                    486:        /*
                    487:         * Some options are forbidden for non root users
                    488:         */
1.2       manu      489:        if (ps->ps_owner_uid != 0)
1.1       manu      490:            ps->ps_mountflags |= MNT_NOSUID|MNT_NODEV;
                    491:
                    492:        PUFFSOP_INIT(pops);
                    493:        PUFFSOP_SET(pops, perfuse, fs, unmount);
                    494:        PUFFSOP_SET(pops, perfuse, fs, statvfs);
                    495:        PUFFSOP_SET(pops, perfuse, fs, sync);
                    496:        PUFFSOP_SET(pops, perfuse, node, lookup);
                    497:        PUFFSOP_SET(pops, perfuse, node, create);
                    498:        PUFFSOP_SET(pops, perfuse, node, mknod);
                    499:        PUFFSOP_SET(pops, perfuse, node, open);
                    500:        PUFFSOP_SET(pops, perfuse, node, close);
                    501:        PUFFSOP_SET(pops, perfuse, node, access);
                    502:        PUFFSOP_SET(pops, perfuse, node, getattr);
                    503:        PUFFSOP_SET(pops, perfuse, node, setattr);
                    504:        PUFFSOP_SET(pops, perfuse, node, poll);
                    505:        PUFFSOP_SET(pops, perfuse, node, fsync);
                    506:        PUFFSOP_SET(pops, perfuse, node, remove);
                    507:        PUFFSOP_SET(pops, perfuse, node, link);
                    508:        PUFFSOP_SET(pops, perfuse, node, rename);
                    509:        PUFFSOP_SET(pops, perfuse, node, mkdir);
                    510:        PUFFSOP_SET(pops, perfuse, node, rmdir);
                    511:        PUFFSOP_SET(pops, perfuse, node, symlink);
                    512:        PUFFSOP_SET(pops, perfuse, node, readdir);
                    513:        PUFFSOP_SET(pops, perfuse, node, readlink);
                    514:        PUFFSOP_SET(pops, perfuse, node, reclaim);
                    515:        PUFFSOP_SET(pops, perfuse, node, inactive);
                    516:        PUFFSOP_SET(pops, perfuse, node, print);
1.34      manu      517:        PUFFSOP_SET(pops, perfuse, node, pathconf);
1.1       manu      518:        PUFFSOP_SET(pops, perfuse, node, advlock);
                    519:        PUFFSOP_SET(pops, perfuse, node, read);
                    520:        PUFFSOP_SET(pops, perfuse, node, write);
1.16      manu      521: #ifdef PUFFS_EXTNAMELEN
                    522:        PUFFSOP_SET(pops, perfuse, node, getextattr);
                    523:        PUFFSOP_SET(pops, perfuse, node, setextattr);
                    524:        PUFFSOP_SET(pops, perfuse, node, listextattr);
                    525:        PUFFSOP_SET(pops, perfuse, node, deleteextattr);
                    526: #endif /* PUFFS_EXTNAMELEN */
1.28      manu      527: #ifdef PUFFS_KFLAG_CACHE_FS_TTL
                    528:        PUFFSOP_SET(pops, perfuse, node, getattr_ttl);
                    529:        PUFFSOP_SET(pops, perfuse, node, setattr_ttl);
                    530: #endif /* PUFFS_KFLAG_CACHE_FS_TTL */
1.29      manu      531: #ifdef PUFFS_SETATTR_FAF
                    532:        PUFFSOP_SET(pops, perfuse, node, write2);
                    533: #endif /* PUFFS_SETATTR_FAF */
1.32      manu      534: #ifdef PUFFS_OPEN_IO_DIRECT
                    535:        PUFFSOP_SET(pops, perfuse, node, open2);
                    536: #endif /* PUFFS_OPEN_IO_DIRECT */
1.35      manu      537: #ifdef PUFFS_HAVE_FALLOCATE
                    538:        PUFFSOP_SET(pops, perfuse, node, fallocate);
                    539: #endif /* PUFFS_HAVE_FALLOCATE */
1.1       manu      540:
1.17      manu      541:        /*
1.23      manu      542:         * PUFFS_KFLAG_NOCACHE_NAME is required so that we can see changes
1.27      manu      543:         * done by other machines in networked filesystems. In later
                    544:         * NetBSD releases we use the alternative PUFFS_KFLAG_CACHE_FS_TTL,
                    545:         * which implement name cache with a filesystem-provided TTL.
                    546:         */
                    547: #ifdef PUFFS_KFLAG_CACHE_FS_TTL
                    548:        puffs_flags = PUFFS_KFLAG_CACHE_FS_TTL;
                    549: #else
                    550:        puffs_flags = PUFFS_KFLAG_NOCACHE_NAME;
                    551: #endif
1.30      manu      552:
                    553:        /*
                    554:         * Do not lookuo ..
                    555:         * That means we keep all parent vnode active
                    556:         */
                    557: #ifdef PUFFS_KFLAG_CACHE_DOTDOT
                    558:        puffs_flags |= PUFFS_KFLAG_CACHE_DOTDOT;
                    559: #endif
1.27      manu      560:
                    561:        /*
                    562:         * It would be nice to avoid useless inactive, and only
                    563:         * get them on file open for writing (PUFFS does
                    564:         * CLOSE/WRITE/INACTIVE, therefore actual close must be
                    565:         * done at INACTIVE time). Unfortunatley, puffs_setback
                    566:         * crashes when called on OPEN, therefore leave it for
                    567:         * another day.
1.17      manu      568:         */
1.27      manu      569: #ifdef notyet
                    570:        puffs_flags |= PUFFS_FLAG_IAONDEMAND;
                    571: #endif
1.9       manu      572:
1.36      manu      573:        /*
                    574:         * FUSE filesystem do not expect [amc]time and size
                    575:         * updates to be sent by the kernel, they do the
                    576:         * updates on their own after other operations.
                    577:         */
                    578: #ifdef PUFFS_KFLAG_NOFLUSH_META
                    579:        puffs_flags |= PUFFS_KFLAG_NOFLUSH_META;
                    580: #endif
                    581:
1.1       manu      582:        if (perfuse_diagflags & PDF_PUFFS)
                    583:                puffs_flags |= PUFFS_FLAG_OPDUMP;
                    584:
1.13      manu      585:        if ((pu = puffs_init(pops, source, fstype, ps, puffs_flags)) == NULL)
1.18      christos  586:                DERR(EX_OSERR, "%s: puffs_init failed", __func__);
1.1       manu      587:
1.29      manu      588:        puffs_setncookiehash(pu, PUFFS_PNODEBUCKETS);
                    589:
1.1       manu      590:        ps->ps_pu = pu;
                    591:
                    592:        /*
                    593:         * Setup filesystem root
                    594:         */
1.10      manu      595:        pn_root = perfuse_new_pn(pu, "", NULL);
1.23      manu      596:        PERFUSE_NODE_DATA(pn_root)->pnd_nodeid = FUSE_ROOT_ID;
1.29      manu      597:        PERFUSE_NODE_DATA(pn_root)->pnd_parent_nodeid = FUSE_ROOT_ID;
                    598:        perfuse_node_cache(ps, pn_root);
1.1       manu      599:        puffs_setroot(pu, pn_root);
                    600:        ps->ps_fsid = pn_root->pn_va.va_fsid;
                    601:
                    602:        po_root = puffs_getrootpathobj(pu);
                    603:        if ((po_root->po_path = strdup("/")) == NULL)
                    604:                DERRX(EX_OSERR, "perfuse_mount_start() failed");
                    605:
                    606:        po_root->po_len = 1;
                    607:        puffs_path_buildhash(pu, po_root);
                    608:
                    609:        puffs_vattr_null(&pn_root->pn_va);
                    610:        pn_root->pn_va.va_type = VDIR;
                    611:        pn_root->pn_va.va_mode = 0755;
1.23      manu      612:        pn_root->pn_va.va_fileid = FUSE_ROOT_ID;
1.1       manu      613:
                    614:        ps->ps_root = pn_root;
                    615:
                    616:        /*
                    617:         *  Callbacks
                    618:         */
                    619:        ps->ps_new_msg = pc->pc_new_msg;
                    620:        ps->ps_xchg_msg = pc->pc_xchg_msg;
                    621:        ps->ps_destroy_msg = pc->pc_destroy_msg;
                    622:        ps->ps_get_inhdr = pc->pc_get_inhdr;
                    623:        ps->ps_get_inpayload = pc->pc_get_inpayload;
                    624:        ps->ps_get_outhdr = pc->pc_get_outhdr;
                    625:        ps->ps_get_outpayload = pc->pc_get_outpayload;
1.15      manu      626:        ps->ps_umount = pc->pc_umount;
1.1       manu      627:
1.29      manu      628:        pc->pc_fsreq = *perfuse_fsreq;
                    629:
1.1       manu      630:        return pu;
                    631: }
                    632:
                    633: void
1.26      matt      634: perfuse_setspecific(struct puffs_usermount *pu, void *priv)
1.1       manu      635: {
                    636:        struct perfuse_state *ps;
                    637:
                    638:        ps = puffs_getspecific(pu);
                    639:        ps->ps_private = priv;
                    640:
                    641:        return;
                    642: }
                    643:
                    644: void *
1.26      matt      645: perfuse_getspecific(struct puffs_usermount *pu)
1.1       manu      646: {
                    647:        struct perfuse_state *ps;
                    648:
                    649:        ps = puffs_getspecific(pu);
                    650:
                    651:        return ps->ps_private;
                    652: }
                    653:
                    654: int
1.26      matt      655: perfuse_inloop(struct puffs_usermount *pu)
1.1       manu      656: {
                    657:        struct perfuse_state *ps;
                    658:
                    659:        ps = puffs_getspecific(pu);
                    660:
                    661:        return ps->ps_flags & PS_INLOOP;
                    662: }
                    663:
                    664: int
1.26      matt      665: perfuse_mainloop(struct puffs_usermount *pu)
1.1       manu      666: {
                    667:        struct perfuse_state *ps;
                    668:
                    669:        ps = puffs_getspecific(pu);
                    670:
                    671:        ps->ps_flags |= PS_INLOOP;
1.15      manu      672:        if (puffs_mainloop(ps->ps_pu) != 0) {
1.18      christos  673:                DERR(EX_OSERR, "%s: failed", __func__);
1.15      manu      674:                return -1;
                    675:        }
1.1       manu      676:
1.15      manu      677:        /*
                    678:         * Normal exit after unmount
                    679:         */
                    680:        return 0;
1.1       manu      681: }
                    682:
                    683: /* ARGSUSED0 */
                    684: uint64_t
1.26      matt      685: perfuse_get_nodeid(struct puffs_usermount *pu, puffs_cookie_t opc)
1.1       manu      686: {
1.23      manu      687:        return PERFUSE_NODE_DATA(opc)->pnd_nodeid;
1.1       manu      688: }
1.2       manu      689:
                    690: int
1.26      matt      691: perfuse_unmount(struct puffs_usermount *pu)
1.2       manu      692: {
                    693:        struct perfuse_state *ps;
                    694:
                    695:        ps = puffs_getspecific(pu);
                    696:
                    697:        return unmount(ps->ps_target, MNT_FORCE);
                    698: }
1.29      manu      699:
                    700: void
                    701: perfuse_fsreq(struct puffs_usermount *pu, perfuse_msg_t *pm)
                    702: {
                    703:        struct perfuse_state *ps;
                    704:        struct fuse_out_header *foh;
                    705:
                    706:        ps = puffs_getspecific(pu);
                    707:        foh = GET_OUTHDR(ps, pm);
                    708:
                    709:        /*
                    710:         * There are some operations we may use in a  Fire and Forget wey,
                    711:         * because the kernel does not await a reply, but FUSE still
                    712:         * sends a reply. This happens for fsyc, setattr (for metadata
                    713:         * associated with a fsync) and write (for VOP_PUTPAGES). Ignore
                    714:         * if it was fine, warn or abort otherwise.
                    715:         */
                    716:        switch (foh->error) {
                    717:        case 0:
                    718:                break;
                    719:        case -ENOENT:
                    720:                /* File disapeared during a FAF operation */
                    721:                break;
                    722:        case -ENOTCONN: /* FALLTHROUGH */
                    723:        case -EAGAIN: /* FALLTHROUGH */
                    724:        case -EMSGSIZE:
                    725:                DWARN("operation unique = %"PRId64" failed", foh->unique);
                    726:                break;
                    727:        default:
1.31      manu      728:                DWARNX("Unexpected frame: unique = %"PRId64", error = %d",
                    729:                        foh->unique, foh->error);
1.29      manu      730:                /* NOTREACHED */
                    731:                break;
                    732:        }
                    733:
                    734:        ps->ps_destroy_msg(pm);
                    735:
                    736:        return;
                    737: }

CVSweb <webmaster@jp.NetBSD.org>