[BACK]Return to puffs_vfsops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / puffs

Annotation of src/sys/fs/puffs/puffs_vfsops.c, Revision 1.83

1.83    ! pooka       1: /*     $NetBSD: puffs_vfsops.c,v 1.82 2009/03/18 10:22:42 cegger Exp $ */
1.1       pooka       2:
                      3: /*
                      4:  * Copyright (c) 2005, 2006  Antti Kantee.  All Rights Reserved.
                      5:  *
                      6:  * Development of this software was supported by the
                      7:  * Google Summer of Code program and the Ulla Tuominen Foundation.
                      8:  * The Google SoC project was mentored by Bill Studenmund.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     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>
1.83    ! pooka      33: __KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.82 2009/03/18 10:22:42 cegger Exp $");
1.1       pooka      34:
                     35: #include <sys/param.h>
                     36: #include <sys/mount.h>
                     37: #include <sys/malloc.h>
                     38: #include <sys/extattr.h>
                     39: #include <sys/queue.h>
                     40: #include <sys/vnode.h>
                     41: #include <sys/dirent.h>
                     42: #include <sys/kauth.h>
1.47      ad         43: #include <sys/proc.h>
1.80      rumble     44: #include <sys/module.h>
1.1       pooka      45:
1.68      pooka      46: #include <dev/putter/putter_sys.h>
1.1       pooka      47:
1.78      dholland   48: #include <miscfs/genfs/genfs.h>
                     49:
1.1       pooka      50: #include <fs/puffs/puffs_msgif.h>
                     51: #include <fs/puffs/puffs_sys.h>
                     52:
1.66      pooka      53: #include <lib/libkern/libkern.h>
                     54:
1.38      pooka      55: #include <nfs/nfsproto.h> /* for fh sizes */
                     56:
1.81      jmcneill   57: MODULE(MODULE_CLASS_VFS, puffs, "putter");
1.80      rumble     58:
1.73      pooka      59: VFS_PROTOS(puffs_vfsop);
1.1       pooka      60:
1.22      pooka      61: #ifndef PUFFS_PNODEBUCKETS
                     62: #define PUFFS_PNODEBUCKETS 256
                     63: #endif
                     64: #ifndef PUFFS_MAXPNODEBUCKETS
1.35      pooka      65: #define PUFFS_MAXPNODEBUCKETS 8192
1.22      pooka      66: #endif
1.35      pooka      67: int puffs_pnodebuckets_default = PUFFS_PNODEBUCKETS;
                     68: int puffs_maxpnodebuckets = PUFFS_MAXPNODEBUCKETS;
1.22      pooka      69:
1.70      pooka      70: #define BUCKETALLOC(a) (sizeof(struct puffs_pnode_hashlist *) * (a))
                     71:
1.66      pooka      72: static struct putter_ops puffs_putter = {
                     73:        .pop_getout     = puffs_msgif_getout,
                     74:        .pop_releaseout = puffs_msgif_releaseout,
                     75:        .pop_waitcount  = puffs_msgif_waitcount,
                     76:        .pop_dispatch   = puffs_msgif_dispatch,
                     77:        .pop_close      = puffs_msgif_close,
                     78: };
                     79:
1.1       pooka      80: int
1.73      pooka      81: puffs_vfsop_mount(struct mount *mp, const char *path, void *data,
                     82:        size_t *data_len)
