xref: /csrg-svn/sys/miscfs/nullfs/null_subr.c (revision 54751)
1*54751Sjohnh /*
2*54751Sjohnh  * Copyright (c) 1992 The Regents of the University of California
3*54751Sjohnh  * Copyright (c) 1990, 1992 Jan-Simon Pendry
4*54751Sjohnh  * All rights reserved.
5*54751Sjohnh  *
6*54751Sjohnh  * This code is derived from software donated to Berkeley by
7*54751Sjohnh  * Jan-Simon Pendry.
8*54751Sjohnh  *
9*54751Sjohnh  * %sccs.include.redist.c%
10*54751Sjohnh  *
11*54751Sjohnh  *	@(#)lofs_subr.c	1.2 (Berkeley) 6/18/92
12*54751Sjohnh  *
13*54751Sjohnh  * $Id: lofs_subr.c,v 1.11 1992/05/30 10:05:43 jsp Exp jsp $
14*54751Sjohnh  */
15*54751Sjohnh 
16*54751Sjohnh #include <sys/param.h>
17*54751Sjohnh #include <sys/systm.h>
18*54751Sjohnh #include <sys/time.h>
19*54751Sjohnh #include <sys/types.h>
20*54751Sjohnh #include <sys/vnode.h>
21*54751Sjohnh #include <sys/mount.h>
22*54751Sjohnh #include <sys/namei.h>
23*54751Sjohnh #include <sys/malloc.h>
24*54751Sjohnh #include <lofs/lofs.h>
25*54751Sjohnh 
26*54751Sjohnh #define LOG2_SIZEVNODE 7		/* log2(sizeof struct vnode) */
27*54751Sjohnh #define	NLOFSCACHE 16
28*54751Sjohnh #define	LOFS_NHASH(vp) ((((u_long)vp)>>LOG2_SIZEVNODE) & (NLOFSCACHE-1))
29*54751Sjohnh 
30*54751Sjohnh /*
31*54751Sjohnh  * Loopback cache:
32*54751Sjohnh  * Each cache entry holds a reference to the target vnode
33*54751Sjohnh  * along with a pointer to the alias vnode.  When an
34*54751Sjohnh  * entry is added the target vnode is VREF'd.  When the
35*54751Sjohnh  * alias is removed the target vnode is vrele'd.
36*54751Sjohnh  */
37*54751Sjohnh 
38*54751Sjohnh /*
39*54751Sjohnh  * Cache head
40*54751Sjohnh  */
41*54751Sjohnh struct lofscache {
42*54751Sjohnh 	struct lofsnode	*ac_forw;
43*54751Sjohnh 	struct lofsnode	*ac_back;
44*54751Sjohnh };
45*54751Sjohnh 
46*54751Sjohnh static struct lofscache lofscache[NLOFSCACHE];
47*54751Sjohnh 
48*54751Sjohnh /*
49*54751Sjohnh  * Initialise cache headers
50*54751Sjohnh  */
51*54751Sjohnh lofs_init()
52*54751Sjohnh {
53*54751Sjohnh 	struct lofscache *ac;
54*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
55*54751Sjohnh 	printf("lofs_init\n");		/* printed during system boot */
56*54751Sjohnh #endif
57*54751Sjohnh 
58*54751Sjohnh 	for (ac = lofscache; ac < lofscache + NLOFSCACHE; ac++)
59*54751Sjohnh 		ac->ac_forw = ac->ac_back = (struct lofsnode *) ac;
60*54751Sjohnh }
61*54751Sjohnh 
62*54751Sjohnh /*
63*54751Sjohnh  * Compute hash list for given target vnode
64*54751Sjohnh  */
65*54751Sjohnh static struct lofscache *
66*54751Sjohnh lofs_hash(targetvp)
67*54751Sjohnh struct vnode *targetvp;
68*54751Sjohnh {
69*54751Sjohnh 	return (&lofscache[LOFS_NHASH(targetvp)]);
70*54751Sjohnh }
71*54751Sjohnh 
72*54751Sjohnh /*
73*54751Sjohnh  * Make a new lofsnode node.
74*54751Sjohnh  * Vp is the alias vnode, lofsvp is the target vnode.
75*54751Sjohnh  * Maintain a reference to (targetvp).
76*54751Sjohnh  */
77*54751Sjohnh static void
78*54751Sjohnh lofs_alloc(vp, targetvp)
79*54751Sjohnh 	struct vnode *vp;
80*54751Sjohnh 	struct vnode *targetvp;
81*54751Sjohnh {
82*54751Sjohnh 	struct lofscache *hd;
83*54751Sjohnh 	struct lofsnode *a;
84*54751Sjohnh 
85*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
86*54751Sjohnh 	printf("lofs_alloc(%x, %x)\n", vp, targetvp);
87*54751Sjohnh #endif
88*54751Sjohnh 
89*54751Sjohnh 	MALLOC(a, struct lofsnode *, sizeof(struct lofsnode), M_TEMP, M_WAITOK);
90*54751Sjohnh 	a->a_vnode = vp;
91*54751Sjohnh 	vp->v_data = a;
92*54751Sjohnh 	VREF(targetvp);
93*54751Sjohnh 	a->a_lofsvp = targetvp;
94*54751Sjohnh 	hd = lofs_hash(targetvp);
95*54751Sjohnh 	insque(a, hd);
96*54751Sjohnh 
97*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
98*54751Sjohnh 	vprint("alloc vp", vp);
99*54751Sjohnh 	vprint("alloc targetvp", targetvp);
100*54751Sjohnh #endif
101*54751Sjohnh }
102*54751Sjohnh 
103*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
104*54751Sjohnh void
105*54751Sjohnh lofs_flushmp(mp)
106*54751Sjohnh 	struct mount *mp;
107*54751Sjohnh {
108*54751Sjohnh 	struct lofscache *ac;
109*54751Sjohnh 	int i = 0;
110*54751Sjohnh 	struct lofsnode *roota;
111*54751Sjohnh 
112*54751Sjohnh 	printf("lofs_flushmp(%x)\n", mp);
113*54751Sjohnh 
114*54751Sjohnh 	roota = LOFSP(VFSTOLOFS(mp)->rootvp);
115*54751Sjohnh 
116*54751Sjohnh 	for (ac = lofscache; ac < lofscache + NLOFSCACHE; ac++) {
117*54751Sjohnh 		struct lofsnode *a = ac->ac_forw;
118*54751Sjohnh 		while (a != (struct lofsnode *) ac) {
119*54751Sjohnh 			if (a != roota && a->a_vnode->v_mount == mp) {
120*54751Sjohnh 				struct vnode *vp = a->a_lofsvp;
121*54751Sjohnh 				if (vp) {
122*54751Sjohnh 					a->a_lofsvp = 0;
123*54751Sjohnh 					vprint("would vrele", vp);
124*54751Sjohnh 					/*vrele(vp);*/
125*54751Sjohnh 					i++;
126*54751Sjohnh 				}
127*54751Sjohnh 			}
128*54751Sjohnh 			a = a->a_forw;
129*54751Sjohnh 		}
130*54751Sjohnh 	}
131*54751Sjohnh 	if (i > 0)
132*54751Sjohnh 		printf("lofsnode: vrele'd %d aliases\n", i);
133*54751Sjohnh }
134*54751Sjohnh #endif
135*54751Sjohnh 
136*54751Sjohnh /*
137*54751Sjohnh  * Return alias for target vnode if already exists, else 0.
138*54751Sjohnh  */
139*54751Sjohnh static struct lofsnode *
140*54751Sjohnh lofs_find(mp, targetvp)
141*54751Sjohnh 	struct mount *mp;
142*54751Sjohnh 	struct vnode *targetvp;
143*54751Sjohnh {
144*54751Sjohnh 	struct lofscache *hd;
145*54751Sjohnh 	struct lofsnode *a;
146*54751Sjohnh 
147*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
148*54751Sjohnh 	printf("lofs_find(mp = %x, target = %x)\n", mp, targetvp);
149*54751Sjohnh #endif
150*54751Sjohnh 
151*54751Sjohnh 	/*
152*54751Sjohnh 	 * Find hash base, and then search the (two-way) linked
153*54751Sjohnh 	 * list looking for a lofsnode structure which is referencing
154*54751Sjohnh 	 * the target vnode.  If found, the increment the lofsnode
155*54751Sjohnh 	 * reference count (but NOT the target vnode's VREF counter).
156*54751Sjohnh 	 */
157*54751Sjohnh 	hd = lofs_hash(targetvp);
158*54751Sjohnh 
159*54751Sjohnh 	for (a = hd->ac_forw; a != (struct lofsnode *) hd; a = a->a_forw) {
160*54751Sjohnh 		if (a->a_lofsvp == targetvp && a->a_vnode->v_mount == mp) {
161*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
162*54751Sjohnh 			printf("lofs_find(%x): found (%x,%x)->%x\n",
163*54751Sjohnh 				targetvp, mp, a->a_vnode, targetvp);
164*54751Sjohnh #endif
165*54751Sjohnh 			return (a);
166*54751Sjohnh 		}
167*54751Sjohnh 	}
168*54751Sjohnh 
169*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
170*54751Sjohnh 	printf("lofs_find(%x, %x): NOT found\n", mp, targetvp);
171*54751Sjohnh #endif
172*54751Sjohnh 
173*54751Sjohnh 	return (0);
174*54751Sjohnh }
175*54751Sjohnh 
176*54751Sjohnh static int
177*54751Sjohnh lofs_alias(mp, targetvp, newvpp)
178*54751Sjohnh 	struct mount *mp;
179*54751Sjohnh 	struct vnode *targetvp;
180*54751Sjohnh 	struct vnode **newvpp;
181*54751Sjohnh {
182*54751Sjohnh 	struct lofsnode *ap;
183*54751Sjohnh 	struct vnode *aliasvp;
184*54751Sjohnh 
185*54751Sjohnh 	if (targetvp->v_type != VDIR || targetvp->v_op == lofs_vnodeop_p) {
186*54751Sjohnh 		*newvpp = targetvp;
187*54751Sjohnh 		return;
188*54751Sjohnh 	}
189*54751Sjohnh 
190*54751Sjohnh 	ap = lofs_find(mp, targetvp);
191*54751Sjohnh 
192*54751Sjohnh 	if (ap) {
193*54751Sjohnh 		/*
194*54751Sjohnh 		 * Take another reference to the alias vnode
195*54751Sjohnh 		 */
196*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
197*54751Sjohnh 		vprint("lofs_alias: exists", ap->a_vnode);
198*54751Sjohnh #endif
199*54751Sjohnh 		aliasvp = ap->a_vnode;
200*54751Sjohnh 		VREF(aliasvp);
201*54751Sjohnh 	} else {
202*54751Sjohnh 		int error;
203*54751Sjohnh 
204*54751Sjohnh 		/*
205*54751Sjohnh 		 * Get new vnode.
206*54751Sjohnh 		 */
207*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
208*54751Sjohnh 		printf("lofs_alias: create new alias vnode\n");
209*54751Sjohnh #endif
210*54751Sjohnh 		if (error = getnewvnode(VT_UFS, mp, lofs_vnodeop_p, &aliasvp))
211*54751Sjohnh 			return (error);	/* XXX: VT_LOFS above */
212*54751Sjohnh 
213*54751Sjohnh 		/*
214*54751Sjohnh 		 * Must be a directory
215*54751Sjohnh 		 */
216*54751Sjohnh 		aliasvp->v_type = VDIR;
217*54751Sjohnh 
218*54751Sjohnh 		/*
219*54751Sjohnh 		 * Make new vnode reference the lofsnode.
220*54751Sjohnh 		 */
221*54751Sjohnh 		lofs_alloc(aliasvp, targetvp);
222*54751Sjohnh 
223*54751Sjohnh 		/*
224*54751Sjohnh 		 * aliasvp is already VREF'd by getnewvnode()
225*54751Sjohnh 		 */
226*54751Sjohnh 	}
227*54751Sjohnh 
228*54751Sjohnh 	vrele(targetvp);
229*54751Sjohnh 
230*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
231*54751Sjohnh 	vprint("lofs_alias alias", aliasvp);
232*54751Sjohnh 	vprint("lofs_alias target", targetvp);
233*54751Sjohnh #endif
234*54751Sjohnh 
235*54751Sjohnh 	*newvpp = aliasvp;
236*54751Sjohnh 	return (0);
237*54751Sjohnh }
238*54751Sjohnh 
239*54751Sjohnh /*
240*54751Sjohnh  * Try to find an existing lofsnode vnode refering
241*54751Sjohnh  * to it, otherwise make a new lofsnode vnode which
242*54751Sjohnh  * contains a reference to the target vnode.
243*54751Sjohnh  */
244*54751Sjohnh make_lofs(mp, vpp)
245*54751Sjohnh 	struct mount *mp;
246*54751Sjohnh 	struct vnode **vpp;
247*54751Sjohnh {
248*54751Sjohnh 	int error;
249*54751Sjohnh 	struct vnode *aliasvp;
250*54751Sjohnh 	struct vnode *targetvp;
251*54751Sjohnh 
252*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
253*54751Sjohnh 	printf("make_lofs(mp = %x, vp = %x\n", mp, *vpp);
254*54751Sjohnh #endif
255*54751Sjohnh 
256*54751Sjohnh 	/*
257*54751Sjohnh 	 * (targetvp) is locked at this point.
258*54751Sjohnh 	 */
259*54751Sjohnh 	targetvp = *vpp;
260*54751Sjohnh 
261*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
262*54751Sjohnh 	if (targetvp == 0)
263*54751Sjohnh 		panic("make_lofs: null vp");
264*54751Sjohnh #endif
265*54751Sjohnh 
266*54751Sjohnh 	/*
267*54751Sjohnh 	 * Try to find an existing reference to the target vnodes.
268*54751Sjohnh 	 */
269*54751Sjohnh 	return (lofs_alias(mp, targetvp, vpp));
270*54751Sjohnh }
271*54751Sjohnh 
272*54751Sjohnh #ifdef LOFS_DIAGNOSTIC
273*54751Sjohnh struct vnode *
274*54751Sjohnh lofs_checkvp(vp, fil, lno)
275*54751Sjohnh 	struct vnode *vp;
276*54751Sjohnh 	char *fil;
277*54751Sjohnh 	int lno;
278*54751Sjohnh {
279*54751Sjohnh 	struct lofsnode *a = LOFSP(vp);
280*54751Sjohnh 	if (a->a_lofsvp == 0) {
281*54751Sjohnh 		int i; u_long *p;
282*54751Sjohnh 		printf("vp = %x, ZERO ptr\n", vp);
283*54751Sjohnh #ifdef notdef
284*54751Sjohnh 		for (p = (u_long *) a, i = 0; i < 8; i++)
285*54751Sjohnh 			printf(" %x", p[i]);
286*54751Sjohnh 		printf("\n");
287*54751Sjohnh 		DELAY(2000000);
288*54751Sjohnh 		panic("lofs_checkvp");
289*54751Sjohnh #endif
290*54751Sjohnh 	}
291*54751Sjohnh 	printf("aliasvp %x/%d -> %x/%d [%s, %d]\n",
292*54751Sjohnh 		a->a_vnode, a->a_vnode->v_usecount,
293*54751Sjohnh 		a->a_lofsvp, a->a_lofsvp ? a->a_lofsvp->v_usecount : -42,
294*54751Sjohnh 		fil, lno);
295*54751Sjohnh 	return a->a_lofsvp;
296*54751Sjohnh }
297*54751Sjohnh #endif
298