[BACK]Return to layer_subr.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / miscfs / genfs

Annotation of src/sys/miscfs/genfs/layer_subr.c, Revision 1.31

1.31    ! hannken     1: /*     $NetBSD: layer_subr.c,v 1.30 2010/07/02 03:16:00 rmind Exp $    */
1.1       wrstuden    2:
                      3: /*
                      4:  * Copyright (c) 1999 National Aeronautics & Space Administration
                      5:  * All rights reserved.
                      6:  *
                      7:  * This software was written by William Studenmund of the
1.8       wiz         8:  * Numerical Aerospace Simulation Facility, NASA Ames Research Center.
1.1       wrstuden    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.
1.5       soren      18:  * 3. Neither the name of the National Aeronautics & Space Administration
1.1       wrstuden   19:  *    nor the names of its contributors may be used to endorse or promote
                     20:  *    products derived from this software without specific prior written
                     21:  *    permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE NATIONAL AERONAUTICS & SPACE ADMINISTRATION
                     24:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     25:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     26:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ADMINISTRATION OR CONTRIB-
                     27:  * UTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
                     28:  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     29:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     30:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     31:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     32:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     33:  * POSSIBILITY OF SUCH DAMAGE.
                     34:  */
1.30      rmind      35:
1.1       wrstuden   36: /*
                     37:  * Copyright (c) 1992, 1993
                     38:  *     The Regents of the University of California.  All rights reserved.
                     39:  *
                     40:  * This code is derived from software donated to Berkeley by
                     41:  * Jan-Simon Pendry.
                     42:  *
                     43:  * Redistribution and use in source and binary forms, with or without
                     44:  * modification, are permitted provided that the following conditions
                     45:  * are met:
                     46:  * 1. Redistributions of source code must retain the above copyright
                     47:  *    notice, this list of conditions and the following disclaimer.
                     48:  * 2. Redistributions in binary form must reproduce the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer in the
                     50:  *    documentation and/or other materials provided with the distribution.
1.15      agc        51:  * 3. Neither the name of the University nor the names of its contributors
1.1       wrstuden   52:  *    may be used to endorse or promote products derived from this software
                     53:  *    without specific prior written permission.
                     54:  *
                     55:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     56:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     57:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     58:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     59:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     60:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     61:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     62:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     63:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     64:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     65:  * SUCH DAMAGE.
                     66:  *
                     67:  *     from: Id: lofs_subr.c,v 1.11 1992/05/30 10:05:43 jsp Exp
                     68:  *     @(#)null_subr.c 8.7 (Berkeley) 5/14/95
                     69:  */
1.9       lukem      70:
                     71: #include <sys/cdefs.h>
1.31    ! hannken    72: __KERNEL_RCSID(0, "$NetBSD: layer_subr.c,v 1.30 2010/07/02 03:16:00 rmind Exp $");
1.1       wrstuden   73:
                     74: #include <sys/param.h>
                     75: #include <sys/systm.h>
                     76: #include <sys/proc.h>
                     77: #include <sys/time.h>
                     78: #include <sys/vnode.h>
                     79: #include <sys/mount.h>
                     80: #include <sys/namei.h>
1.23      ad         81: #include <sys/kmem.h>
1.1       wrstuden   82: #include <sys/malloc.h>
1.23      ad         83:
1.1       wrstuden   84: #include <miscfs/specfs/specdev.h>
                     85: #include <miscfs/genfs/layer.h>
                     86: #include <miscfs/genfs/layer_extern.h>
                     87:
1.16      erh        88: #ifdef LAYERFS_DIAGNOSTIC
                     89: int layerfs_debug = 1;
                     90: #endif
                     91:
1.1       wrstuden   92: /*
                     93:  * layer cache:
                     94:  * Each cache entry holds a reference to the lower vnode
                     95:  * along with a pointer to the alias vnode.  When an
                     96:  * entry is added the lower vnode is VREF'd.  When the
                     97:  * alias is removed the lower vnode is vrele'd.
                     98:  */
                     99:
                    100: void