1.1       pooka      83: {
1.22      pooka      84:        struct puffs_mount *pmp = NULL;
1.34      pooka      85:        struct puffs_kargs *args;
1.51      pooka      86:        char fstype[_VFS_NAMELEN];
                     87:        char *p;
1.22      pooka      88:        int error = 0, i;
1.71      pooka      89:        pid_t mntpid = curlwp->l_proc->p_pid;
1.1       pooka      90:
1.48      dsl        91:        if (*data_len < sizeof *args)
                     92:                return EINVAL;
                     93:
1.1       pooka      94:        if (mp->mnt_flag & MNT_GETARGS) {
                     95:                pmp = MPTOPUFFSMP(mp);
1.48      dsl        96:                *(struct puffs_kargs *)data = pmp->pmp_args;
                     97:                *data_len = sizeof *args;
                     98:                return 0;
1.1       pooka      99:        }
                    100:
                    101:        /* update is not supported currently */
                    102:        if (mp->mnt_flag & MNT_UPDATE)
                    103:                return EOPNOTSUPP;
                    104:
                    105:        /*
                    106:         * We need the file system name
                    107:         */
                    108:        if (!data)
                    109:                return EINVAL;
                    110:
1.70      pooka     111:        args = (struct puffs_kargs *)data;
1.17      pooka     112:
                    113:        /* devel phase */
                    114:        if (args->pa_vers != (PUFFSVERSION | PUFFSDEVELVERS)) {
1.64      pooka     115:                printf("puffs_mount: development version mismatch: "
                    116:                    "kernel %d, lib %d\n",
                    117:                    PUFFSVERSION, args->pa_vers & ~PUFFSDEVELVERS);
1.17      pooka     118:                error = EINVAL;
                    119:                goto out;
                    120:        }
1.1       pooka     121:
1.54      pooka     122:        if ((args->pa_flags & ~PUFFS_KFLAG_MASK) != 0) {
                    123:                printf("puffs_mount: invalid KFLAGs 0x%x\n", args->pa_flags);
                    124:                error = EINVAL;
                    125:                goto out;
                    126:        }
                    127:        if ((args->pa_fhflags & ~PUFFS_FHFLAG_MASK) != 0) {
                    128:                printf("puffs_mount: invalid FHFLAGs 0x%x\n", args->pa_fhflags);
                    129:                error = EINVAL;
                    130:                goto out;
                    131:        }
                    132:
                    133:        /* use dummy value for passthrough */
                    134:        if (args->pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH)
                    135:                args->pa_fhsize = sizeof(struct fid);
1.8       pooka     136:
1.38      pooka     137:        /* sanitize file handle length */
                    138:        if (PUFFS_TOFHSIZE(args->pa_fhsize) > FHANDLE_SIZE_MAX) {
                    139:                printf("puffs_mount: handle size %zu too large\n",
                    140:                    args->pa_fhsize);
                    141:                error = EINVAL;
                    142:                goto out;
                    143:        }
                    144:        /* sanity check file handle max sizes */
                    145:        if (args->pa_fhsize && args->pa_fhflags & PUFFS_FHFLAG_PROTOMASK) {
                    146:                size_t kfhsize = PUFFS_TOFHSIZE(args->pa_fhsize);
                    147:
                    148:                if (args->pa_fhflags & PUFFS_FHFLAG_NFSV2) {
                    149:                        if (NFSX_FHTOOBIG_P(kfhsize, 0)) {
                    150:                                printf("puffs_mount: fhsize larger than "
                    151:                                    "NFSv2 max %d\n",
                    152:                                    PUFFS_FROMFHSIZE(NFSX_V2FH));
                    153:                                error = EINVAL;
                    154:                                goto out;
                    155:                        }
                    156:                }
                    157:
                    158:                if (args->pa_fhflags & PUFFS_FHFLAG_NFSV3) {
                    159:                        if (NFSX_FHTOOBIG_P(kfhsize, 1)) {
                    160:                                printf("puffs_mount: fhsize larger than "
                    161:                                    "NFSv3 max %d\n",
                    162:                                    PUFFS_FROMFHSIZE(NFSX_V3FHMAX));
                    163:                                error = EINVAL;
                    164:                                goto out;
                    165:                        }
                    166:                }
                    167:        }
                    168:
1.51      pooka     169:        /* don't allow non-printing characters (like my sweet umlauts.. snif) */
                    170:        args->pa_typename[sizeof(args->pa_typename)-1] = '\0';
                    171:        for (p = args->pa_typename; *p; p++)
                    172:                if (*p < ' ' || *p > '~')
                    173:                        *p = '.';
                    174:
                    175:        args->pa_mntfromname[sizeof(args->pa_mntfromname)-1] = '\0';
                    176:        for (p = args->pa_mntfromname; *p; p++)
                    177:                if (*p < ' ' || *p > '~')
                    178:                        *p = '.';
                    179:
1.1       pooka     180:        /* build real name */
1.51      pooka     181:        (void)strlcpy(fstype, PUFFS_TYPEPREFIX, sizeof(fstype));
                    182:        (void)strlcat(fstype, args->pa_typename, sizeof(fstype));
1.1       pooka     183:
                    184:        /* inform user server if it got the max request size it wanted */
1.63      pooka     185:        if (args->pa_maxmsglen == 0 || args->pa_maxmsglen > PUFFS_MSG_MAXSIZE)
                    186:                args->pa_maxmsglen = PUFFS_MSG_MAXSIZE;
                    187:        else if (args->pa_maxmsglen < 2*PUFFS_MSGSTRUCT_MAX)
                    188:                args->pa_maxmsglen = 2*PUFFS_MSGSTRUCT_MAX;
                    189:
1.51      pooka     190:        (void)strlcpy(args->pa_typename, fstype, sizeof(args->pa_typename));
1.1       pooka     191:
1.40      pooka     192:        if (args->pa_nhashbuckets == 0)
                    193:                args->pa_nhashbuckets = puffs_pnodebuckets_default;
                    194:        if (args->pa_nhashbuckets < 1)
                    195:                args->pa_nhashbuckets = 1;
                    196:        if (args->pa_nhashbuckets > PUFFS_MAXPNODEBUCKETS) {
                    197:                args->pa_nhashbuckets = puffs_maxpnodebuckets;
                    198:                printf("puffs_mount: using %d hash buckets. "
                    199:                    "adjust puffs_maxpnodebuckets for more\n",
                    200:                    puffs_maxpnodebuckets);
                    201:        }
                    202:
1.51      pooka     203:        error = set_statvfs_info(path, UIO_USERSPACE, args->pa_mntfromname,
1.71      pooka     204:            UIO_SYSSPACE, fstype, mp, curlwp);
1.1       pooka     205:        if (error)
1.17      pooka     206:                goto out;
1.10      pooka     207:        mp->mnt_stat.f_iosize = DEV_BSIZE;
1.1       pooka     208:
1.42      pooka     209:        /*
                    210:         * We can't handle the VFS_STATVFS() mount_domount() does
                    211:         * after VFS_MOUNT() because we'd deadlock, so handle it
                    212:         * here already.
                    213:         */
                    214:        copy_statvfs_info(&args->pa_svfsb, mp);
                    215:        (void)memcpy(&mp->mnt_stat, &args->pa_svfsb, sizeof(mp->mnt_stat));
                    216:
1.70      pooka     217:        pmp = kmem_zalloc(sizeof(struct puffs_mount), KM_SLEEP);
1.1       pooka     218:
1.6       pooka     219:        mp->mnt_fs_bshift = DEV_BSHIFT;
                    220:        mp->mnt_dev_bshift = DEV_BSHIFT;
                    221:        mp->mnt_flag &= ~MNT_LOCAL; /* we don't really know, so ... */
1.1       pooka     222:        mp->mnt_data = pmp;
1.6       pooka     223:
1.1       pooka     224:        pmp->pmp_status = PUFFSTAT_MOUNTING;
                    225:        pmp->pmp_mp = mp;
1.63      pooka     226:        pmp->pmp_msg_maxsize = args->pa_maxmsglen;
1.17      pooka     227:        pmp->pmp_args = *args;
1.1       pooka     228:
1.40      pooka     229:        pmp->pmp_npnodehash = args->pa_nhashbuckets;
1.70      pooka     230:        pmp->pmp_pnodehash = kmem_alloc(BUCKETALLOC(pmp->pmp_npnodehash), KM_SLEEP);
1.22      pooka     231:        for (i = 0; i < pmp->pmp_npnodehash; i++)
                    232:                LIST_INIT(&pmp->pmp_pnodehash[i]);
1.57      pooka     233:        LIST_INIT(&pmp->pmp_newcookie);
1.22      pooka     234:
1.1       pooka     235:        /*
                    236:         * Inform the fileops processing code that we have a mountpoint.
                    237:         * If it doesn't know about anyone with our pid/fd having the
                    238:         * device open, punt
                    239:         */
1.66      pooka     240:        if ((pmp->pmp_pi
                    241:            = putter_attach(mntpid, args->pa_fd, pmp, &puffs_putter)) == NULL) {
1.17      pooka     242:                error = ENOENT;
                    243:                goto out;
1.1       pooka     244:        }
                    245:
1.42      pooka     246:        /* XXX: check parameters */
                    247:        pmp->pmp_root_cookie = args->pa_root_cookie;
                    248:        pmp->pmp_root_vtype = args->pa_root_vtype;
                    249:        pmp->pmp_root_vsize = args->pa_root_vsize;
                    250:        pmp->pmp_root_rdev = args->pa_root_rdev;
                    251:
1.31      pooka     252:        mutex_init(&pmp->pmp_lock, MUTEX_DEFAULT, IPL_NONE);
1.63      pooka     253:        cv_init(&pmp->pmp_msg_waiter_cv, "puffsget");
1.41      pooka     254:        cv_init(&pmp->pmp_refcount_cv, "puffsref");
1.31      pooka     255:        cv_init(&pmp->pmp_unmounting_cv, "puffsum");
1.63      pooka     256:        TAILQ_INIT(&pmp->pmp_msg_touser);
                    257:        TAILQ_INIT(&pmp->pmp_msg_replywait);
1.1       pooka     258:
                    259:        DPRINTF(("puffs_mount: mount point at %p, puffs specific at %p\n",
                    260:            mp, MPTOPUFFSMP(mp)));
                    261:
                    262:        vfs_getnewfsid(mp);
                    263:
1.17      pooka     264:  out:
1.22      pooka     265:        if (error && pmp && pmp->pmp_pnodehash)
1.70      pooka     266:                kmem_free(pmp->pmp_pnodehash, BUCKETALLOC(pmp->pmp_npnodehash));
1.22      pooka     267:        if (error && pmp)
1.70      pooka     268:                kmem_free(pmp, sizeof(struct puffs_mount));
1.17      pooka     269:        return error;
1.1       pooka     270: }
                    271:
                    272: int
