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

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

unix.superglobalmegacorp.com

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