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

Annotation of src/sys/fs/puffs/puffs_subr.c, Revision 1.13.2.4

1.13.2.4! yamt        1: /*     $NetBSD: puffs_subr.c,v 1.13.2.3 2007/09/03 14:40:30 yamt Exp $ */
1.13.2.2  yamt        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.13.2.4! yamt       33: __KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.13.2.3 2007/09/03 14:40:30 yamt Exp $");
1.13.2.2  yamt       34:
                     35: #include <sys/param.h>
                     36: #include <sys/conf.h>
1.13.2.3  yamt       37: #include <sys/hash.h>
1.13.2.4! yamt       38: #include <sys/kauth.h>
1.13.2.2  yamt       39: #include <sys/malloc.h>
                     40: #include <sys/mount.h>
1.13.2.4! yamt       41: #include <sys/namei.h>
        !            42: #include <sys/poll.h>
1.13.2.2  yamt       43: #include <sys/socketvar.h>
                     44: #include <sys/vnode.h>
1.13.2.4! yamt       45: #include <sys/proc.h>
1.13.2.2  yamt       46:
                     47: #include <fs/puffs/puffs_msgif.h>
                     48: #include <fs/puffs/puffs_sys.h>
                     49:
                     50: #include <miscfs/genfs/genfs_node.h>
                     51: #include <miscfs/specfs/specdev.h>
                     52:
1.13.2.4! yamt       53: struct pool puffs_pnpool;
1.13.2.2  yamt       54:
1.13.2.3  yamt       55: #ifdef PUFFSDEBUG
1.13.2.2  yamt       56: int puffsdebug;
                     57: #endif
                     58:
1.13.2.3  yamt       59: static __inline struct puffs_node_hashlist
                     60:        *puffs_cookie2hashlist(struct puffs_mount *, void *);
                     61: static struct puffs_node *puffs_cookie2pnode(struct puffs_mount *, void *);