1.73      pooka     273: puffs_vfsop_start(struct mount *mp, int flags)
1.1       pooka     274: {
1.42      pooka     275:        struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.1       pooka     276:
1.42      pooka     277:        KASSERT(pmp->pmp_status == PUFFSTAT_MOUNTING);
1.1       pooka     278:        pmp->pmp_status = PUFFSTAT_RUNNING;
                    279:
                    280:        return 0;
                    281: }
                    282:
                    283: int
1.73      pooka     284: puffs_vfsop_unmount(struct mount *mp, int mntflags)
1.1       pooka     285: {
1.63      pooka     286:        PUFFS_MSG_VARS(vfs, unmount);
1.1       pooka     287:        struct puffs_mount *pmp;
                    288:        int error, force;
                    289:
                    290:        error = 0;
                    291:        force = mntflags & MNT_FORCE;
                    292:        pmp = MPTOPUFFSMP(mp);
                    293:
                    294:        DPRINTF(("puffs_unmount: detach filesystem from vfs, current "
                    295:            "status 0x%x\n", pmp->pmp_status));
                    296:
                    297:        /*
                    298:         * flush all the vnodes.  VOP_RECLAIM() takes care that the
                    299:         * root vnode does not get flushed until unmount.  The
                    300:         * userspace root node cookie is stored in the mount
                    301:         * structure, so we can always re-instantiate a root vnode,
                    302:         * should userspace unmount decide it doesn't want to
                    303:         * cooperate.
                    304:         */
                    305:        error = vflush(mp, NULLVP, force ? FORCECLOSE : 0);
                    306:        if (error)
                    307:                goto out;
                    308:
                    309:        /*
                    310:         * If we are not DYING, we should ask userspace's opinion
                    311:         * about the situation
                    312:         */
1.31      pooka     313:        mutex_enter(&pmp->pmp_lock);
1.1       pooka     314:        if (pmp->pmp_status != PUFFSTAT_DYING) {
1.16      pooka     315:                pmp->pmp_unmounting = 1;
1.31      pooka     316:                mutex_exit(&pmp->pmp_lock);
1.16      pooka     317:
1.63      pooka     318:                PUFFS_MSG_ALLOC(vfs, unmount);
1.69      pooka     319:                puffs_msg_setinfo(park_unmount,
                    320:                    PUFFSOP_VFS, PUFFS_VFS_UNMOUNT, NULL);
1.63      pooka     321:                unmount_msg->pvfsr_flags = mntflags;
                    322:
1.69      pooka     323:                PUFFS_MSG_ENQUEUEWAIT(pmp, park_unmount, error);
1.63      pooka     324:                PUFFS_MSG_RELEASE(unmount);
1.16      pooka     325:
1.60      pooka     326:                error = checkerr(pmp, error, __func__);
1.16      pooka     327:                DPRINTF(("puffs_unmount: error %d force %d\n", error, force));
                    328:
1.31      pooka     329:                mutex_enter(&pmp->pmp_lock);
1.16      pooka     330:                pmp->pmp_unmounting = 0;
1.31      pooka     331:                cv_broadcast(&pmp->pmp_unmounting_cv);
1.1       pooka     332:        }
                    333:
                    334:        /*
                    335:         * if userspace cooperated or we really need to die,
                    336:         * screw what userland thinks and just die.
                    337:         */
                    338:        if (error == 0 || force) {
1.26      pooka     339:                /* tell waiters & other resources to go unwait themselves */
                    340:                puffs_userdead(pmp);
1.66      pooka     341:                putter_detach(pmp->pmp_pi);
1.26      pooka     342:
                    343:                /*
1.41      pooka     344:                 * Wait until there are no more users for the mount resource.
                    345:                 * Notice that this is hooked against transport_close
                    346:                 * and return from touser.  In an ideal world, it would
                    347:                 * be hooked against final return from all operations.
                    348:                 * But currently it works well enough, since nobody
                    349:                 * does weird blocking voodoo after return from touser().
1.26      pooka     350:                 */
1.41      pooka     351:                while (pmp->pmp_refcount != 0)
                    352:                        cv_wait(&pmp->pmp_refcount_cv, &pmp->pmp_lock);
1.31      pooka     353:                mutex_exit(&pmp->pmp_lock);
1.26      pooka     354:
                    355:                /* free resources now that we hopefully have no waiters left */
1.41      pooka     356:                cv_destroy(&pmp->pmp_unmounting_cv);
                    357:                cv_destroy(&pmp->pmp_refcount_cv);
1.63      pooka     358:                cv_destroy(&pmp->pmp_msg_waiter_cv);
1.31      pooka     359:                mutex_destroy(&pmp->pmp_lock);
                    360:
1.70      pooka     361:                kmem_free(pmp->pmp_pnodehash, BUCKETALLOC(pmp->pmp_npnodehash));
                    362:                kmem_free(pmp, sizeof(struct puffs_mount));
1.1       pooka     363:                error = 0;
1.16      pooka     364:        } else {
1.31      pooka     365:                mutex_exit(&pmp->pmp_lock);
1.1       pooka     366:        }
                    367:
                    368:  out:
1.2       pooka     369:        DPRINTF(("puffs_unmount: return %d\n", error));
1.1       pooka     370:        return error;
                    371: }
                    372:
                    373: /*
                    374:  * This doesn't need to travel to userspace
                    375:  */
                    376: int