1.27      cegger    101: layerfs_init(void)
1.1       wrstuden  102: {
1.30      rmind     103:        /* Nothing. */
1.6       jdolecek  104: }
1.1       wrstuden  105:
1.6       jdolecek  106: void
1.27      cegger    107: layerfs_done(void)
1.6       jdolecek  108: {
1.30      rmind     109:        /* Nothing. */
1.1       wrstuden  110: }
                    111:
                    112: /*
1.30      rmind     113:  * layer_node_find: find and return alias for lower vnode or NULL.
                    114:  *
                    115:  * => Return alias vnode locked and referenced. if already exists.
                    116:  * => The layermp's hashlock must be held on entry, we will unlock on success.
1.1       wrstuden  117:  */
                    118: struct vnode *
1.26      dsl       119: layer_node_find(struct mount *mp, struct vnode *lowervp)
1.1       wrstuden  120: {
                    121:        struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp);
                    122:        struct layer_node_hashhead *hd;
                    123:        struct layer_node *a;
                    124:        struct vnode *vp;
1.21      chs       125:        int error;
1.1       wrstuden  126:
                    127:        /*
1.30      rmind     128:         * Find hash bucket and search the (two-way) linked list looking
                    129:         * for a layerfs node structure which is referencing the lower vnode.
                    130:         * If found, the increment the layer_node reference count, but NOT
                    131:         * the lower vnode's reference counter.  Return vnode locked.
1.1       wrstuden  132:         */
1.30      rmind     133:        KASSERT(mutex_owned(&lmp->layerm_hashlock));
1.1       wrstuden  134:        hd = LAYER_NHASH(lmp, lowervp);
                    135: loop:
1.21      chs       136:        LIST_FOREACH(a, hd, layer_hash) {
1.30      rmind     137:                if (a->layer_lowervp != lowervp) {
                    138:                        continue;
                    139:                }
                    140:                vp = LAYERTOV(a);
                    141:                if (vp->v_mount != mp) {
                    142:                        continue;
                    143:                }
                    144:                mutex_enter(&vp->v_interlock);
                    145:                /*
                    146:                 * If we find a node being cleaned out, then ignore it and
                    147:                 * continue.  A thread trying to clean out the extant layer
                    148:                 * vnode needs to acquire the shared lock (i.e. the lower
                    149:                 * vnode's lock), which our caller already holds.  To allow
                    150:                 * the cleaning to succeed the current thread must make
                    151:                 * progress.  So, for a brief time more than one vnode in a
                    152:                 * layered file system may refer to a single vnode in the
                    153:                 * lower file system.
                    154:                 */
                    155:                if ((vp->v_iflag & VI_XLOCK) != 0) {
                    156:                        mutex_exit(&vp->v_interlock);
                    157:                        continue;
                    158:                }
                    159:                mutex_exit(&lmp->layerm_hashlock);
                    160:                /*
                    161:                 * We must not let vget() try to lock the layer vp, since
                    162:                 * the lower vp is already locked and locking the layer vp
                    163:                 * will involve locking the lower vp.
                    164:                 */
1.31    ! hannken   165:                error = vget(vp, LK_NOWAIT);
1.30      rmind     166:                if (error) {
                    167:                        kpause("layerfs", false, 1, NULL);
                    168:                        mutex_enter(&lmp->layerm_hashlock);
                    169:                        goto loop;
1.1       wrstuden  170:                }
1.30      rmind     171:                return vp;
1.1       wrstuden  172:        }
                    173:        return NULL;
                    174: }
                    175:
                    176: /*
1.30      rmind     177:  * layer_node_alloc: make a new layerfs vnode.
                    178:  *
                    179:  * => vp is the alias vnode, lowervp is the lower vnode.
                    180:  * => We will hold a reference to lowervp.
1.1       wrstuden  181:  */
                    182: int
1.26      dsl       183: layer_node_alloc(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)
1.1       wrstuden  184: {
                    185:        struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp);
                    186:        struct layer_node_hashhead *hd;
                    187:        struct layer_node *xp;
                    188:        struct vnode *vp, *nvp;
                    189:        int error;
1.17      xtraeme   190:        extern int (**dead_vnodeop_p)(void *);
1.1       wrstuden  191:
1.23      ad        192:        error = getnewvnode(lmp->layerm_tag, mp, lmp->layerm_vnodeop_p, &vp);
1.30      rmind     193:        if (error) {
                    194:                return error;
                    195:        }