1.13.2.2  yamt       62:
                     63: static void puffs_gop_size(struct vnode *, off_t, off_t *, int);
                     64: static void puffs_gop_markupdate(struct vnode *, int);
                     65:
                     66: static const struct genfs_ops puffs_genfsops = {
                     67:        .gop_size = puffs_gop_size,
                     68:        .gop_write = genfs_gop_write,
                     69:        .gop_markupdate = puffs_gop_markupdate,
                     70: #if 0
                     71:        .gop_alloc, should ask userspace
                     72: #endif
                     73: };
                     74:
                     75: /*
                     76:  * Grab a vnode, intialize all the puffs-dependant stuff.
                     77:  */
                     78: int
                     79: puffs_getvnode(struct mount *mp, void *cookie, enum vtype type,
                     80:        voff_t vsize, dev_t rdev, struct vnode **vpp)
                     81: {
                     82:        struct puffs_mount *pmp;
                     83:        struct vnode *vp, *nvp;
                     84:        struct puffs_node *pnode;
1.13.2.3  yamt       85:        struct puffs_node_hashlist *plist;
1.13.2.2  yamt       86:        int error;
                     87:
1.13.2.4! yamt       88:        if (type <= VNON || type >= VBAD)
        !            89:                return EINVAL;
        !            90:
1.13.2.2  yamt       91:        pmp = MPTOPUFFSMP(mp);
                     92:
                     93:        /*
                     94:         * XXX: there is a deadlock condition between vfs_busy() and
                     95:         * vnode locks.  For an unmounting file system the mountpoint
                     96:         * is frozen, but in unmount(FORCE) vflush() wants to access all
                     97:         * of the vnodes.  If we are here waiting for the mountpoint
                     98:         * lock while holding on to a vnode lock, well, we ain't
                     99:         * just pining for the fjords anymore.  If we release the
                    100:         * vnode lock, we will be in the situation "mount point
                    101:         * is dying" and panic() will ensue in insmntque.  So as a
                    102:         * temporary workaround, get a vnode without putting it on
                    103:         * the mount point list, check if mount point is still alive
                    104:         * and kicking and only then add the vnode to the list.
                    105:         */
                    106:        error = getnewvnode(VT_PUFFS, NULL, puffs_vnodeop_p, &vp);
                    107:        if (error)
                    108:                return error;
                    109:        vp->v_vnlock = NULL;
                    110:        vp->v_type = type;
                    111:
                    112:        /*
                    113:         * Check what mount point isn't going away.  This will work
                    114:         * until we decide to remove biglock or make the kernel
                    115:         * preemptive.  But hopefully the real problem will be fixed
                    116:         * by then.
                    117:         *
                    118:         * XXX: yes, should call vfs_busy(), but thar be rabbits with
                    119:         * vicious streaks a mile wide ...
                    120:         */
                    121:        if (mp->mnt_iflag & IMNT_UNMOUNT) {
                    122:                DPRINTF(("puffs_getvnode: mp %p unmount, unable to create "
                    123:                    "vnode for cookie %p\n", mp, cookie));
                    124:                ungetnewvnode(vp);
                    125:                return ENXIO;
                    126:        }
                    127:
                    128:        /* So it's not dead yet.. good.. inform new vnode of its master */
                    129:        simple_lock(&mntvnode_slock);
1.13.2.3  yamt      130:        TAILQ_INSERT_TAIL(&mp->mnt_vnodelist, vp, v_mntvnodes);
1.13.2.2  yamt      131:        simple_unlock(&mntvnode_slock);
                    132:        vp->v_mount = mp;
                    133:
                    134:        /*
                    135:         * clerical tasks & footwork
                    136:         */
                    137:
1.13.2.4! yamt      138:        /* default size */
        !           139:        uvm_vnp_setsize(vp, 0);
        !           140:
1.13.2.2  yamt      141:        /* dances based on vnode type. almost ufs_vinit(), but not quite */
                    142:        switch (type) {
                    143:        case VCHR:
                    144:        case VBLK:
                    145:                /*
                    146:                 * replace vnode operation vector with the specops vector.
                    147:                 * our user server has very little control over the node
                    148:                 * if it decides its a character or block special file
                    149:                 */
                    150:                vp->v_op = puffs_specop_p;
                    151:
                    152:                /* do the standard checkalias-dance */
                    153:                if ((nvp = checkalias(vp, rdev, mp)) != NULL) {
                    154:                        /*
                    155:                         * found: release & unallocate aliased
                    156:                         * old (well, actually, new) node
                    157:                         */
                    158:                        vp->v_op = spec_vnodeop_p;
                    159:                        vp->v_flag &= ~VLOCKSWORK;
                    160:                        vrele(vp);
                    161:                        vgone(vp); /* cya */
                    162:
                    163:                        /* init "new" vnode */
                    164:                        vp = nvp;
                    165:                        vp->v_vnlock = NULL;
                    166:                        vp->v_mount = mp;
                    167:                }
                    168:                break;
                    169:
                    170:        case VFIFO:
                    171:                vp->v_op = puffs_fifoop_p;
                    172:                break;
                    173:
                    174:        case VREG:
                    175:                uvm_vnp_setsize(vp, vsize);
                    176:                break;
                    177:
                    178:        case VDIR:
                    179:        case VLNK:
                    180:        case VSOCK:
                    181:                break;
                    182:        default:
                    183: #ifdef DIAGNOSTIC
                    184:                panic("puffs_getvnode: invalid vtype %d", type);
                    185: #endif
                    186:                break;
                    187:        }
                    188:
                    189:        pnode = pool_get(&puffs_pnpool, PR_WAITOK);
1.13.2.4! yamt      190:        memset(pnode, 0, sizeof(struct puffs_node));
        !           191:
1.13.2.2  yamt      192:        pnode->pn_cookie = cookie;
1.13.2.4! yamt      193:        pnode->pn_refcount = 1;
        !           194:
        !           195:        mutex_init(&pnode->pn_mtx, MUTEX_DEFAULT, IPL_NONE);
        !           196:        SLIST_INIT(&pnode->pn_sel.sel_klist);
        !           197:
1.13.2.3  yamt      198:        plist = puffs_cookie2hashlist(pmp, cookie);
                    199:        LIST_INSERT_HEAD(plist, pnode, pn_hashent);
1.13.2.2  yamt      200:        vp->v_data = pnode;
                    201:        vp->v_type = type;
                    202:        pnode->pn_vp = vp;
1.13.2.4! yamt      203:        pnode->pn_serversize = vsize;
1.13.2.2  yamt      204:
                    205:        genfs_node_init(vp, &puffs_genfsops);
                    206:        *vpp = vp;
                    207:
                    208:        DPRINTF(("new vnode at %p, pnode %p, cookie %p\n", vp,
                    209:            pnode, pnode->pn_cookie));
                    210:
                    211:        return 0;
                    212: }
                    213:
                    214: /* new node creating for creative vop ops (create, symlink, mkdir, mknod) */
                    215: int
                    216: puffs_newnode(struct mount *mp, struct vnode *dvp, struct vnode **vpp,
                    217:        void *cookie, struct componentname *cnp, enum vtype type, dev_t rdev)
                    218: {
                    219:        struct puffs_mount *pmp = MPTOPUFFSMP(mp);
                    220:        struct vnode *vp;
                    221:        int error;
                    222:
                    223:        /* userspace probably has this as a NULL op */
                    224:        if (cookie == NULL) {
                    225:                error = EOPNOTSUPP;
                    226:                return error;
                    227:        }
                    228:
1.13.2.3  yamt      229:        /*
                    230:         * Check for previous node with the same designation.
                    231:         * Explicitly check the root node cookie, since it might be
                    232:         * reclaimed from the kernel when this check is made.
                    233:         *
                    234:         * XXX: technically this error check should punish the fs,
                    235:         * not the caller.
                    236:         */
1.13.2.4! yamt      237:        mutex_enter(&pmp->pmp_lock);
        !           238:        if (cookie == pmp->pmp_root_cookie
1.13.2.3  yamt      239:            || puffs_cookie2pnode(pmp, cookie) != NULL) {
1.13.2.4! yamt      240:                mutex_exit(&pmp->pmp_lock);
1.13.2.3  yamt      241:                error = EEXIST;
                    242:                return error;
                    243:        }
1.13.2.4! yamt      244:        mutex_exit(&pmp->pmp_lock);
1.13.2.3  yamt      245:
1.13.2.2  yamt      246:        error = puffs_getvnode(dvp->v_mount, cookie, type, 0, rdev, &vp);
                    247:        if (error)
                    248:                return error;
                    249:
                    250:        vp->v_type = type;
                    251:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    252:        *vpp = vp;
                    253:
1.13.2.4! yamt      254:        if ((cnp->cn_flags & MAKEENTRY) && PUFFS_USE_NAMECACHE(pmp))
1.13.2.2  yamt      255:                cache_enter(dvp, vp, cnp);
                    256:
                    257:        return 0;
                    258: }
                    259:
1.13.2.4! yamt      260: /*
        !           261:  * Release pnode structure which dealing with references to the
        !           262:  * puffs_node instead of the vnode.  Can't use vref()/vrele() on
        !           263:  * the vnode there, since that causes the lovely VOP_INACTIVE(),
        !           264:  * which in turn causes the lovely deadlock when called by the one
        !           265:  * who is supposed to handle it.
        !           266:  */
        !           267: void
        !           268: puffs_releasenode(struct puffs_node *pn)
        !           269: {
        !           270:
        !           271:        mutex_enter(&pn->pn_mtx);
        !           272:        if (--pn->pn_refcount == 0) {
        !           273:                mutex_exit(&pn->pn_mtx);
        !           274:                mutex_destroy(&pn->pn_mtx);
        !           275:                pool_put(&puffs_pnpool, pn);
        !           276:        } else {
        !           277:                mutex_exit(&pn->pn_mtx);
        !           278:        }
        !           279: }
        !           280:
        !           281: /*
        !           282:  * Add reference to node.
        !           283:  *  mutex held on entry and return
        !           284:  */
        !           285: void
        !           286: puffs_referencenode(struct puffs_node *pn)
        !           287: {
        !           288:
        !           289:        KASSERT(mutex_owned(&pn->pn_mtx));
        !           290:        pn->pn_refcount++;
        !           291: }
        !           292:
1.13.2.2  yamt      293: void
                    294: puffs_putvnode(struct vnode *vp)
                    295: {
                    296:        struct puffs_mount *pmp;
                    297:        struct puffs_node *pnode;
                    298:
                    299:        pmp = VPTOPUFFSMP(vp);
                    300:        pnode = VPTOPP(vp);
                    301:
                    302: #ifdef DIAGNOSTIC
                    303:        if (vp->v_tag != VT_PUFFS)
                    304:                panic("puffs_putvnode: %p not a puffs vnode", vp);
                    305: #endif
                    306:
1.13.2.3  yamt      307:        LIST_REMOVE(pnode, pn_hashent);
                    308:        genfs_node_destroy(vp);
1.13.2.4! yamt      309:        puffs_releasenode(pnode);
1.13.2.2  yamt      310:        vp->v_data = NULL;
                    311:
                    312:        return;
                    313: }
                    314:
1.13.2.3  yamt      315: static __inline struct puffs_node_hashlist *
                    316: puffs_cookie2hashlist(struct puffs_mount *pmp, void *cookie)
                    317: {
                    318:        uint32_t hash;
                    319:
                    320:        hash = hash32_buf(&cookie, sizeof(void *), HASH32_BUF_INIT);
                    321:        return &pmp->pmp_pnodehash[hash % pmp->pmp_npnodehash];
                    322: }
                    323:
                    324: /*
                    325:  * Translate cookie to puffs_node.  Caller must hold mountpoint
                    326:  * lock and it will be held upon return.
                    327:  */
                    328: static struct puffs_node *
                    329: puffs_cookie2pnode(struct puffs_mount *pmp, void *cookie)
                    330: {
                    331:        struct puffs_node_hashlist *plist;
                    332:        struct puffs_node *pnode;
                    333:
                    334:        plist = puffs_cookie2hashlist(pmp, cookie);
                    335:        LIST_FOREACH(pnode, plist, pn_hashent) {
                    336:                if (pnode->pn_cookie == cookie)
                    337:                        break;
                    338:        }
                    339:
                    340:        return pnode;
                    341: }
                    342:
1.13.2.2  yamt      343: /*
1.13.2.4! yamt      344:  * Make sure root vnode exists and reference it.  Does NOT lock.
        !           345:  */
        !           346: static int
        !           347: puffs_makeroot(struct puffs_mount *pmp)
        !           348: {
        !           349:        struct vnode *vp;
        !           350:        int rv;
        !           351:
        !           352:        /*
        !           353:         * pmp_lock must be held if vref()'ing or vrele()'ing the
        !           354:         * root vnode.  the latter is controlled by puffs_inactive().
        !           355:         *
        !           356:         * pmp_root is set here and cleared in puffs_reclaim().
        !           357:         */
        !           358:  retry:
        !           359:        mutex_enter(&pmp->pmp_lock);
        !           360:        vp = pmp->pmp_root;
        !           361:        if (vp) {
        !           362:                simple_lock(&vp->v_interlock);
        !           363:                mutex_exit(&pmp->pmp_lock);
        !           364:                if (vget(vp, LK_INTERLOCK) == 0)
        !           365:                        return 0;
        !           366:        } else
        !           367:                mutex_exit(&pmp->pmp_lock);
        !           368:
        !           369:        /*
        !           370:         * So, didn't have the magic root vnode available.
        !           371:         * No matter, grab another an stuff it with the cookie.
        !           372:         */
        !           373:        if ((rv = puffs_getvnode(pmp->pmp_mp, pmp->pmp_root_cookie,
        !           374:            pmp->pmp_root_vtype, pmp->pmp_root_vsize, pmp->pmp_root_rdev, &vp)))
        !           375:                return rv;
        !           376:
        !           377:        /*
        !           378:         * Someone magically managed to race us into puffs_getvnode?
        !           379:         * Put our previous new vnode back and retry.
        !           380:         */
        !           381:        mutex_enter(&pmp->pmp_lock);
        !           382:        if (pmp->pmp_root) {
        !           383:                mutex_exit(&pmp->pmp_lock);
        !           384:                puffs_putvnode(vp);
        !           385:                goto retry;
        !           386:        }
        !           387:
        !           388:        /* store cache */
        !           389:        vp->v_flag = VROOT;
        !           390:        pmp->pmp_root = vp;
        !           391:        mutex_exit(&pmp->pmp_lock);
        !           392:
        !           393:        return 0;
        !           394: }
        !           395:
        !           396: /*
1.13.2.2  yamt      397:  * Locate the in-kernel vnode based on the cookie received given
1.13.2.3  yamt      398:  * from userspace.  Returns a vnode, if found, NULL otherwise.
                    399:  * The parameter "lock" control whether to lock the possible or
                    400:  * not.  Locking always might cause us to lock against ourselves
                    401:  * in situations where we want the vnode but don't care for the
                    402:  * vnode lock, e.g. file server issued putpages.
1.13.2.2  yamt      403:  */
1.13.2.4! yamt      404: int
        !           405: puffs_pnode2vnode(struct puffs_mount *pmp, void *cookie, int lock,
        !           406:        struct vnode **vpp)
