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