1.1       wrstuden  196:        vp->v_type = lowervp->v_type;
1.23      ad        197:        mutex_enter(&vp->v_interlock);
1.22      ad        198:        vp->v_iflag |= VI_LAYER;
1.23      ad        199:        mutex_exit(&vp->v_interlock);
1.1       wrstuden  200:
1.23      ad        201:        xp = kmem_alloc(lmp->layerm_size, KM_SLEEP);
                    202:        if (xp == NULL) {
                    203:                ungetnewvnode(vp);
                    204:                return ENOMEM;
                    205:        }
1.1       wrstuden  206:        if (vp->v_type == VBLK || vp->v_type == VCHR) {
1.25      ad        207:                spec_node_init(vp, lowervp->v_rdev);
1.1       wrstuden  208:        }
                    209:
                    210:        vp->v_data = xp;
1.23      ad        211:        vp->v_vflag = (vp->v_vflag & ~VV_MPSAFE) |
                    212:            (lowervp->v_vflag & VV_MPSAFE);
1.1       wrstuden  213:        xp->layer_vnode = vp;
                    214:        xp->layer_lowervp = lowervp;
                    215:        xp->layer_flags = 0;
1.21      chs       216:
1.1       wrstuden  217:        /*
1.30      rmind     218:         * Before inserting the node into the hash, check if other thread
                    219:         * did not race with us.  If so - return that node, destroy ours.
1.1       wrstuden  220:         */
1.22      ad        221:        mutex_enter(&lmp->layerm_hashlock);
1.1       wrstuden  222:        if ((nvp = layer_node_find(mp, lowervp)) != NULL) {
1.30      rmind     223:                /* Free the structures we have created. */
1.1       wrstuden  224:                if (vp->v_type == VBLK || vp->v_type == VCHR)
1.25      ad        225:                        spec_node_destroy(vp);
1.1       wrstuden  226:
                    227:                vp->v_type = VBAD;              /* node is discarded */
                    228:                vp->v_op = dead_vnodeop_p;      /* so ops will still work */
                    229:                vrele(vp);                      /* get rid of it. */
1.30      rmind     230:                kmem_free(xp, lmp->layerm_size);
                    231:                *vpp = nvp;
                    232:                return 0;
1.1       wrstuden  233:        }
                    234:
                    235:        /*
1.21      chs       236:         * Insert the new node into the hash.
                    237:         * Add a reference to the lower node.
1.1       wrstuden  238:         */
1.28      pooka     239:        vref(lowervp);
1.1       wrstuden  240:        hd = LAYER_NHASH(lmp, lowervp);
                    241:        LIST_INSERT_HEAD(hd, xp, layer_hash);
1.7       chs       242:        uvm_vnp_setsize(vp, 0);
1.22      ad        243:        mutex_exit(&lmp->layerm_hashlock);
1.30      rmind     244:
                    245:        *vpp = vp;
                    246:        return 0;
1.1       wrstuden  247: }
                    248:
                    249: /*
1.30      rmind     250:  * layer_node_create: try to find an existing layerfs vnode refering to it,
                    251:  * otherwise make a new vnode which contains a reference to the lower vnode.
1.1       wrstuden  252:  *
1.30      rmind     253:  * => Caller should lock the lower node.
1.1       wrstuden  254:  */
                    255: int