1.73      pooka     377: puffs_vfsop_root(struct mount *mp, struct vnode **vpp)
1.1       pooka     378: {
1.45      pooka     379:        struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.59      pooka     380:        int rv;
1.1       pooka     381:
1.59      pooka     382:        rv = puffs_cookie2vnode(pmp, pmp->pmp_root_cookie, 1, 1, vpp);
                    383:        KASSERT(rv != PUFFS_NOSUCHCOOKIE);
                    384:        return rv;
1.1       pooka     385: }
                    386:
                    387: int
1.73      pooka     388: puffs_vfsop_statvfs(struct mount *mp, struct statvfs *sbp)
1.1       pooka     389: {
1.63      pooka     390:        PUFFS_MSG_VARS(vfs, statvfs);
1.1       pooka     391:        struct puffs_mount *pmp;
                    392:        int error = 0;
                    393:
                    394:        pmp = MPTOPUFFSMP(mp);
                    395:
                    396:        /*
                    397:         * If we are mounting, it means that the userspace counterpart
                    398:         * is calling mount(2), but mount(2) also calls statvfs.  So
                    399:         * requesting statvfs from userspace would mean a deadlock.
                    400:         * Compensate.
                    401:         */
                    402:        if (pmp->pmp_status == PUFFSTAT_MOUNTING)
                    403:                return EINPROGRESS;
                    404:
1.63      pooka     405:        PUFFS_MSG_ALLOC(vfs, statvfs);
1.69      pooka     406:        puffs_msg_setinfo(park_statvfs, PUFFSOP_VFS, PUFFS_VFS_STATVFS, NULL);
1.1       pooka     407:
1.69      pooka     408:        PUFFS_MSG_ENQUEUEWAIT(pmp, park_statvfs, error);
1.60      pooka     409:        error = checkerr(pmp, error, __func__);
1.63      pooka     410:        statvfs_msg->pvfsr_sb.f_iosize = DEV_BSIZE;
1.10      pooka     411:
1.1       pooka     412:        /*
                    413:         * Try to produce a sensible result even in the event
                    414:         * of userspace error.
                    415:         *
                    416:         * XXX: cache the copy in non-error case
                    417:         */
                    418:        if (!error) {
1.63      pooka     419:                copy_statvfs_info(&statvfs_msg->pvfsr_sb, mp);
                    420:                (void)memcpy(sbp, &statvfs_msg->pvfsr_sb,
1.1       pooka     421:                    sizeof(struct statvfs));
                    422:        } else {
                    423:                copy_statvfs_info(sbp, mp);
                    424:        }
                    425:
1.63      pooka     426:        PUFFS_MSG_RELEASE(statvfs);
1.14      pooka     427:        return error;
1.1       pooka     428: }
                    429:
