|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.