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

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

CVSweb <webmaster@jp.NetBSD.org>