1.26      pooka     430: static int
1.83    ! pooka     431: pageflush(struct mount *mp, kauth_cred_t cred, int waitfor)
1.1       pooka     432: {
1.26      pooka     433:        struct puffs_node *pn;
1.74      ad        434:        struct vnode *vp, *mvp;
1.30      pooka     435:        int error, rv;
1.1       pooka     436:
1.18      pooka     437:        error = 0;
                    438:
1.74      ad        439:        /* Allocate a marker vnode. */
1.76      pooka     440:        if ((mvp = vnalloc(mp)) == NULL)
1.74      ad        441:                return ENOMEM;
                    442:
1.18      pooka     443:        /*
1.24      pooka     444:         * Sync all cached data from regular vnodes (which are not
                    445:         * currently locked, see below).  After this we call VFS_SYNC
                    446:         * for the fs server, which should handle data and metadata for
                    447:         * all the nodes it knows to exist.
1.18      pooka     448:         */
1.74      ad        449:        mutex_enter(&mntvnode_lock);
1.18      pooka     450:  loop:
1.74      ad        451:        for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = vunmark(mvp)) {
                    452:                vmark(mvp, vp);
                    453:                if (vp->v_mount != mp || vismarker(vp))
                    454:                        continue;
1.18      pooka     455:
1.74      ad        456:                mutex_enter(&vp->v_interlock);
1.26      pooka     457:                pn = VPTOPP(vp);
1.19      pooka     458:                if (vp->v_type != VREG || UVM_OBJ_IS_CLEAN(&vp->v_uobj)) {
1.74      ad        459:                        mutex_exit(&vp->v_interlock);
1.18      pooka     460:                        continue;
                    461:                }
                    462:
1.74      ad        463:                mutex_exit(&mntvnode_lock);
1.21      pooka     464:
                    465:                /*
                    466:                 * Here we try to get a reference to the vnode and to
                    467:                 * lock it.  This is mostly cargo-culted, but I will
                    468:                 * offer an explanation to why I believe this might
                    469:                 * actually do the right thing.
                    470:                 *
                    471:                 * If the vnode is a goner, we quite obviously don't need
                    472:                 * to sync it.
                    473:                 *
                    474:                 * If the vnode was busy, we don't need to sync it because
                    475:                 * this is never called with MNT_WAIT except from
                    476:                 * dounmount(), when we are wait-flushing all the dirty
                    477:                 * vnodes through other routes in any case.  So there,
                    478:                 * sync() doesn't actually sync.  Happy now?
                    479:                 */
1.18      pooka     480:                rv = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK);
                    481:                if (rv) {
1.74      ad        482:                        mutex_enter(&mntvnode_lock);
                    483:                        if (rv == ENOENT) {
                    484:                                (void)vunmark(mvp);
1.18      pooka     485:                                goto loop;
1.74      ad        486:                        }
1.18      pooka     487:                        continue;
                    488:                }
                    489:
1.83    ! pooka     490:                /* hmm.. is the FAF thing entirely sensible? */
        !           491:                if (waitfor == MNT_LAZY) {
1.74      ad        492:                        mutex_enter(&vp->v_interlock);
1.83    ! pooka     493:                        pn->pn_stat |= PNODE_FAF;
1.74      ad        494:                        mutex_exit(&vp->v_interlock);
1.30      pooka     495:                }
1.71      pooka     496:                rv = VOP_FSYNC(vp, cred, waitfor, 0, 0);
1.83    ! pooka     497:                if (waitfor == MNT_LAZY) {
1.74      ad        498:                        mutex_enter(&vp->v_interlock);
1.83    ! pooka     499:                        pn->pn_stat &= ~PNODE_FAF;
1.74      ad        500:                        mutex_exit(&vp->v_interlock);
1.26      pooka     501:                }
1.21      pooka     502:                if (rv)
1.18      pooka     503:                        error = rv;
                    504:                vput(vp);
1.74      ad        505:                mutex_enter(&mntvnode_lock);
1.18      pooka     506:        }
1.74      ad        507:        mutex_exit(&mntvnode_lock);
1.76      pooka     508:        vnfree(mvp);
1.18      pooka     509:
1.26      pooka     510:        return error;
                    511: }
                    512:
                    513: int
1.73      pooka     514: puffs_vfsop_sync(struct mount *mp, int waitfor, struct kauth_cred *cred)
1.26      pooka     515: {
1.63      pooka     516:        PUFFS_MSG_VARS(vfs, sync);
1.62      pooka     517:        struct puffs_mount *pmp = MPTOPUFFSMP(mp);
1.26      pooka     518:        int error, rv;
                    519:
1.83    ! pooka     520:        error = pageflush(mp, cred, waitfor);
1.26      pooka     521:
1.18      pooka     522:        /* sync fs */
1.63      pooka     523:        PUFFS_MSG_ALLOC(vfs, sync);
                    524:        sync_msg->pvfsr_waitfor = waitfor;
                    525:        puffs_credcvt(&sync_msg->pvfsr_cred, cred);
1.69      pooka     526:        puffs_msg_setinfo(park_sync, PUFFSOP_VFS, PUFFS_VFS_SYNC, NULL);
1.1       pooka     527:
1.69      pooka     528:        PUFFS_MSG_ENQUEUEWAIT(pmp, park_sync, rv);
1.62      pooka     529:        rv = checkerr(pmp, rv, __func__);
1.18      pooka     530:        if (rv)
                    531:                error = rv;
1.1       pooka     532:
1.63      pooka     533:        PUFFS_MSG_RELEASE(sync);
1.1       pooka     534:        return error;
                    535: }
                    536:
                    537: int
1.73      pooka     538: puffs_vfsop_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
1.1       pooka     539: {
1.63      pooka     540:        PUFFS_MSG_VARS(vfs, fhtonode);
1.33      pooka     541:        struct puffs_mount *pmp = MPTOPUFFSMP(mp);
                    542:        struct vnode *vp;
1.54      pooka     543:        void *fhdata;
                    544:        size_t argsize, fhlen;
1.33      pooka     545:        int error;
                    546:
1.38      pooka     547:        if (pmp->pmp_args.pa_fhsize == 0)
1.33      pooka     548:                return EOPNOTSUPP;
                    549:
1.54      pooka     550:        if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) {
                    551:                fhlen = fhp->fid_len;
                    552:                fhdata = fhp;
1.39      pooka     553:        } else {
1.54      pooka     554:                fhlen = PUFFS_FROMFHSIZE(fhp->fid_len);
                    555:                fhdata = fhp->fid_data;
                    556:
                    557:                if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC) {
                    558:                        if (pmp->pmp_args.pa_fhsize < fhlen)
                    559:                                return EINVAL;
                    560:                } else {
                    561:                        if (pmp->pmp_args.pa_fhsize != fhlen)
                    562:                                return EINVAL;
                    563:                }
1.39      pooka     564:        }
1.33      pooka     565:
1.63      pooka     566:        argsize = sizeof(struct puffs_vfsmsg_fhtonode) + fhlen;
1.75      pooka     567:        puffs_msgmem_alloc(argsize, &park_fhtonode, (void *)&fhtonode_msg, 1);
1.63      pooka     568:        fhtonode_msg->pvfsr_dsize = fhlen;
                    569:        memcpy(fhtonode_msg->pvfsr_data, fhdata, fhlen);
