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

1.10    ! pooka       1: /*     $NetBSD: puffs_subr.c,v 1.9 2006/11/18 08:18:24 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:  * 3. The name of the company nor the name of the author may be used to
                     19:  *    endorse or promote products derived from this software without specific
                     20:  *    prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     23:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     24:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     25:  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     28:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  */
                     34:
                     35: #include <sys/cdefs.h>
1.10    ! pooka      36: __KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.9 2006/11/18 08:18:24 pooka Exp $");
1.1       pooka      37:
                     38: #include <sys/param.h>
                     39: #include <sys/conf.h>
                     40: #include <sys/malloc.h>
                     41: #include <sys/mount.h>
                     42: #include <sys/socketvar.h>
                     43: #include <sys/vnode.h>
                     44: #include <sys/kauth.h>
                     45: #include <sys/namei.h>
                     46:
                     47: #include <fs/puffs/puffs_msgif.h>
                     48: #include <fs/puffs/puffs_sys.h>
                     49:
1.7       pooka      50: #include <miscfs/genfs/genfs_node.h>
1.4       pooka      51: #include <miscfs/specfs/specdev.h>
                     52:
1.1       pooka      53: POOL_INIT(puffs_pnpool, sizeof(struct puffs_node), 0, 0, 0, "puffspnpl",
                     54:     &pool_allocator_nointr);
                     55:
1.10    ! pooka      56: #ifdef DEBUG
        !            57: int puffsdebug;
        !            58: #endif
        !            59:
1.7       pooka      60:
                     61: static void puffs_gop_size(struct vnode *, off_t, off_t *, int);
                     62: static void puffs_gop_markupdate(struct vnode *, int);
                     63:
                     64: static const struct genfs_ops puffs_genfsops = {
                     65:        .gop_size = puffs_gop_size,
                     66:        .gop_write = genfs_gop_write,
                     67:        .gop_markupdate = puffs_gop_markupdate,
                     68: #if 0
                     69:        .gop_alloc, should ask userspace
                     70: #endif
                     71: };
                     72:
1.1       pooka      73: /*
                     74:  * Grab a vnode, intialize all the puffs-dependant stuff.
                     75:  */
                     76: int