1.30      rmind     256: layer_node_create(struct mount *mp, struct vnode *lowervp, struct vnode **nvpp)
1.1       wrstuden  257: {
                    258:        struct vnode *aliasvp;
                    259:        struct layer_mount *lmp = MOUNTTOLAYERMOUNT(mp);
                    260:
1.30      rmind     261:        KASSERT(VOP_ISLOCKED(lowervp));
                    262:
1.22      ad        263:        mutex_enter(&lmp->layerm_hashlock);
1.21      chs       264:        aliasvp = layer_node_find(mp, lowervp);
                    265:        if (aliasvp != NULL) {
1.1       wrstuden  266:                /*
1.30      rmind     267:                 * Note: layer_node_find() has taken another reference to
                    268:                 * the alias vnode and moved the lock holding to aliasvp.
1.1       wrstuden  269:                 */
                    270: #ifdef LAYERFS_DIAGNOSTIC
1.16      erh       271:                if (layerfs_debug)
                    272:                        vprint("layer_node_create: exists", aliasvp);
1.1       wrstuden  273: #endif
                    274:        } else {
                    275:                int error;
                    276:
1.22      ad        277:                mutex_exit(&lmp->layerm_hashlock);
1.1       wrstuden  278:                /*
1.30      rmind     279:                 * Get a new vnode.  Make it to reference the layer_node.
                    280:                 * Note: aliasvp will be return with the reference held.
1.1       wrstuden  281:                 */
1.30      rmind     282:                error = (lmp->layerm_alloc)(mp, lowervp, &aliasvp);
                    283:                if (error)
                    284:                        return error;
1.1       wrstuden  285: #ifdef LAYERFS_DIAGNOSTIC
1.16      erh       286:                if (layerfs_debug)
                    287:                        printf("layer_node_create: create new alias vnode\n");
1.1       wrstuden  288: #endif
                    289:        }
                    290:
                    291:        /*
1.30      rmind     292:         * Now that we acquired a reference on the upper vnode, release one
                    293:         * on the lower node.  The existence of the layer_node retains one
1.1       wrstuden  294:         * reference to the lower node.
                    295:         */
                    296:        vrele(lowervp);
1.30      rmind     297:        KASSERT(lowervp->v_usecount > 0);
1.1       wrstuden  298:
                    299: #ifdef LAYERFS_DIAGNOSTIC
1.16      erh       300:        if (layerfs_debug)
                    301:                vprint("layer_node_create: alias", aliasvp);
1.1       wrstuden  302: #endif
1.30      rmind     303:        *nvpp = aliasvp;
                    304:        return 0;
1.1       wrstuden  305: }
                    306:
1.16      erh       307: #ifdef LAYERFS_DIAGNOSTIC
1.1       wrstuden  308: struct vnode *
1.26      dsl       309: layer_checkvp(struct vnode *vp, const char *fil, int lno)
1.1       wrstuden  310: {
                    311:        struct layer_node *a = VTOLAYER(vp);
                    312: #ifdef notyet
                    313:        /*
                    314:         * Can't do this check because vop_reclaim runs
                    315:         * with a funny vop vector.
                    316:         *
                    317:         * WRS - no it doesnt...
                    318:         */
                    319:        if (vp->v_op != layer_vnodeop_p) {
                    320:                printf ("layer_checkvp: on non-layer-node\n");
                    321: #ifdef notyet
                    322:                while (layer_checkvp_barrier) /*WAIT*/ ;
                    323: #endif
                    324:                panic("layer_checkvp");
                    325:        };
                    326: #endif
                    327:        if (a->layer_lowervp == NULL) {
                    328:                /* Should never happen */
                    329:                int i; u_long *p;
                    330:                printf("vp = %p, ZERO ptr\n", vp);
                    331:                for (p = (u_long *) a, i = 0; i < 8; i++)
                    332:                        printf(" %lx", p[i]);
                    333:                printf("\n");
                    334:                /* wait for debugger */
                    335:                panic("layer_checkvp");
                    336:        }
                    337:        if (a->layer_lowervp->v_usecount < 1) {
                    338:                int i; u_long *p;
                    339:                printf("vp = %p, unref'ed lowervp\n", vp);
                    340:                for (p = (u_long *) a, i = 0; i < 8; i++)
                    341:                        printf(" %lx", p[i]);
                    342:                printf("\n");
                    343:                /* wait for debugger */
                    344:                panic ("layer with unref'ed lowervp");
                    345:        };
                    346: #ifdef notnow
                    347:        printf("layer %p/%d -> %p/%d [%s, %d]\n",
                    348:                LAYERTOV(a), LAYERTOV(a)->v_usecount,
                    349:                a->layer_lowervp, a->layer_lowervp->v_usecount,
                    350:                fil, lno);
                    351: #endif
                    352:        return a->layer_lowervp;
                    353: }
1.16      erh       354: #endif

CVSweb <webmaster@jp.NetBSD.org>