1.13.2.2  yamt      407: {
                    408:        struct puffs_node *pnode;
                    409:        struct vnode *vp;
1.13.2.4! yamt      410:        int vgetflags, rv;
1.13.2.3  yamt      411:
                    412:        /*
1.13.2.4! yamt      413:         * Handle root in a special manner, since we want to make sure
        !           414:         * pmp_root is properly set.
1.13.2.3  yamt      415:         */
1.13.2.4! yamt      416:        if (cookie == pmp->pmp_root_cookie) {
        !           417:                if ((rv = puffs_makeroot(pmp)))
        !           418:                        return rv;
        !           419:                if (lock)
        !           420:                        vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY);
1.13.2.3  yamt      421:
1.13.2.4! yamt      422:                *vpp = pmp->pmp_root;
        !           423:                return 0;
1.13.2.3  yamt      424:        }
                    425:
1.13.2.4! yamt      426:        mutex_enter(&pmp->pmp_lock);
1.13.2.3  yamt      427:        pnode = puffs_cookie2pnode(pmp, cookie);
                    428:
                    429:        if (pnode == NULL) {
1.13.2.4! yamt      430:                mutex_exit(&pmp->pmp_lock);
        !           431:                return ENOENT;
1.13.2.2  yamt      432:        }
1.13.2.3  yamt      433:
1.13.2.4! yamt      434:        vp = pnode->pn_vp;
1.13.2.3  yamt      435:        simple_lock(&vp->v_interlock);
1.13.2.4! yamt      436:        mutex_exit(&pmp->pmp_lock);
1.13.2.3  yamt      437:
1.13.2.4! yamt      438:        vgetflags = LK_INTERLOCK;
        !           439:        if (lock)
        !           440:                vgetflags |= LK_EXCLUSIVE | LK_RETRY;
        !           441:        if ((rv = vget(vp, vgetflags)))
        !           442:                return rv;
1.13.2.2  yamt      443:
1.13.2.4! yamt      444:        *vpp = vp;
        !           445:        return 0;
1.13.2.2  yamt      446: }
                    447:
                    448: void
1.13.2.4! yamt      449: puffs_makecn(struct puffs_kcn *pkcn, struct puffs_kcred *pkcr,
        !           450:        struct puffs_kcid *pkcid, const struct componentname *cn, int full)