1.69      pooka     570:        puffs_msg_setinfo(park_fhtonode, PUFFSOP_VFS, PUFFS_VFS_FHTOVP, NULL);
1.33      pooka     571:
1.69      pooka     572:        PUFFS_MSG_ENQUEUEWAIT(pmp, park_fhtonode, error);
1.60      pooka     573:        error = checkerr(pmp, error, __func__);
1.33      pooka     574:        if (error)
1.38      pooka     575:                goto out;
1.33      pooka     576:
1.63      pooka     577:        error = puffs_cookie2vnode(pmp, fhtonode_msg->pvfsr_fhcookie, 1,1,&vp);
1.33      pooka     578:        DPRINTF(("puffs_fhtovp: got cookie %p, existing vnode %p\n",
1.63      pooka     579:            fhtonode_msg->pvfsr_fhcookie, vp));
1.59      pooka     580:        if (error == PUFFS_NOSUCHCOOKIE) {
1.63      pooka     581:                error = puffs_getvnode(mp, fhtonode_msg->pvfsr_fhcookie,
                    582:                    fhtonode_msg->pvfsr_vtype, fhtonode_msg->pvfsr_size,
                    583:                    fhtonode_msg->pvfsr_rdev, &vp);
1.33      pooka     584:                if (error)
1.38      pooka     585:                        goto out;
1.33      pooka     586:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.59      pooka     587:        } else if (error) {
                    588:                goto out;
1.33      pooka     589:        }
1.1       pooka     590:
1.33      pooka     591:        *vpp = vp;
1.38      pooka     592:  out:
1.63      pooka     593:        puffs_msgmem_release(park_fhtonode);
1.38      pooka     594:        return error;
1.1       pooka     595: }
                    596:
                    597: int
1.73      pooka     598: puffs_vfsop_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)
1.1       pooka     599: {
1.63      pooka     600:        PUFFS_MSG_VARS(vfs, nodetofh);
1.33      pooka     601:        struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
1.54      pooka     602:        size_t argsize, fhlen;
1.33      pooka     603:        int error;
                    604:
1.38      pooka     605:        if (pmp->pmp_args.pa_fhsize == 0)
1.33      pooka     606:                return EOPNOTSUPP;
                    607:
1.54      pooka     608:        /* if file handles are static len, we can test len immediately */
1.38      pooka     609:        if (((pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC) == 0)
1.54      pooka     610:            && ((pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) == 0)
1.38      pooka     611:            && (PUFFS_FROMFHSIZE(*fh_size) < pmp->pmp_args.pa_fhsize)) {
                    612:                *fh_size = PUFFS_TOFHSIZE(pmp->pmp_args.pa_fhsize);
1.33      pooka     613:                return E2BIG;
                    614:        }
1.1       pooka     615:
1.54      pooka     616:        if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH)
                    617:                fhlen = *fh_size;
                    618:        else
                    619:                fhlen = PUFFS_FROMFHSIZE(*fh_size);
                    620:
1.63      pooka     621:        argsize = sizeof(struct puffs_vfsmsg_nodetofh) + fhlen;
1.75      pooka     622:        puffs_msgmem_alloc(argsize, &park_nodetofh, (void *)&nodetofh_msg, 1);
1.63      pooka     623:        nodetofh_msg->pvfsr_fhcookie = VPTOPNC(vp);
                    624:        nodetofh_msg->pvfsr_dsize = fhlen;
1.69      pooka     625:        puffs_msg_setinfo(park_nodetofh, PUFFSOP_VFS, PUFFS_VFS_VPTOFH, NULL);
1.38      pooka     626:
1.69      pooka     627:        PUFFS_MSG_ENQUEUEWAIT(pmp, park_nodetofh, error);
1.60      pooka     628:        error = checkerr(pmp, error, __func__);
1.54      pooka     629:
                    630:        if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH)
1.63      pooka     631:                fhlen = nodetofh_msg->pvfsr_dsize;
1.54      pooka     632:        else if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_DYNAMIC)
1.63      pooka     633:                fhlen = PUFFS_TOFHSIZE(nodetofh_msg->pvfsr_dsize);
1.54      pooka     634:        else
                    635:                fhlen = PUFFS_TOFHSIZE(pmp->pmp_args.pa_fhsize);
                    636:
1.38      pooka     637:        if (error) {
                    638:                if (error == E2BIG)
1.54      pooka     639:                        *fh_size = fhlen;
1.38      pooka     640:                goto out;
                    641:        }
                    642:
1.54      pooka     643:        if (fhlen > FHANDLE_SIZE_MAX) {
1.69      pooka     644:                puffs_senderr(pmp, PUFFS_ERR_VPTOFH, E2BIG,
1.60      pooka     645:                    "file handle too big", VPTOPNC(vp));
1.58      pooka     646:                error = EPROTO;
1.38      pooka     647:                goto out;
                    648:        }