1.4       pooka      77: puffs_getvnode(struct mount *mp, void *cookie, enum vtype type,
1.7       pooka      78:        voff_t vsize, dev_t rdev, struct vnode **vpp)
1.1       pooka      79: {
                     80:        struct puffs_mount *pmp;
1.4       pooka      81:        struct vnode *vp, *nvp;
1.1       pooka      82:        struct puffs_node *pnode;
                     83:        int error;
                     84:
                     85:        pmp = MPTOPUFFSMP(mp);
                     86:
1.2       pooka      87:        /*
                     88:         * XXX: there is a deadlock condition between vfs_busy() and
                     89:         * vnode locks.  For an unmounting file system the mountpoint
                     90:         * is frozen, but in unmount(FORCE) vflush() wants to access all
                     91:         * of the vnodes.  If we are here waiting for the mountpoint
                     92:         * lock while holding on to a vnode lock, well, we ain't
                     93:         * just pining for the fjords anymore.  If we release the
                     94:         * vnode lock, we will be in the situation "mount point
                     95:         * is dying" and panic() will ensue in insmntque.  So as a
                     96:         * temporary workaround, get a vnode without putting it on
                     97:         * the mount point list, check if mount point is still alive
                     98:         * and kicking and only then add the vnode to the list.
                     99:         */
                    100:        error = getnewvnode(VT_PUFFS, NULL, puffs_vnodeop_p, &vp);
                    101:        if (error)
1.1       pooka     102:                return error;
1.2       pooka     103:        vp->v_vnlock = NULL;
1.4       pooka     104:        vp->v_type = type;
1.2       pooka     105:
                    106:        /*
                    107:         * Check what mount point isn't going away.  This will work
                    108:         * until we decide to remove biglock or make the kernel
                    109:         * preemptive.  But hopefully the real problem will be fixed
                    110:         * by then.
                    111:         *
                    112:         * XXX: yes, should call vfs_busy(), but thar be rabbits with
                    113:         * vicious streaks a mile wide ...
                    114:         */
                    115:        if (mp->mnt_iflag & IMNT_UNMOUNT) {
                    116:                DPRINTF(("puffs_getvnode: mp %p unmount, unable to create "
                    117:                    "vnode for cookie %p\n", mp, cookie));
                    118:                ungetnewvnode(vp);
                    119:                return ENXIO;
1.1       pooka     120:        }
                    121:
1.2       pooka     122:        /* So it's not dead yet.. good.. inform new vnode of its master */
                    123:        simple_lock(&mntvnode_slock);
                    124:        if (TAILQ_EMPTY(&mp->mnt_vnodelist))
                    125:                TAILQ_INSERT_HEAD(&mp->mnt_vnodelist, vp, v_mntvnodes);
                    126:        else
                    127:                TAILQ_INSERT_TAIL(&mp->mnt_vnodelist, vp, v_mntvnodes);
                    128:        simple_unlock(&mntvnode_slock);
                    129:        vp->v_mount = mp;
                    130:
1.4       pooka     131:        /*
                    132:         * clerical tasks & footwork
                    133:         */
                    134:
                    135:        /* dances based on vnode type. almost ufs_vinit(), but not quite */
                    136:        switch (type) {
                    137:        case VCHR:
                    138:        case VBLK:
                    139:                /*
                    140:                 * replace vnode operation vector with the specops vector.
                    141:                 * our user server has very little control over the node
                    142:                 * if it decides its a character or block special file
                    143:                 */
                    144:                vp->v_op = puffs_specop_p;
                    145:
                    146:                /* do the standard checkalias-dance */
                    147:                if ((nvp = checkalias(vp, rdev, mp)) != NULL) {
                    148:                        /*
1.6       pooka     149:                         * found: release & unallocate aliased
1.4       pooka     150:                         * old (well, actually, new) node
                    151:                         */
                    152:                        vp->v_op = spec_vnodeop_p;
                    153:                        vp->v_flag &= ~VLOCKSWORK;
                    154:                        vrele(vp);
                    155:                        vgone(vp); /* cya */
                    156:
                    157:                        /* init "new" vnode */
                    158:                        vp = nvp;
                    159:                        vp->v_vnlock = NULL;
                    160:                        vp->v_mount = mp;
                    161:                }
                    162:                break;
1.7       pooka     163:
1.5       pooka     164:        case VFIFO:
                    165:                vp->v_op = puffs_fifoop_p;
                    166:                break;
1.7       pooka     167:
                    168:        case VREG:
                    169:                uvm_vnp_setsize(vp, vsize);
                    170:                break;
                    171:
1.5       pooka     172:        case VDIR:
                    173:        case VLNK:
                    174:        case VSOCK:
                    175:                break;
1.4       pooka     176:        default:
1.5       pooka     177: #ifdef DIAGNOSTIC
                    178:                panic("puffs_getvnode: invalid vtype %d", type);
                    179: #endif
1.4       pooka     180:                break;
                    181:        }
                    182:
1.2       pooka     183:        pnode = pool_get(&puffs_pnpool, PR_WAITOK);
1.1       pooka     184:        pnode->pn_cookie = cookie;
                    185:        pnode->pn_stat = 0;
                    186:        LIST_INSERT_HEAD(&pmp->pmp_pnodelist, pnode, pn_entries);
                    187:        vp->v_data = pnode;
1.4       pooka     188:        vp->v_type = type;
1.1       pooka     189:        pnode->pn_vp = vp;
                    190:
1.7       pooka     191:        genfs_node_init(vp, &puffs_genfsops);
1.1       pooka     192:        *vpp = vp;
                    193:
                    194:        DPRINTF(("new vnode at %p, pnode %p, cookie %p\n", vp,
                    195:            pnode, pnode->pn_cookie));
                    196:
                    197:        return 0;
                    198: }
                    199:
                    200: /* new node creating for creative vop ops (create, symlink, mkdir, mknod) */
                    201: int
                    202: puffs_newnode(struct mount *mp, struct vnode *dvp, struct vnode **vpp,
1.4       pooka     203:        void *cookie, struct componentname *cnp, enum vtype type, dev_t rdev)
1.1       pooka     204: {
                    205:        struct vnode *vp;
                    206:        int error;
                    207:
                    208:        /* userspace probably has this as a NULL op */
                    209:        if (cookie == NULL) {
                    210:                error = EOPNOTSUPP;
1.3       pooka     211:                return error;
1.1       pooka     212:        }
                    213:
1.7       pooka     214:        error = puffs_getvnode(dvp->v_mount, cookie, type, 0, rdev, &vp);
1.1       pooka     215:        if (error)
1.3       pooka     216:                return error;
1.1       pooka     217:
                    218:        vp->v_type = type;
                    219:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    220:        *vpp = vp;
                    221:
1.3       pooka     222:        return 0;
1.1       pooka     223: }
                    224:
                    225: void
                    226: puffs_putvnode(struct vnode *vp)
                    227: {
                    228:        struct puffs_mount *pmp;
                    229:        struct puffs_node *pnode;
                    230:
                    231:        pmp = VPTOPUFFSMP(vp);
                    232:        pnode = VPTOPP(vp);
                    233:
                    234: #ifdef DIAGNOSTIC
                    235:        if (vp->v_tag != VT_PUFFS)
                    236:                panic("puffs_putvnode: %p not a puffs vnode", vp);
                    237: #endif
                    238:
                    239:        LIST_REMOVE(pnode, pn_entries);
                    240:        pool_put(&puffs_pnpool, vp->v_data);
                    241:        vp->v_data = NULL;
                    242:
                    243:        return;
                    244: }
                    245:
                    246: /*
                    247:  * Locate the in-kernel vnode based on the cookie received given
                    248:  * from userspace.  Returns a locked & referenced vnode, if found,
                    249:  * NULL otherwise.
                    250:  *
                    251:  * XXX: lists, although lookup cache mostly shields us from this
                    252:  */
                    253: struct vnode *
                    254: puffs_pnode2vnode(struct puffs_mount *pmp, void *cookie)
                    255: {
                    256:        struct puffs_node *pnode;
                    257:        struct vnode *vp;
                    258:
                    259:        simple_lock(&pmp->pmp_lock);
                    260:        LIST_FOREACH(pnode, &pmp->pmp_pnodelist, pn_entries) {
                    261:                if (pnode->pn_cookie == cookie)
                    262:                        break;
                    263:        }
                    264:        simple_unlock(&pmp->pmp_lock);
                    265:        if (!pnode)
                    266:                return NULL;
                    267:        vp = pnode->pn_vp;
                    268:
                    269:        if (pnode->pn_stat & PNODE_INACTIVE) {
                    270:                if (vget(vp, LK_EXCLUSIVE | LK_RETRY))
                    271:                        return NULL;
                    272:        } else {
                    273:                vref(vp);
                    274:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    275:        }
                    276:        return vp;
                    277: }
                    278:
                    279: void
                    280: puffs_makecn(struct puffs_cn *pcn, const struct componentname *cn)
                    281: {
                    282:
                    283:        pcn->pcn_nameiop = cn->cn_nameiop;
                    284:        pcn->pcn_flags = cn->cn_flags;
                    285:        pcn->pcn_pid = cn->cn_lwp->l_proc->p_pid;
                    286:        puffs_credcvt(&pcn->pcn_cred, cn->cn_cred);
                    287:
                    288:        (void)memcpy(&pcn->pcn_name, cn->cn_nameptr, cn->cn_namelen);
                    289:        pcn->pcn_name[cn->cn_namelen] = '\0';
                    290:        pcn->pcn_namelen = cn->cn_namelen;
                    291: }
                    292:
                    293: /*
                    294:  * Convert given credentials to struct puffs_cred for userspace.
                    295:  */
                    296: void
                    297: puffs_credcvt(struct puffs_cred *pcr, const kauth_cred_t cred)
                    298: {
                    299:
                    300:        memset(pcr, 0, sizeof(struct puffs_cred));
                    301:
                    302:        if (cred == NOCRED || cred == FSCRED) {
                    303:                pcr->pcr_type = PUFFCRED_TYPE_INTERNAL;
                    304:                if (cred == NOCRED)
                    305:                        pcr->pcr_internal = PUFFCRED_CRED_NOCRED;
                    306:                if (cred == FSCRED)
                    307:                        pcr->pcr_internal = PUFFCRED_CRED_FSCRED;
                    308:        } else {
                    309:                pcr->pcr_type = PUFFCRED_TYPE_UUC;
                    310:                kauth_cred_to_uucred(&pcr->pcr_uuc, cred);
                    311:        }
                    312: }
                    313:
                    314: /*
                    315:  * Return pid.  In case the operation is coming from within the
                    316:  * kernel without any process context, borrow the swapper's pid.
                    317:  */
                    318: pid_t
                    319: puffs_lwp2pid(struct lwp *l)
                    320: {
                    321:
                    322:        return l ? l->l_proc->p_pid : 0;
                    323: }