1.13.2.2  yamt      451: {
                    452:
                    453:        pkcn->pkcn_nameiop = cn->cn_nameiop;
                    454:        pkcn->pkcn_flags = cn->cn_flags;
1.13.2.4! yamt      455:        puffs_cidcvt(pkcid, cn->cn_lwp);
1.13.2.2  yamt      456:
1.13.2.4! yamt      457:        if (full) {
        !           458:                (void)strcpy(pkcn->pkcn_name, cn->cn_nameptr);
        !           459:        } else {
        !           460:                (void)memcpy(pkcn->pkcn_name, cn->cn_nameptr, cn->cn_namelen);
        !           461:                pkcn->pkcn_name[cn->cn_namelen] = '\0';
        !           462:        }
1.13.2.2  yamt      463:        pkcn->pkcn_namelen = cn->cn_namelen;
1.13.2.4! yamt      464:        pkcn->pkcn_consume = 0;
        !           465:
        !           466:        puffs_credcvt(pkcr, cn->cn_cred);
1.13.2.2  yamt      467: }
                    468:
                    469: /*
1.13.2.4! yamt      470:  * Convert given credentials to struct puffs_kcred for userspace.
1.13.2.2  yamt      471:  */
                    472: void
1.13.2.4! yamt      473: puffs_credcvt(struct puffs_kcred *pkcr, const kauth_cred_t cred)
1.13.2.2  yamt      474: {
                    475:
1.13.2.4! yamt      476:        memset(pkcr, 0, sizeof(struct puffs_kcred));
1.13.2.2  yamt      477:
                    478:        if (cred == NOCRED || cred == FSCRED) {
1.13.2.4! yamt      479:                pkcr->pkcr_type = PUFFCRED_TYPE_INTERNAL;
1.13.2.2  yamt      480:                if (cred == NOCRED)
1.13.2.4! yamt      481:                        pkcr->pkcr_internal = PUFFCRED_CRED_NOCRED;
1.13.2.2  yamt      482:                if (cred == FSCRED)
1.13.2.4! yamt      483:                        pkcr->pkcr_internal = PUFFCRED_CRED_FSCRED;
1.13.2.2  yamt      484:        } else {
1.13.2.4! yamt      485:                pkcr->pkcr_type = PUFFCRED_TYPE_UUC;
        !           486:                kauth_cred_to_uucred(&pkcr->pkcr_uuc, cred);
1.13.2.2  yamt      487:        }
                    488: }
                    489:
1.13.2.4! yamt      490: void
        !           491: puffs_cidcvt(struct puffs_kcid *pkcid, const struct lwp *l)
1.13.2.2  yamt      492: {
                    493:
1.13.2.4! yamt      494:        if (l) {
        !           495:                pkcid->pkcid_type = PUFFCID_TYPE_REAL;
        !           496:                pkcid->pkcid_pid = l->l_proc->p_pid;
        !           497:                pkcid->pkcid_lwpid = l->l_lid;
        !           498:        } else {
        !           499:                pkcid->pkcid_type = PUFFCID_TYPE_FAKE;
        !           500:                pkcid->pkcid_pid = 0;
        !           501:                pkcid->pkcid_lwpid = 0;
        !           502:        }
1.13.2.2  yamt      503: }
                    504:
                    505: static void
                    506: puffs_gop_size(struct vnode *vp, off_t size, off_t *eobp,
                    507:        int flags)
                    508: {
                    509:
                    510:        *eobp = size;
                    511: }
                    512:
                    513: static void
                    514: puffs_gop_markupdate(struct vnode *vp, int flags)
                    515: {
                    516:        int uflags = 0;
                    517:
                    518:        if (flags & GOP_UPDATE_ACCESSED)
                    519:                uflags |= PUFFS_UPDATEATIME;
                    520:        if (flags & GOP_UPDATE_MODIFIED)
                    521:                uflags |= PUFFS_UPDATEMTIME;
                    522:
                    523:        puffs_updatenode(vp, uflags);
                    524: }
                    525:
                    526: void
                    527: puffs_updatenode(struct vnode *vp, int flags)
                    528: {
1.13.2.4! yamt      529:        struct puffs_node *pn;
1.13.2.2  yamt      530:        struct timespec ts;
                    531:
                    532:        if (flags == 0)
                    533:                return;
                    534:
1.13.2.4! yamt      535:        pn = VPTOPP(vp);
1.13.2.2  yamt      536:        nanotime(&ts);
                    537:
1.13.2.4! yamt      538:        if (flags & PUFFS_UPDATEATIME) {
        !           539:                pn->pn_mc_atime = ts;
        !           540:                pn->pn_stat |= PNODE_METACACHE_ATIME;
        !           541:        }
        !           542:        if (flags & PUFFS_UPDATECTIME) {
        !           543:                pn->pn_mc_ctime = ts;
        !           544:                pn->pn_stat |= PNODE_METACACHE_CTIME;
        !           545:        }
        !           546:        if (flags & PUFFS_UPDATEMTIME) {
        !           547:                pn->pn_mc_mtime = ts;
        !           548:                pn->pn_stat |= PNODE_METACACHE_MTIME;
        !           549:        }
        !           550:        if (flags & PUFFS_UPDATESIZE) {
        !           551:                pn->pn_mc_size = vp->v_size;
        !           552:                pn->pn_stat |= PNODE_METACACHE_SIZE;
        !           553:        }
1.13.2.2  yamt      554: }
                    555:
                    556: void
                    557: puffs_updatevpsize(struct vnode *vp)
                    558: {
                    559:        struct vattr va;
                    560:
                    561:        if (VOP_GETATTR(vp, &va, FSCRED, NULL))
                    562:                return;
                    563:
                    564:        if (va.va_size != VNOVAL)
                    565:                vp->v_size = va.va_size;
                    566: }
                    567:
                    568: void
