Annotation of kernel/bsd/miscfs/nullfs/null_subr.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     26: /*
                     27:  * Copyright (c) 1992, 1993
                     28:  *     The Regents of the University of California.  All rights reserved.
                     29:  *
                     30:  * This code is derived from software donated to Berkeley by
                     31:  * Jan-Simon Pendry.
                     32:  *
                     33:  * Redistribution and use in source and binary forms, with or without
                     34:  * modification, are permitted provided that the following conditions
                     35:  * are met:
                     36:  * 1. Redistributions of source code must retain the above copyright
                     37:  *    notice, this list of conditions and the following disclaimer.
                     38:  * 2. Redistributions in binary form must reproduce the above copyright
                     39:  *    notice, this list of conditions and the following disclaimer in the
                     40:  *    documentation and/or other materials provided with the distribution.
                     41:  * 3. All advertising materials mentioning features or use of this software
                     42:  *    must display the following acknowledgement:
                     43:  *     This product includes software developed by the University of
                     44:  *     California, Berkeley and its contributors.
                     45:  * 4. Neither the name of the University nor the names of its contributors
                     46:  *    may be used to endorse or promote products derived from this software
                     47:  *    without specific prior written permission.
                     48:  *
                     49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     59:  * SUCH DAMAGE.
                     60:  *
                     61:  *     @(#)null_subr.c 8.7 (Berkeley) 5/14/95
                     62:  *
                     63:  *     null_subr.c     8.4 (Berkeley) 1/21/94
                     64:  */
                     65: 
                     66: #include <sys/param.h>
                     67: #include <sys/systm.h>
                     68: #include <sys/proc.h>
                     69: #include <sys/time.h>
                     70: #include <sys/types.h>
                     71: #include <sys/vnode.h>
                     72: #include <sys/mount.h>
                     73: #include <sys/namei.h>
                     74: #include <sys/malloc.h>
                     75: #include <miscfs/nullfs/null.h>
                     76: 
                     77: #define LOG2_SIZEVNODE 7               /* log2(sizeof struct vnode) */
                     78: #define        NNULLNODECACHE 16
                     79: 
                     80: /*
                     81:  * Null layer cache:
                     82:  * Each cache entry holds a reference to the lower vnode
                     83:  * along with a pointer to the alias vnode.  When an
                     84:  * entry is added the lower vnode is VREF'd.  When the
                     85:  * alias is removed the lower vnode is vrele'd.
                     86:  */
                     87: 
                     88: #define        NULL_NHASH(vp) \
                     89:        (&null_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & null_node_hash])
                     90: LIST_HEAD(null_node_hashhead, null_node) *null_node_hashtbl;
                     91: u_long null_node_hash;
                     92: 
                     93: /*
                     94:  * Initialise cache headers
                     95:  */
                     96: nullfs_init()
                     97: {
                     98: 
                     99: #ifdef NULLFS_DIAGNOSTIC
                    100:        printf("nullfs_init\n");                /* printed during system boot */
                    101: #endif
                    102:        null_node_hashtbl = hashinit(NNULLNODECACHE, M_CACHE, &null_node_hash);
                    103: }
                    104: 
                    105: /*
                    106:  * Return a VREF'ed alias for lower vnode if already exists, else 0.
                    107:  */
                    108: static struct vnode *
                    109: null_node_find(mp, lowervp)
                    110:        struct mount *mp;
                    111:        struct vnode *lowervp;
                    112: {
                    113:        struct proc *p = curproc;       /* XXX */
                    114:        struct null_node_hashhead *hd;
                    115:        struct null_node *a;
                    116:        struct vnode *vp;
                    117: 
                    118:        /*
                    119:         * Find hash base, and then search the (two-way) linked
                    120:         * list looking for a null_node structure which is referencing
                    121:         * the lower vnode.  If found, the increment the null_node
                    122:         * reference count (but NOT the lower vnode's VREF counter).
                    123:         */
                    124:        hd = NULL_NHASH(lowervp);
                    125: loop:
                    126:        for (a = hd->lh_first; a != 0; a = a->null_hash.le_next) {
                    127:                if (a->null_lowervp == lowervp && NULLTOV(a)->v_mount == mp) {
                    128:                        vp = NULLTOV(a);
                    129:                        /*
                    130:                         * We need vget for the VXLOCK
                    131:                         * stuff, but we don't want to lock
                    132:                         * the lower node.
                    133:                         */
                    134:                        if (vget(vp, 0, p)) {
                    135:                                printf ("null_node_find: vget failed.\n");
                    136:                                goto loop;
                    137:                        };
                    138:                        return (vp);
                    139:                }
                    140:        }
                    141: 
                    142:        return NULL;
                    143: }
                    144: 
                    145: 
                    146: /*
                    147:  * Make a new null_node node.
                    148:  * Vp is the alias vnode, lofsvp is the lower vnode.
                    149:  * Maintain a reference to (lowervp).
                    150:  */
                    151: static int
                    152: null_node_alloc(mp, lowervp, vpp)
                    153:        struct mount *mp;
                    154:        struct vnode *lowervp;
                    155:        struct vnode **vpp;
                    156: {
                    157:        struct null_node_hashhead *hd;
                    158:        struct null_node *xp;
                    159:        struct vnode *othervp, *vp;
                    160:        int error;
                    161: 
                    162:        if (error = getnewvnode(VT_NULL, mp, null_vnodeop_p, vpp))
                    163:                return (error);
                    164:        vp = *vpp;
                    165: 
                    166:        MALLOC(xp, struct null_node *, sizeof(struct null_node), M_TEMP, M_WAITOK);
                    167:        vp->v_type = lowervp->v_type;
                    168:        xp->null_vnode = vp;
                    169:        vp->v_data = xp;
                    170:        xp->null_lowervp = lowervp;
                    171:        /*
                    172:         * Before we insert our new node onto the hash chains,
                    173:         * check to see if someone else has beaten us to it.
                    174:         * (We could have slept in MALLOC.)
                    175:         */
                    176:        if (othervp = null_node_find(lowervp)) {
                    177:                FREE(xp, M_TEMP);
                    178:                vp->v_type = VBAD;      /* node is discarded */
                    179:                vp->v_usecount = 0;     /* XXX */
                    180:                *vpp = othervp;
                    181:                return 0;
                    182:        };
                    183:        VREF(lowervp);   /* Extra VREF will be vrele'd in null_node_create */
                    184:        hd = NULL_NHASH(lowervp);
                    185:        LIST_INSERT_HEAD(hd, xp, null_hash);
                    186:        return 0;
                    187: }
                    188: 
                    189: 
                    190: /*
                    191:  * Try to find an existing null_node vnode refering
                    192:  * to it, otherwise make a new null_node vnode which
                    193:  * contains a reference to the lower vnode.
                    194:  */
                    195: int
                    196: null_node_create(mp, lowervp, newvpp)
                    197:        struct mount *mp;
                    198:        struct vnode *lowervp;
                    199:        struct vnode **newvpp;
                    200: {
                    201:        struct vnode *aliasvp;
                    202: 
                    203:        if (aliasvp = null_node_find(mp, lowervp)) {
                    204:                /*
                    205:                 * null_node_find has taken another reference
                    206:                 * to the alias vnode.
                    207:                 */
                    208: #ifdef NULLFS_DIAGNOSTIC
                    209:                vprint("null_node_create: exists", NULLTOV(ap));
                    210: #endif
                    211:                /* VREF(aliasvp); --- done in null_node_find */
                    212:        } else {
                    213:                int error;
                    214: 
                    215:                /*
                    216:                 * Get new vnode.
                    217:                 */
                    218: #ifdef NULLFS_DIAGNOSTIC
                    219:                printf("null_node_create: create new alias vnode\n");
                    220: #endif
                    221: 
                    222:                /*
                    223:                 * Make new vnode reference the null_node.
                    224:                 */
                    225:                if (error = null_node_alloc(mp, lowervp, &aliasvp))
                    226:                        return error;
                    227: 
                    228:                /*
                    229:                 * aliasvp is already VREF'd by getnewvnode()
                    230:                 */
                    231:        }
                    232: 
                    233:        vrele(lowervp);
                    234: 
                    235: #if DIAGNOSTIC
                    236:        if (lowervp->v_usecount < 1) {
                    237:                /* Should never happen... */
                    238:                vprint ("null_node_create: alias ", aliasvp);
                    239:                vprint ("null_node_create: lower ", lowervp);
                    240:                panic ("null_node_create: lower has 0 usecount.");
                    241:        };
                    242: #endif
                    243: 
                    244: #ifdef NULLFS_DIAGNOSTIC
                    245:        vprint("null_node_create: alias", aliasvp);
                    246:        vprint("null_node_create: lower", lowervp);
                    247: #endif
                    248: 
                    249:        *newvpp = aliasvp;
                    250:        return (0);
                    251: }
                    252: #ifdef NULLFS_DIAGNOSTIC
                    253: struct vnode *
                    254: null_checkvp(vp, fil, lno)
                    255:        struct vnode *vp;
                    256:        char *fil;
                    257:        int lno;
                    258: {
                    259:        struct null_node *a = VTONULL(vp);
                    260: #ifdef notyet
                    261:        /*
                    262:         * Can't do this check because vop_reclaim runs
                    263:         * with a funny vop vector.
                    264:         */
                    265:        if (vp->v_op != null_vnodeop_p) {
                    266:                printf ("null_checkvp: on non-null-node\n");
                    267:                while (null_checkvp_barrier) /*WAIT*/ ;
                    268:                panic("null_checkvp");
                    269:        };
                    270: #endif
                    271:        if (a->null_lowervp == NULL) {
                    272:                /* Should never happen */
                    273:                int i; u_long *p;
                    274:                printf("vp = %x, ZERO ptr\n", vp);
                    275:                for (p = (u_long *) a, i = 0; i < 8; i++)
                    276:                        printf(" %x", p[i]);
                    277:                printf("\n");
                    278:                /* wait for debugger */
                    279:                while (null_checkvp_barrier) /*WAIT*/ ;
                    280:                panic("null_checkvp");
                    281:        }
                    282:        if (a->null_lowervp->v_usecount < 1) {
                    283:                int i; u_long *p;
                    284:                printf("vp = %x, unref'ed lowervp\n", vp);
                    285:                for (p = (u_long *) a, i = 0; i < 8; i++)
                    286:                        printf(" %x", p[i]);
                    287:                printf("\n");
                    288:                /* wait for debugger */
                    289:                while (null_checkvp_barrier) /*WAIT*/ ;
                    290:                panic ("null with unref'ed lowervp");
                    291:        };
                    292: #ifdef notyet
                    293:        printf("null %x/%d -> %x/%d [%s, %d]\n",
                    294:                NULLTOV(a), NULLTOV(a)->v_usecount,
                    295:                a->null_lowervp, a->null_lowervp->v_usecount,
                    296:                fil, lno);
                    297: #endif
                    298:        return a->null_lowervp;
                    299: }
                    300: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.