xref: /csrg-svn/sys/miscfs/umapfs/umap_subr.c (revision 54947)
1*54947Sheideman /*
2*54947Sheideman  * Copyright (c) 1992 The Regents of the University of California
3*54947Sheideman  * Copyright (c) 1990, 1992 Jan-Simon Pendry
4*54947Sheideman  * All rights reserved.
5*54947Sheideman  *
6*54947Sheideman  * This code is derived from software donated to Berkeley by
7*54947Sheideman  * Jan-Simon Pendry.
8*54947Sheideman  *
9*54947Sheideman  * %sccs.include.redist.c%
10*54947Sheideman  *
11*54947Sheideman  *	@(#)lofs_subr.c	1.2 (Berkeley) 6/18/92
12*54947Sheideman  *
13*54947Sheideman  * $Id: lofs_subr.c,v 1.11 1992/05/30 10:05:43 jsp Exp jsp $
14*54947Sheideman  */
15*54947Sheideman 
16*54947Sheideman #include <sys/param.h>
17*54947Sheideman #include <sys/systm.h>
18*54947Sheideman #include <sys/time.h>
19*54947Sheideman #include <sys/types.h>
20*54947Sheideman #include <sys/vnode.h>
21*54947Sheideman #include <sys/mount.h>
22*54947Sheideman #include <sys/namei.h>
23*54947Sheideman #include <sys/malloc.h>
24*54947Sheideman #include <umapfs/umap.h>
25*54947Sheideman 
26*54947Sheideman #define LOG2_SIZEVNODE 7		/* log2(sizeof struct vnode) */
27*54947Sheideman #define	NUMAPNODECACHE 16
28*54947Sheideman #define	UMAP_NHASH(vp) ((((u_long)vp)>>LOG2_SIZEVNODE) & (NUMAPNODECACHE-1))
29*54947Sheideman 
30*54947Sheideman /*
31*54947Sheideman  * Null layer cache:
32*54947Sheideman  * Each cache entry holds a reference to the target vnode
33*54947Sheideman  * along with a pointer to the alias vnode.  When an
34*54947Sheideman  * entry is added the target vnode is VREF'd.  When the
35*54947Sheideman  * alias is removed the target vnode is vrele'd.
36*54947Sheideman  */
37*54947Sheideman 
38*54947Sheideman /*
39*54947Sheideman  * Cache head
40*54947Sheideman  */
41*54947Sheideman struct umap_node_cache {
42*54947Sheideman 	struct umap_node	*ac_forw;
43*54947Sheideman 	struct umap_node	*ac_back;
44*54947Sheideman };
45*54947Sheideman 
46*54947Sheideman static struct umap_node_cache umap_node_cache[NUMAPNODECACHE];
47*54947Sheideman 
48*54947Sheideman /*
49*54947Sheideman  * Initialise cache headers
50*54947Sheideman  */
51*54947Sheideman umapfs_init()
52*54947Sheideman {
53*54947Sheideman 	struct umap_node_cache *ac;
54*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC
55*54947Sheideman 	printf("umapfs_init\n");		/* printed during system boot */
56*54947Sheideman #endif
57*54947Sheideman 
58*54947Sheideman 	for (ac = umap_node_cache; ac < umap_node_cache + NUMAPNODECACHE; ac++)
59*54947Sheideman 		ac->ac_forw = ac->ac_back = (struct umap_node *) ac;
60*54947Sheideman }
61*54947Sheideman 
62*54947Sheideman /*
63*54947Sheideman  * Compute hash list for given target vnode
64*54947Sheideman  */
65*54947Sheideman static struct umap_node_cache *
66*54947Sheideman umap_node_hash(targetvp)
67*54947Sheideman struct vnode *targetvp;
68*54947Sheideman {
69*54947Sheideman 	return (&umap_node_cache[UMAP_NHASH(targetvp)]);
70*54947Sheideman }
71*54947Sheideman 
72*54947Sheideman /*
73*54947Sheideman  * Make a new umap_node node.
74*54947Sheideman  * Vp is the alias vnode, lofsvp is the target vnode.
75*54947Sheideman  * Maintain a reference to (targetvp).
76*54947Sheideman  */
77*54947Sheideman static void
78*54947Sheideman umap_node_alloc(vp, targetvp)
79*54947Sheideman 	struct vnode *vp;
80*54947Sheideman 	struct vnode *targetvp;
81*54947Sheideman {
82*54947Sheideman 	struct umap_node_cache *hd;
83*54947Sheideman 	struct umap_node *a;
84*54947Sheideman 
85*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC
86*54947Sheideman 	printf("umap_node_alloc(%x, %x)\n", vp, targetvp);
87*54947Sheideman #endif
88*54947Sheideman 
89*54947Sheideman 	MALLOC(a, struct umap_node *, sizeof(struct umap_node), M_TEMP, M_WAITOK);
90*54947Sheideman 	vp->v_type = targetvp->v_type;
91*54947Sheideman 	a->umap_vnode = vp;
92*54947Sheideman 	vp->v_data = a;
93*54947Sheideman 	VREF(targetvp);   /* Extra VREF will be vrele'd in umap_node_create */
94*54947Sheideman 	a->umap_lowervp = targetvp;
95*54947Sheideman 	hd = umap_node_hash(targetvp);
96*54947Sheideman 	insque(a, hd);
97*54947Sheideman 
98*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC
99*54947Sheideman 	vprint("umap_node_alloc vp", vp);
100*54947Sheideman 	vprint("umap_node_alloc targetvp", targetvp);
101*54947Sheideman #endif
102*54947Sheideman }
103*54947Sheideman 
104*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC
105*54947Sheideman /*
106*54947Sheideman  * NEEDSWORK:  The ability to set lowervp to umap here
107*54947Sheideman  * implies that one can never count on lowervp staying umap
108*54947Sheideman  * (even if vp is locked).  This seems quite bad.  Think
109*54947Sheideman  * about these things.
110*54947Sheideman  */
111*54947Sheideman void
112*54947Sheideman umap_node_flushmp (mp)
113*54947Sheideman 	struct mount *mp;
114*54947Sheideman {
115*54947Sheideman 	struct umap_node_cache *ac;
116*54947Sheideman 	int i = 0;
117*54947Sheideman 	struct umap_node *roota;
118*54947Sheideman 
119*54947Sheideman 	printf("umap_node_flushmp (%x)\n", mp);
120*54947Sheideman 
121*54947Sheideman 	roota = VTOUMAP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp);
122*54947Sheideman 
123*54947Sheideman 	for (ac = umap_node_cache; ac < umap_node_cache + NUMAPNODECACHE; ac++) {
124*54947Sheideman 		struct umap_node *a = ac->ac_forw;
125*54947Sheideman 		while (a != (struct umap_node *) ac) {
126*54947Sheideman 			if (a != roota && a->umap_vnode->v_mount == mp) {
127*54947Sheideman 				struct vnode *vp = a->umap_lowervp;
128*54947Sheideman 				if (vp) {
129*54947Sheideman 					a->umap_lowervp = 0;
130*54947Sheideman 					vprint("umap_flushmp: would vrele", vp);
131*54947Sheideman 					/*vrele(vp);*/
132*54947Sheideman 					i++;
133*54947Sheideman 				}
134*54947Sheideman 			}
135*54947Sheideman 			a = a->umap_forw;
136*54947Sheideman 		}
137*54947Sheideman 	}
138*54947Sheideman 	if (i > 0)
139*54947Sheideman 		printf("umap_node: vrele'd %d aliases\n", i);
140*54947Sheideman }
141*54947Sheideman #endif
142*54947Sheideman 
143*54947Sheideman /*
144*54947Sheideman  * Return alias for target vnode if already exists, else 0.
145*54947Sheideman  */
146*54947Sheideman static struct umap_node *
147*54947Sheideman umap_node_find(mp, targetvp)
148*54947Sheideman 	struct mount *mp;
149*54947Sheideman 	struct vnode *targetvp;
150*54947Sheideman {
151*54947Sheideman 	struct umap_node_cache *hd;
152*54947Sheideman 	struct umap_node *a;
153*54947Sheideman 
154*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC
155*54947Sheideman 	printf("umap_node_find(mp = %x, target = %x)\n", mp, targetvp);
156*54947Sheideman #endif
157*54947Sheideman 
158*54947Sheideman 	/*
159*54947Sheideman 	 * Find hash base, and then search the (two-way) linked
160*54947Sheideman 	 * list looking for a umap_node structure which is referencing
161*54947Sheideman 	 * the target vnode.  If found, the increment the umap_node
162*54947Sheideman 	 * reference count (but NOT the target vnode's VREF counter).
163*54947Sheideman 	 */
164*54947Sheideman 	hd = umap_node_hash(targetvp);
165*54947Sheideman 
166*54947Sheideman 	for (a = hd->ac_forw; a != (struct umap_node *) hd; a = a->umap_forw) {
167*54947Sheideman 		if (a->umap_lowervp == targetvp && a->umap_vnode->v_mount == mp) {
168*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC
169*54947Sheideman 			printf("umap_node_find(%x): found (%x,%x)->%x\n",
170*54947Sheideman 				targetvp, mp, a->umap_vnode, targetvp);
171*54947Sheideman #endif
172*54947Sheideman 			return (a);
173*54947Sheideman 		}
174*54947Sheideman 	}
175*54947Sheideman 
176*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC
177*54947Sheideman 	printf("umap_node_find(%x, %x): NOT found\n", mp, targetvp);
178*54947Sheideman #endif
179*54947Sheideman 
180*54947Sheideman 	return (0);
181*54947Sheideman }
182*54947Sheideman 
183*54947Sheideman /*
184*54947Sheideman  * Try to find an existing umap_node vnode refering
185*54947Sheideman  * to it, otherwise make a new umap_node vnode which
186*54947Sheideman  * contains a reference to the target vnode.
187*54947Sheideman  */
188*54947Sheideman int
189*54947Sheideman umap_node_create(mp, targetvp, newvpp)
190*54947Sheideman 	struct mount *mp;
191*54947Sheideman 	struct vnode *targetvp;
192*54947Sheideman 	struct vnode **newvpp;
193*54947Sheideman {
194*54947Sheideman 	struct umap_node *ap;
195*54947Sheideman 	struct vnode *aliasvp;
196*54947Sheideman 
197*54947Sheideman 	ap = umap_node_find(mp, targetvp);
198*54947Sheideman 
199*54947Sheideman 	if (ap) {
200*54947Sheideman 		/*
201*54947Sheideman 		 * Take another reference to the alias vnode
202*54947Sheideman 		 */
203*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC
204*54947Sheideman 		vprint("umap_node_create: exists", ap->umap_vnode);
205*54947Sheideman #endif
206*54947Sheideman 		aliasvp = ap->umap_vnode;
207*54947Sheideman 		VREF(aliasvp);
208*54947Sheideman 	} else {
209*54947Sheideman 		int error;
210*54947Sheideman 
211*54947Sheideman 		/*
212*54947Sheideman 		 * Get new vnode.
213*54947Sheideman 		 */
214*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC
215*54947Sheideman 		printf("umap_node_create: create new alias vnode\n");
216*54947Sheideman #endif
217*54947Sheideman 		if (error = getnewvnode(VT_UFS, mp, umap_vnodeop_p, &aliasvp))
218*54947Sheideman 			return (error);	/* XXX: VT_LOFS above */
219*54947Sheideman 
220*54947Sheideman 		/*
221*54947Sheideman 		 * Make new vnode reference the umap_node.
222*54947Sheideman 		 */
223*54947Sheideman 		umap_node_alloc(aliasvp, targetvp);
224*54947Sheideman 
225*54947Sheideman 		/*
226*54947Sheideman 		 * aliasvp is already VREF'd by getnewvnode()
227*54947Sheideman 		 */
228*54947Sheideman 	}
229*54947Sheideman 
230*54947Sheideman 	vrele(targetvp);
231*54947Sheideman 
232*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC
233*54947Sheideman 	vprint("umap_node_create: alias", aliasvp);
234*54947Sheideman 	vprint("umap_node_create: target", targetvp);
235*54947Sheideman #endif
236*54947Sheideman 
237*54947Sheideman 	*newvpp = aliasvp;
238*54947Sheideman 	return (0);
239*54947Sheideman }
240*54947Sheideman #ifdef UMAPFS_DIAGNOSTIC
241*54947Sheideman int umap_checkvp_barrier = 1;
242*54947Sheideman struct vnode *
243*54947Sheideman umap_checkvp(vp, fil, lno)
244*54947Sheideman 	struct vnode *vp;
245*54947Sheideman 	char *fil;
246*54947Sheideman 	int lno;
247*54947Sheideman {
248*54947Sheideman 	struct umap_node *a = VTOUMAP(vp);
249*54947Sheideman #if 0
250*54947Sheideman 	/*
251*54947Sheideman 	 * Can't do this check because vop_reclaim runs
252*54947Sheideman 	 * with funny vop vector.
253*54947Sheideman 	 */
254*54947Sheideman 	if (vp->v_op != umap_vnodeop_p) {
255*54947Sheideman 		printf ("umap_checkvp: on non-umap-node\n");
256*54947Sheideman 		while (umap_checkvp_barrier) /*WAIT*/ ;
257*54947Sheideman 		panic("umap_checkvp");
258*54947Sheideman 	};
259*54947Sheideman #endif
260*54947Sheideman 	if (a->umap_lowervp == NULL) {
261*54947Sheideman 		/* Should never happen */
262*54947Sheideman 		int i; u_long *p;
263*54947Sheideman 		printf("vp = %x, ZERO ptr\n", vp);
264*54947Sheideman 		for (p = (u_long *) a, i = 0; i < 8; i++)
265*54947Sheideman 			printf(" %x", p[i]);
266*54947Sheideman 		printf("\n");
267*54947Sheideman 		/* wait for debugger */
268*54947Sheideman 		while (umap_checkvp_barrier) /*WAIT*/ ;
269*54947Sheideman 		panic("umap_checkvp");
270*54947Sheideman 	}
271*54947Sheideman 	if (a->umap_lowervp->v_usecount < 1) {
272*54947Sheideman 		int i; u_long *p;
273*54947Sheideman 		printf("vp = %x, unref'ed lowervp\n", vp);
274*54947Sheideman 		for (p = (u_long *) a, i = 0; i < 8; i++)
275*54947Sheideman 			printf(" %x", p[i]);
276*54947Sheideman 		printf("\n");
277*54947Sheideman 		/* wait for debugger */
278*54947Sheideman 		while (umap_checkvp_barrier) /*WAIT*/ ;
279*54947Sheideman 		panic ("umap with unref'ed lowervp");
280*54947Sheideman 	};
281*54947Sheideman #if 0
282*54947Sheideman 	printf("umap %x/%d -> %x/%d [%s, %d]\n",
283*54947Sheideman 	        a->umap_vnode, a->umap_vnode->v_usecount,
284*54947Sheideman 		a->umap_lowervp, a->umap_lowervp->v_usecount,
285*54947Sheideman 		fil, lno);
286*54947Sheideman #endif
287*54947Sheideman 	return a->umap_lowervp;
288*54947Sheideman }
289*54947Sheideman #endif
290*54947Sheideman 
291*54947Sheideman /* umap_mapids maps all of the ids in a credential, both user and group. */
292*54947Sheideman 
293*54947Sheideman umap_mapids(credp,usermap,unentries,groupmap,gnentries)
294*54947Sheideman 	struct ucred *credp;
295*54947Sheideman 	int * usermap, groupmap;
296*54947Sheideman 	int unentries,gnentries;
297*54947Sheideman {
298*54947Sheideman 	int i,gid,uid;
299*54947Sheideman 
300*54947Sheideman 	/* Find uid entry in map */
301*54947Sheideman 
302*54947Sheideman 	uid = umap_findid(credp->cr_uid,usermap,unentries);
303*54947Sheideman 
304*54947Sheideman 	if (uid != -1) {
305*54947Sheideman 		credp->cr_ruid =
306*54947Sheideman 		credp->cr_uid =
307*54947Sheideman 			(u_short)uid;
308*54947Sheideman 	} else
309*54947Sheideman 		credp->cr_ruid = credp->cr_uid = (u_short)NOBODY;
310*54947Sheideman 
311*54947Sheideman 	/* Find gid entry in map */
312*54947Sheideman 
313*54947Sheideman 	gid = umap_findid(credp->cr_gid,groupmap,gnentries);
314*54947Sheideman 
315*54947Sheideman 	if (gid != -1) {
316*54947Sheideman 		credp->cr_rgid =
317*54947Sheideman 		credp->cr_gid =
318*54947Sheideman 			(u_short)gid;
319*54947Sheideman 	} else
320*54947Sheideman 		credp->cr_rgid = credp->cr_gid = (u_short)NULLGROUP;
321*54947Sheideman 
322*54947Sheideman 	/* Now we must map each of the set of groups in the cr_groups
323*54947Sheideman 		structure. */
324*54947Sheideman 
325*54947Sheideman 	i = 0;
326*54947Sheideman 	while (credp->cr_groups[i] != 0)
327*54947Sheideman 	{
328*54947Sheideman 		gid = umap_findid(credp->cr_groups[i],groupmap,
329*54947Sheideman 			gnentries);
330*54947Sheideman 
331*54947Sheideman 		if (gid != -1)
332*54947Sheideman 			credp->cr_groups[i++] = (u_short)gid;
333*54947Sheideman 		else
334*54947Sheideman 			credp->cr_groups[i++] = (u_short)NULLGROUP;
335*54947Sheideman 
336*54947Sheideman 	}
337*54947Sheideman }
338*54947Sheideman 
339*54947Sheideman /* umap_findid is called by various routines in umap_vnodeops.c to
340*54947Sheideman  * find a user or group id in a map.
341*54947Sheideman  */
342*54947Sheideman 
343*54947Sheideman umap_findid(id,map,nentries)
344*54947Sheideman 	ushort id;
345*54947Sheideman 	int map[][2];
346*54947Sheideman 	int nentries;
347*54947Sheideman {
348*54947Sheideman 	int i;
349*54947Sheideman 
350*54947Sheideman 	/* Find uid entry in map */
351*54947Sheideman 	i = 0;
352*54947Sheideman 	while ((i<nentries) && ((u_short)(map[i][0] ) != id))
353*54947Sheideman 		i++;
354*54947Sheideman 
355*54947Sheideman 	if ( i < nentries )
356*54947Sheideman 		return (map[i][1]);
357*54947Sheideman 	else
358*54947Sheideman 		return (-1);
359*54947Sheideman 
360*54947Sheideman }
361*54947Sheideman 
362*54947Sheideman /* umap_reverse_findid is called by umap_getattr() in umap_vnodeops.c to
363*54947Sheideman  * find a user or group id in a map, in reverse.
364*54947Sheideman  */
365*54947Sheideman 
366*54947Sheideman umap_reverse_findid(id,map,nentries)
367*54947Sheideman 	ushort id;
368*54947Sheideman 	int map[][2];
369*54947Sheideman 	int nentries;
370*54947Sheideman {
371*54947Sheideman 	int i;
372*54947Sheideman 
373*54947Sheideman 	/* Find uid entry in map */
374*54947Sheideman 	i = 0;
375*54947Sheideman 	while ((i<nentries) && ((u_short)(map[i][1] ) != id))
376*54947Sheideman 		i++;
377*54947Sheideman 
378*54947Sheideman 	if ( i < nentries )
379*54947Sheideman 		return (map[i][0]);
380*54947Sheideman 	else
381*54947Sheideman 		return (-1);
382*54947Sheideman 
383*54947Sheideman }
384*54947Sheideman 
385