correct type for umap_init
[unix-history] / usr / src / sys / miscfs / umapfs / umap_subr.c
CommitLineData
461c058b 1/*
1446b03c
KB
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
461c058b
JH
4 *
5 * This code is derived from software donated to Berkeley by
6 * Jan-Simon Pendry.
7 *
8 * %sccs.include.redist.c%
9 *
5fcc2bf1 10 * @(#)umap_subr.c 8.8 (Berkeley) %G%
461c058b 11 *
c5fead24 12 * $Id: lofs_subr.c, v 1.11 1992/05/30 10:05:43 jsp Exp jsp $
461c058b
JH
13 */
14
15#include <sys/param.h>
16#include <sys/systm.h>
17#include <sys/time.h>
18#include <sys/types.h>
19#include <sys/vnode.h>
20#include <sys/mount.h>
21#include <sys/namei.h>
22#include <sys/malloc.h>
fb250c6b 23#include <miscfs/umapfs/umap.h>
461c058b
JH
24
25#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
26#define NUMAPNODECACHE 16
461c058b
JH
27
28/*
29 * Null layer cache:
30 * Each cache entry holds a reference to the target vnode
31 * along with a pointer to the alias vnode. When an
32 * entry is added the target vnode is VREF'd. When the
33 * alias is removed the target vnode is vrele'd.
34 */
35
a22f86d4
KM
36#define UMAP_NHASH(vp) \
37 (&umap_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & umap_node_hash])
38LIST_HEAD(umap_node_hashhead, umap_node) *umap_node_hashtbl;
39u_long umap_node_hash;
461c058b
JH
40
41/*
42 * Initialise cache headers
43 */
5fcc2bf1
KM
44umapfs_init(vfsp)
45 struct vfsconf *vfsp;
461c058b 46{
a22f86d4 47
461c058b
JH
48#ifdef UMAPFS_DIAGNOSTIC
49 printf("umapfs_init\n"); /* printed during system boot */
50#endif
a22f86d4 51 umap_node_hashtbl = hashinit(NUMAPNODECACHE, M_CACHE, &umap_node_hash);
461c058b
JH
52}
53
c5fead24
JSP
54/*
55 * umap_findid is called by various routines in umap_vnodeops.c to
56 * find a user or group id in a map.
57 */
58static u_long
59umap_findid(id, map, nentries)
60 u_long id;
61 u_long map[][2];
62 int nentries;
63{
64 int i;
65
66 /* Find uid entry in map */
67 i = 0;
68 while ((i<nentries) && ((map[i][0]) != id))
69 i++;
70
71 if (i < nentries)
72 return (map[i][1]);
73 else
74 return (-1);
75
76}
77
78/*
79 * umap_reverse_findid is called by umap_getattr() in umap_vnodeops.c to
80 * find a user or group id in a map, in reverse.
81 */
82u_long
83umap_reverse_findid(id, map, nentries)
84 u_long id;
85 u_long map[][2];
86 int nentries;
87{
88 int i;
89
90 /* Find uid entry in map */
91 i = 0;
92 while ((i<nentries) && ((map[i][1]) != id))
93 i++;
94
95 if (i < nentries)
96 return (map[i][0]);
97 else
98 return (-1);
99
100}
101
461c058b
JH
102/*
103 * Return alias for target vnode if already exists, else 0.
104 */
e0851395 105static struct vnode *
461c058b
JH
106umap_node_find(mp, targetvp)
107 struct mount *mp;
108 struct vnode *targetvp;
109{
a22f86d4 110 struct umap_node_hashhead *hd;
461c058b 111 struct umap_node *a;
e0851395 112 struct vnode *vp;
461c058b
JH
113
114#ifdef UMAPFS_DIAGNOSTIC
115 printf("umap_node_find(mp = %x, target = %x)\n", mp, targetvp);
116#endif
117
118 /*
119 * Find hash base, and then search the (two-way) linked
120 * list looking for a umap_node structure which is referencing
121 * the target vnode. If found, the increment the umap_node
122 * reference count (but NOT the target vnode's VREF counter).
123 */
a22f86d4
KM
124 hd = UMAP_NHASH(targetvp);
125loop:
126 for (a = hd->lh_first; a != 0; a = a->umap_hash.le_next) {
fb250c6b
KM
127 if (a->umap_lowervp == targetvp &&
128 a->umap_vnode->v_mount == mp) {
e0851395
JH
129 vp = UMAPTOV(a);
130 /*
131 * We need vget for the VXLOCK
132 * stuff, but we don't want to lock
133 * the lower node.
134 */
da5aa0c7 135 if (vget(vp, 0)) {
c5fead24
JSP
136#ifdef UMAPFS_DIAGNOSTIC
137 printf ("umap_node_find: vget failed.\n");
138#endif
e0851395 139 goto loop;
fb250c6b 140 }
e0851395 141 return (vp);
461c058b
JH
142 }
143 }
144
145#ifdef UMAPFS_DIAGNOSTIC
146 printf("umap_node_find(%x, %x): NOT found\n", mp, targetvp);
147#endif
148
149 return (0);
150}
151
e0851395
JH
152/*
153 * Make a new umap_node node.
154 * Vp is the alias vnode, lofsvp is the target vnode.
155 * Maintain a reference to (targetvp).
156 */
157static int
158umap_node_alloc(mp, lowervp, vpp)
159 struct mount *mp;
160 struct vnode *lowervp;
161 struct vnode **vpp;
162{
a22f86d4 163 struct umap_node_hashhead *hd;
e0851395
JH
164 struct umap_node *xp;
165 struct vnode *othervp, *vp;
166 int error;
167
d11e18ff
JSP
168 if (error = getnewvnode(VT_UMAP, mp, umap_vnodeop_p, vpp))
169 return (error);
e0851395
JH
170 vp = *vpp;
171
fb250c6b
KM
172 MALLOC(xp, struct umap_node *, sizeof(struct umap_node),
173 M_TEMP, M_WAITOK);
e0851395
JH
174 vp->v_type = lowervp->v_type;
175 xp->umap_vnode = vp;
176 vp->v_data = xp;
177 xp->umap_lowervp = lowervp;
178 /*
179 * Before we insert our new node onto the hash chains,
180 * check to see if someone else has beaten us to it.
181 * (We could have slept in MALLOC.)
182 */
183 if (othervp = umap_node_find(lowervp)) {
184 FREE(xp, M_TEMP);
185 vp->v_type = VBAD; /* node is discarded */
186 vp->v_usecount = 0; /* XXX */
187 *vpp = othervp;
fb250c6b
KM
188 return (0);
189 }
e0851395 190 VREF(lowervp); /* Extra VREF will be vrele'd in umap_node_create */
a22f86d4
KM
191 hd = UMAP_NHASH(lowervp);
192 LIST_INSERT_HEAD(hd, xp, umap_hash);
fb250c6b 193 return (0);
e0851395
JH
194}
195
196
461c058b
JH
197/*
198 * Try to find an existing umap_node vnode refering
199 * to it, otherwise make a new umap_node vnode which
200 * contains a reference to the target vnode.
201 */
202int
203umap_node_create(mp, targetvp, newvpp)
204 struct mount *mp;
205 struct vnode *targetvp;
206 struct vnode **newvpp;
207{
461c058b
JH
208 struct vnode *aliasvp;
209
e0851395 210 if (aliasvp = umap_node_find(mp, targetvp)) {
461c058b
JH
211 /*
212 * Take another reference to the alias vnode
213 */
214#ifdef UMAPFS_DIAGNOSTIC
215 vprint("umap_node_create: exists", ap->umap_vnode);
216#endif
e0851395 217 /* VREF(aliasvp); */
461c058b
JH
218 } else {
219 int error;
220
221 /*
222 * Get new vnode.
223 */
224#ifdef UMAPFS_DIAGNOSTIC
225 printf("umap_node_create: create new alias vnode\n");
226#endif
461c058b
JH
227 /*
228 * Make new vnode reference the umap_node.
229 */
e0851395 230 if (error = umap_node_alloc(mp, targetvp, &aliasvp))
fb250c6b 231 return (error);
461c058b
JH
232
233 /*
234 * aliasvp is already VREF'd by getnewvnode()
235 */
236 }
237
238 vrele(targetvp);
239
240#ifdef UMAPFS_DIAGNOSTIC
241 vprint("umap_node_create: alias", aliasvp);
242 vprint("umap_node_create: target", targetvp);
243#endif
244
245 *newvpp = aliasvp;
246 return (0);
247}
fb250c6b 248
461c058b
JH
249#ifdef UMAPFS_DIAGNOSTIC
250int umap_checkvp_barrier = 1;
251struct vnode *
252umap_checkvp(vp, fil, lno)
253 struct vnode *vp;
254 char *fil;
255 int lno;
256{
257 struct umap_node *a = VTOUMAP(vp);
258#if 0
259 /*
260 * Can't do this check because vop_reclaim runs
261 * with funny vop vector.
262 */
263 if (vp->v_op != umap_vnodeop_p) {
264 printf ("umap_checkvp: on non-umap-node\n");
265 while (umap_checkvp_barrier) /*WAIT*/ ;
266 panic("umap_checkvp");
fb250c6b 267 }
461c058b
JH
268#endif
269 if (a->umap_lowervp == NULL) {
270 /* Should never happen */
271 int i; u_long *p;
272 printf("vp = %x, ZERO ptr\n", vp);
273 for (p = (u_long *) a, i = 0; i < 8; i++)
274 printf(" %x", p[i]);
275 printf("\n");
276 /* wait for debugger */
277 while (umap_checkvp_barrier) /*WAIT*/ ;
278 panic("umap_checkvp");
279 }
280 if (a->umap_lowervp->v_usecount < 1) {
281 int i; u_long *p;
282 printf("vp = %x, unref'ed lowervp\n", vp);
283 for (p = (u_long *) a, i = 0; i < 8; i++)
284 printf(" %x", p[i]);
285 printf("\n");
286 /* wait for debugger */
287 while (umap_checkvp_barrier) /*WAIT*/ ;
288 panic ("umap with unref'ed lowervp");
fb250c6b 289 }
461c058b
JH
290#if 0
291 printf("umap %x/%d -> %x/%d [%s, %d]\n",
292 a->umap_vnode, a->umap_vnode->v_usecount,
293 a->umap_lowervp, a->umap_lowervp->v_usecount,
294 fil, lno);
295#endif
fb250c6b 296 return (a->umap_lowervp);
461c058b
JH
297}
298#endif
299
300/* umap_mapids maps all of the ids in a credential, both user and group. */
301
c5fead24
JSP
302void
303umap_mapids(v_mount, credp)
e0851395 304 struct mount *v_mount;
461c058b 305 struct ucred *credp;
461c058b 306{
996f103b
KM
307 int i, unentries, gnentries;
308 u_long *groupmap, *usermap;
c5fead24
JSP
309 uid_t uid;
310 gid_t gid;
e0851395
JH
311
312 unentries = MOUNTTOUMAPMOUNT(v_mount)->info_nentries;
313 usermap = &(MOUNTTOUMAPMOUNT(v_mount)->info_mapdata[0][0]);
314 gnentries = MOUNTTOUMAPMOUNT(v_mount)->info_gnentries;
315 groupmap = &(MOUNTTOUMAPMOUNT(v_mount)->info_gmapdata[0][0]);
461c058b
JH
316
317 /* Find uid entry in map */
318
c5fead24
JSP
319 uid = (uid_t) umap_findid(credp->cr_uid, usermap, unentries);
320
321 if (uid != -1)
322 credp->cr_uid = uid;
323 else
324 credp->cr_uid = (uid_t) NOBODY;
461c058b 325
c5fead24
JSP
326#ifdef notdef
327 /* cr_gid is the same as cr_groups[0] in 4BSD */
461c058b
JH
328
329 /* Find gid entry in map */
330
c5fead24 331 gid = (gid_t) umap_findid(credp->cr_gid, groupmap, gnentries);
461c058b 332
c5fead24
JSP
333 if (gid != -1)
334 credp->cr_gid = gid;
335 else
336 credp->cr_gid = NULLGROUP;
337#endif
461c058b
JH
338
339 /* Now we must map each of the set of groups in the cr_groups
340 structure. */
341
342 i = 0;
c5fead24
JSP
343 while (credp->cr_groups[i] != 0) {
344 gid = (gid_t) umap_findid(credp->cr_groups[i],
345 groupmap, gnentries);
461c058b 346
c5fead24
JSP
347 if (gid != -1)
348 credp->cr_groups[i++] = gid;
349 else
350 credp->cr_groups[i++] = NULLGROUP;
461c058b
JH
351 }
352}