1.33      pooka     649:
1.54      pooka     650:        if (*fh_size < fhlen) {
                    651:                *fh_size = fhlen;
1.38      pooka     652:                error = E2BIG;
                    653:                goto out;
                    654:        }
1.54      pooka     655:        *fh_size = fhlen;
1.1       pooka     656:
1.38      pooka     657:        if (fhp) {
1.54      pooka     658:                if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) {
1.63      pooka     659:                        memcpy(fhp, nodetofh_msg->pvfsr_data, fhlen);
1.54      pooka     660:                } else {
                    661:                        fhp->fid_len = *fh_size;
1.63      pooka     662:                        memcpy(fhp->fid_data, nodetofh_msg->pvfsr_data,
                    663:                            nodetofh_msg->pvfsr_dsize);
1.54      pooka     664:                }
1.38      pooka     665:        }
1.1       pooka     666:
1.38      pooka     667:  out:
1.63      pooka     668:        puffs_msgmem_release(park_nodetofh);
1.38      pooka     669:        return error;
1.1       pooka     670: }
                    671:
                    672: void
1.82      cegger    673: puffs_vfsop_init(void)
1.1       pooka     674: {
                    675:
1.56      pooka     676:        /* some checks depend on this */
                    677:        KASSERT(VNOVAL == VSIZENOTSET);
                    678:
1.31      pooka     679:        pool_init(&puffs_pnpool, sizeof(struct puffs_node), 0, 0, 0,
                    680:            "puffpnpl", &pool_allocator_nointr, IPL_NONE);
                    681:        puffs_msgif_init();
1.1       pooka     682: }
                    683:
                    684: void
1.82      cegger    685: puffs_vfsop_done(void)
1.1       pooka     686: {
                    687:
1.31      pooka     688:        puffs_msgif_destroy();
                    689:        pool_destroy(&puffs_pnpool);
1.1       pooka     690: }
                    691:
                    692: int
1.73      pooka     693: puffs_vfsop_snapshot(struct mount *mp, struct vnode *vp, struct timespec *ts)
1.1       pooka     694: {
                    695:
                    696:        return EOPNOTSUPP;
                    697: }
                    698:
                    699: const struct vnodeopv_desc * const puffs_vnodeopv_descs[] = {
                    700:        &puffs_vnodeop_opv_desc,
1.3       pooka     701:        &puffs_specop_opv_desc,
1.4       pooka     702:        &puffs_fifoop_opv_desc,
1.12      pooka     703:        &puffs_msgop_opv_desc,
1.1       pooka     704:        NULL,
                    705: };
                    706:
                    707: struct vfsops puffs_vfsops = {
                    708:        MOUNT_PUFFS,
1.48      dsl       709:        sizeof (struct puffs_kargs),
1.73      pooka     710:        puffs_vfsop_mount,              /* mount        */
                    711:        puffs_vfsop_start,              /* start        */
                    712:        puffs_vfsop_unmount,            /* unmount      */
                    713:        puffs_vfsop_root,               /* root         */
                    714:        (void *)eopnotsupp,             /* quotactl     */
                    715:        puffs_vfsop_statvfs,            /* statvfs      */
                    716:        puffs_vfsop_sync,               /* sync         */
                    717:        (void *)eopnotsupp,             /* vget         */
                    718:        puffs_vfsop_fhtovp,             /* fhtovp       */
                    719:        puffs_vfsop_vptofh,             /* vptofh       */
                    720:        puffs_vfsop_init,               /* init         */
                    721:        NULL,                           /* reinit       */
                    722:        puffs_vfsop_done,               /* done         */
                    723:        NULL,                           /* mountroot    */
                    724:        puffs_vfsop_snapshot,           /* snapshot     */
                    725:        vfs_stdextattrctl,              /* extattrctl   */
1.83    ! pooka     726:        (void *)eopnotsupp,             /* suspendctl   */
1.78      dholland  727:        genfs_renamelock_enter,
                    728:        genfs_renamelock_exit,
1.79      ad        729:        (void *)eopnotsupp,
1.73      pooka     730:        puffs_vnodeopv_descs,           /* vnodeops     */
                    731:        0,                              /* refcount     */
1.1       pooka     732:        { NULL, NULL }
                    733: };
1.80      rumble    734:
                    735: static int
                    736: puffs_modcmd(modcmd_t cmd, void *arg)
                    737: {
                    738:
                    739:        switch (cmd) {
                    740:        case MODULE_CMD_INIT:
                    741:                return vfs_attach(&puffs_vfsops);
                    742:        case MODULE_CMD_FINI:
                    743:                return vfs_detach(&puffs_vfsops);
                    744:        default:
                    745:                return ENOTTY;
                    746:        }
                    747: }

CVSweb <webmaster@jp.NetBSD.org>