1.13.2.4! yamt      569: puffs_parkdone_asyncbioread(struct puffs_req *preq, void *arg)
1.13.2.2  yamt      570: {
1.13.2.4! yamt      571:        struct puffs_vnreq_read *read_argp = (void *)preq;
        !           572:        struct buf *bp = arg;
        !           573:        size_t moved;
        !           574:
        !           575:        bp->b_error = preq->preq_rv;
        !           576:        if (bp->b_error == 0) {
        !           577:                moved = bp->b_bcount - read_argp->pvnr_resid;
        !           578:                bp->b_resid = read_argp->pvnr_resid;
1.13.2.2  yamt      579:
1.13.2.4! yamt      580:                memcpy(bp->b_data, read_argp->pvnr_data, moved);
1.13.2.2  yamt      581:        }
                    582:
1.13.2.4! yamt      583:        biodone(bp);
        !           584:        free(preq, M_PUFFS);
        !           585: }
        !           586:
        !           587: /* XXX: userspace can leak kernel resources */
        !           588: void
        !           589: puffs_parkdone_poll(struct puffs_req *preq, void *arg)
        !           590: {
        !           591:        struct puffs_vnreq_poll *poll_argp = (void *)preq;
        !           592:        struct puffs_node *pn = arg;
        !           593:        int revents;
        !           594:
        !           595:        if (preq->preq_rv == 0)
        !           596:                revents = poll_argp->pvnr_events;
        !           597:        else
        !           598:                revents = POLLERR;
        !           599:
        !           600:        mutex_enter(&pn->pn_mtx);
        !           601:        pn->pn_revents |= revents;
        !           602:        mutex_exit(&pn->pn_mtx);
        !           603:
        !           604:        selnotify(&pn->pn_sel, 0);
        !           605:        free(preq, M_PUFFS);
        !           606:
        !           607:        puffs_releasenode(pn);
        !           608: }
        !           609:
        !           610: void
        !           611: puffs_mp_reference(struct puffs_mount *pmp)
        !           612: {
        !           613:
        !           614:        KASSERT(mutex_owned(&pmp->pmp_lock));
        !           615:        pmp->pmp_refcount++;
        !           616: }
        !           617:
        !           618: void
        !           619: puffs_mp_release(struct puffs_mount *pmp)
        !           620: {
        !           621:
        !           622:        KASSERT(mutex_owned(&pmp->pmp_lock));
        !           623:        if (--pmp->pmp_refcount == 0)
        !           624:                cv_broadcast(&pmp->pmp_refcount_cv);
1.13.2.2  yamt      625: }

CVSweb <webmaster@jp.NetBSD.org>