1.7       pooka     324:
                    325:
                    326: static void
1.8       christos  327: puffs_gop_size(struct vnode *vp, off_t size, off_t *eobp,
                    328:        int flags)
1.7       pooka     329: {
                    330:
                    331:        *eobp = size;
                    332: }
                    333:
                    334: static void
                    335: puffs_gop_markupdate(struct vnode *vp, int flags)
                    336: {
                    337:        int uflags = 0;
                    338:
                    339:        if (flags & GOP_UPDATE_ACCESSED)
                    340:                uflags |= PUFFS_UPDATEATIME;
                    341:        if (flags & GOP_UPDATE_MODIFIED)
                    342:                uflags |= PUFFS_UPDATEMTIME;
                    343:
                    344:        puffs_updatenode(vp, uflags);
                    345: }
                    346:
                    347: void
                    348: puffs_updatenode(struct vnode *vp, int flags)
                    349: {
                    350:        struct timespec ts;
                    351:        struct puffs_vnreq_setattr *setattr_arg;
                    352:
                    353:        if (flags == 0)
                    354:                return;
                    355:
                    356:        setattr_arg = malloc(sizeof(struct puffs_vnreq_setattr), M_PUFFS,
                    357:            M_NOWAIT | M_ZERO);
                    358:        if (setattr_arg == NULL)
                    359:                return; /* 2bad */
                    360:
                    361:        nanotime(&ts);
                    362:
                    363:        VATTR_NULL(&setattr_arg->pvnr_va);
                    364:        if (flags & PUFFS_UPDATEATIME)
                    365:                setattr_arg->pvnr_va.va_atime = ts;
                    366:        if (flags & PUFFS_UPDATECTIME)
                    367:                setattr_arg->pvnr_va.va_ctime = ts;
                    368:        if (flags & PUFFS_UPDATEMTIME)
                    369:                setattr_arg->pvnr_va.va_mtime = ts;
                    370:        if (flags & PUFFS_UPDATESIZE)
                    371:                setattr_arg->pvnr_va.va_size = vp->v_size;
                    372:
                    373:        setattr_arg->pvnr_pid = 0;
                    374:        puffs_credcvt(&setattr_arg->pvnr_cred, NOCRED);
                    375:
                    376:        /* setattr_arg ownership shifted to callee */
                    377:        puffs_vntouser_faf(MPTOPUFFSMP(vp->v_mount), PUFFS_VN_SETATTR,
                    378:            setattr_arg, sizeof(struct puffs_vnreq_setattr), VPTOPNC(vp));
                    379: }
1.9       pooka     380:
                    381: void
                    382: puffs_updatevpsize(struct vnode *vp)
                    383: {
                    384:        struct vattr va;
                    385:
                    386:        if (VOP_GETATTR(vp, &va, FSCRED, NULL))
                    387:                return;
                    388:
                    389:        if (va.va_size != VNOVAL)
                    390:                vp->v_size = va.va_size;
                    391: }

CVSweb <webmaster@jp.NetBSD.org>