154947Sheideman /* 254947Sheideman * Copyright (c) 1992 The Regents of the University of California 354947Sheideman * Copyright (c) 1990, 1992 Jan-Simon Pendry 454947Sheideman * All rights reserved. 554947Sheideman * 654947Sheideman * This code is derived from software donated to Berkeley by 754947Sheideman * Jan-Simon Pendry. 854947Sheideman * 954947Sheideman * %sccs.include.redist.c% 1054947Sheideman * 1154947Sheideman * @(#)lofs_subr.c 1.2 (Berkeley) 6/18/92 1254947Sheideman * 1354947Sheideman * $Id: lofs_subr.c,v 1.11 1992/05/30 10:05:43 jsp Exp jsp $ 1454947Sheideman */ 1554947Sheideman 1654947Sheideman #include <sys/param.h> 1754947Sheideman #include <sys/systm.h> 1854947Sheideman #include <sys/time.h> 1954947Sheideman #include <sys/types.h> 2054947Sheideman #include <sys/vnode.h> 2154947Sheideman #include <sys/mount.h> 2254947Sheideman #include <sys/namei.h> 2354947Sheideman #include <sys/malloc.h> 2454947Sheideman #include <umapfs/umap.h> 2554947Sheideman 2654947Sheideman #define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */ 2754947Sheideman #define NUMAPNODECACHE 16 2854947Sheideman #define UMAP_NHASH(vp) ((((u_long)vp)>>LOG2_SIZEVNODE) & (NUMAPNODECACHE-1)) 2954947Sheideman 3054947Sheideman /* 3154947Sheideman * Null layer cache: 3254947Sheideman * Each cache entry holds a reference to the target vnode 3354947Sheideman * along with a pointer to the alias vnode. When an 3454947Sheideman * entry is added the target vnode is VREF'd. When the 3554947Sheideman * alias is removed the target vnode is vrele'd. 3654947Sheideman */ 3754947Sheideman 3854947Sheideman /* 3954947Sheideman * Cache head 4054947Sheideman */ 4154947Sheideman struct umap_node_cache { 4254947Sheideman struct umap_node *ac_forw; 4354947Sheideman struct umap_node *ac_back; 4454947Sheideman }; 4554947Sheideman 4654947Sheideman static struct umap_node_cache umap_node_cache[NUMAPNODECACHE]; 4754947Sheideman 4854947Sheideman /* 4954947Sheideman * Initialise cache headers 5054947Sheideman */ 5154947Sheideman umapfs_init() 5254947Sheideman { 5354947Sheideman struct umap_node_cache *ac; 5454947Sheideman #ifdef UMAPFS_DIAGNOSTIC 5554947Sheideman printf("umapfs_init\n"); /* printed during system boot */ 5654947Sheideman #endif 5754947Sheideman 5854947Sheideman for (ac = umap_node_cache; ac < umap_node_cache + NUMAPNODECACHE; ac++) 5954947Sheideman ac->ac_forw = ac->ac_back = (struct umap_node *) ac; 6054947Sheideman } 6154947Sheideman 6254947Sheideman /* 6354947Sheideman * Compute hash list for given target vnode 6454947Sheideman */ 6554947Sheideman static struct umap_node_cache * 6654947Sheideman umap_node_hash(targetvp) 6754947Sheideman struct vnode *targetvp; 6854947Sheideman { 6954947Sheideman return (&umap_node_cache[UMAP_NHASH(targetvp)]); 7054947Sheideman } 7154947Sheideman 7254947Sheideman /* 7354947Sheideman * Return alias for target vnode if already exists, else 0. 7454947Sheideman */ 75*54958Sheideman static struct vnode * 7654947Sheideman umap_node_find(mp, targetvp) 7754947Sheideman struct mount *mp; 7854947Sheideman struct vnode *targetvp; 7954947Sheideman { 8054947Sheideman struct umap_node_cache *hd; 8154947Sheideman struct umap_node *a; 82*54958Sheideman struct vnode *vp; 8354947Sheideman 8454947Sheideman #ifdef UMAPFS_DIAGNOSTIC 8554947Sheideman printf("umap_node_find(mp = %x, target = %x)\n", mp, targetvp); 8654947Sheideman #endif 8754947Sheideman 8854947Sheideman /* 8954947Sheideman * Find hash base, and then search the (two-way) linked 9054947Sheideman * list looking for a umap_node structure which is referencing 9154947Sheideman * the target vnode. If found, the increment the umap_node 9254947Sheideman * reference count (but NOT the target vnode's VREF counter). 9354947Sheideman */ 9454947Sheideman hd = umap_node_hash(targetvp); 9554947Sheideman 96*54958Sheideman loop: 9754947Sheideman for (a = hd->ac_forw; a != (struct umap_node *) hd; a = a->umap_forw) { 9854947Sheideman if (a->umap_lowervp == targetvp && a->umap_vnode->v_mount == mp) { 99*54958Sheideman vp = UMAPTOV(a); 100*54958Sheideman /* 101*54958Sheideman * We need vget for the VXLOCK 102*54958Sheideman * stuff, but we don't want to lock 103*54958Sheideman * the lower node. 104*54958Sheideman */ 105*54958Sheideman if (vget_nolock(vp)) { 106*54958Sheideman printf ("null_node_find: vget failed.\n"); 107*54958Sheideman goto loop; 108*54958Sheideman }; 109*54958Sheideman return (vp); 11054947Sheideman } 11154947Sheideman } 11254947Sheideman 11354947Sheideman #ifdef UMAPFS_DIAGNOSTIC 11454947Sheideman printf("umap_node_find(%x, %x): NOT found\n", mp, targetvp); 11554947Sheideman #endif 11654947Sheideman 11754947Sheideman return (0); 11854947Sheideman } 11954947Sheideman 12054947Sheideman /* 121*54958Sheideman * Make a new umap_node node. 122*54958Sheideman * Vp is the alias vnode, lofsvp is the target vnode. 123*54958Sheideman * Maintain a reference to (targetvp). 124*54958Sheideman */ 125*54958Sheideman static int 126*54958Sheideman umap_node_alloc(mp, lowervp, vpp) 127*54958Sheideman struct mount *mp; 128*54958Sheideman struct vnode *lowervp; 129*54958Sheideman struct vnode **vpp; 130*54958Sheideman { 131*54958Sheideman struct umap_node_cache *hd; 132*54958Sheideman struct umap_node *xp; 133*54958Sheideman struct vnode *othervp, *vp; 134*54958Sheideman int error; 135*54958Sheideman 136*54958Sheideman if (error = getnewvnode(VT_UFS, mp, umap_vnodeop_p, vpp)) 137*54958Sheideman return (error); /* XXX: VT_UMAP above */ 138*54958Sheideman vp = *vpp; 139*54958Sheideman 140*54958Sheideman MALLOC(xp, struct umap_node *, sizeof(struct umap_node), M_TEMP, M_WAITOK); 141*54958Sheideman vp->v_type = lowervp->v_type; 142*54958Sheideman xp->umap_vnode = vp; 143*54958Sheideman vp->v_data = xp; 144*54958Sheideman xp->umap_lowervp = lowervp; 145*54958Sheideman /* 146*54958Sheideman * Before we insert our new node onto the hash chains, 147*54958Sheideman * check to see if someone else has beaten us to it. 148*54958Sheideman * (We could have slept in MALLOC.) 149*54958Sheideman */ 150*54958Sheideman if (othervp = umap_node_find(lowervp)) { 151*54958Sheideman FREE(xp, M_TEMP); 152*54958Sheideman vp->v_type = VBAD; /* node is discarded */ 153*54958Sheideman vp->v_usecount = 0; /* XXX */ 154*54958Sheideman *vpp = othervp; 155*54958Sheideman return 0; 156*54958Sheideman }; 157*54958Sheideman VREF(lowervp); /* Extra VREF will be vrele'd in umap_node_create */ 158*54958Sheideman hd = umap_node_hash(lowervp); 159*54958Sheideman insque(xp, hd); 160*54958Sheideman return 0; 161*54958Sheideman } 162*54958Sheideman 163*54958Sheideman 164*54958Sheideman /* 16554947Sheideman * Try to find an existing umap_node vnode refering 16654947Sheideman * to it, otherwise make a new umap_node vnode which 16754947Sheideman * contains a reference to the target vnode. 16854947Sheideman */ 16954947Sheideman int 17054947Sheideman umap_node_create(mp, targetvp, newvpp) 17154947Sheideman struct mount *mp; 17254947Sheideman struct vnode *targetvp; 17354947Sheideman struct vnode **newvpp; 17454947Sheideman { 17554947Sheideman struct vnode *aliasvp; 17654947Sheideman 177*54958Sheideman if (aliasvp = umap_node_find(mp, targetvp)) { 17854947Sheideman /* 17954947Sheideman * Take another reference to the alias vnode 18054947Sheideman */ 18154947Sheideman #ifdef UMAPFS_DIAGNOSTIC 18254947Sheideman vprint("umap_node_create: exists", ap->umap_vnode); 18354947Sheideman #endif 184*54958Sheideman /* VREF(aliasvp); */ 18554947Sheideman } else { 18654947Sheideman int error; 18754947Sheideman 18854947Sheideman /* 18954947Sheideman * Get new vnode. 19054947Sheideman */ 19154947Sheideman #ifdef UMAPFS_DIAGNOSTIC 19254947Sheideman printf("umap_node_create: create new alias vnode\n"); 19354947Sheideman #endif 19454947Sheideman /* 19554947Sheideman * Make new vnode reference the umap_node. 19654947Sheideman */ 197*54958Sheideman if (error = umap_node_alloc(mp, targetvp, &aliasvp)) 198*54958Sheideman return error; 19954947Sheideman 20054947Sheideman /* 20154947Sheideman * aliasvp is already VREF'd by getnewvnode() 20254947Sheideman */ 20354947Sheideman } 20454947Sheideman 20554947Sheideman vrele(targetvp); 20654947Sheideman 20754947Sheideman #ifdef UMAPFS_DIAGNOSTIC 20854947Sheideman vprint("umap_node_create: alias", aliasvp); 20954947Sheideman vprint("umap_node_create: target", targetvp); 21054947Sheideman #endif 21154947Sheideman 21254947Sheideman *newvpp = aliasvp; 21354947Sheideman return (0); 21454947Sheideman } 21554947Sheideman #ifdef UMAPFS_DIAGNOSTIC 21654947Sheideman int umap_checkvp_barrier = 1; 21754947Sheideman struct vnode * 21854947Sheideman umap_checkvp(vp, fil, lno) 21954947Sheideman struct vnode *vp; 22054947Sheideman char *fil; 22154947Sheideman int lno; 22254947Sheideman { 22354947Sheideman struct umap_node *a = VTOUMAP(vp); 22454947Sheideman #if 0 22554947Sheideman /* 22654947Sheideman * Can't do this check because vop_reclaim runs 22754947Sheideman * with funny vop vector. 22854947Sheideman */ 22954947Sheideman if (vp->v_op != umap_vnodeop_p) { 23054947Sheideman printf ("umap_checkvp: on non-umap-node\n"); 23154947Sheideman while (umap_checkvp_barrier) /*WAIT*/ ; 23254947Sheideman panic("umap_checkvp"); 23354947Sheideman }; 23454947Sheideman #endif 23554947Sheideman if (a->umap_lowervp == NULL) { 23654947Sheideman /* Should never happen */ 23754947Sheideman int i; u_long *p; 23854947Sheideman printf("vp = %x, ZERO ptr\n", vp); 23954947Sheideman for (p = (u_long *) a, i = 0; i < 8; i++) 24054947Sheideman printf(" %x", p[i]); 24154947Sheideman printf("\n"); 24254947Sheideman /* wait for debugger */ 24354947Sheideman while (umap_checkvp_barrier) /*WAIT*/ ; 24454947Sheideman panic("umap_checkvp"); 24554947Sheideman } 24654947Sheideman if (a->umap_lowervp->v_usecount < 1) { 24754947Sheideman int i; u_long *p; 24854947Sheideman printf("vp = %x, unref'ed lowervp\n", vp); 24954947Sheideman for (p = (u_long *) a, i = 0; i < 8; i++) 25054947Sheideman printf(" %x", p[i]); 25154947Sheideman printf("\n"); 25254947Sheideman /* wait for debugger */ 25354947Sheideman while (umap_checkvp_barrier) /*WAIT*/ ; 25454947Sheideman panic ("umap with unref'ed lowervp"); 25554947Sheideman }; 25654947Sheideman #if 0 25754947Sheideman printf("umap %x/%d -> %x/%d [%s, %d]\n", 25854947Sheideman a->umap_vnode, a->umap_vnode->v_usecount, 25954947Sheideman a->umap_lowervp, a->umap_lowervp->v_usecount, 26054947Sheideman fil, lno); 26154947Sheideman #endif 26254947Sheideman return a->umap_lowervp; 26354947Sheideman } 26454947Sheideman #endif 26554947Sheideman 26654947Sheideman /* umap_mapids maps all of the ids in a credential, both user and group. */ 26754947Sheideman 268*54958Sheideman umap_mapids(v_mount,credp) 269*54958Sheideman struct mount *v_mount; 27054947Sheideman struct ucred *credp; 27154947Sheideman { 272*54958Sheideman int i,gid,uid,unentries,gnentries,*groupmap,*usermap; 27354947Sheideman 274*54958Sheideman unentries = MOUNTTOUMAPMOUNT(v_mount)->info_nentries; 275*54958Sheideman usermap = &(MOUNTTOUMAPMOUNT(v_mount)->info_mapdata[0][0]); 276*54958Sheideman gnentries = MOUNTTOUMAPMOUNT(v_mount)->info_gnentries; 277*54958Sheideman groupmap = &(MOUNTTOUMAPMOUNT(v_mount)->info_gmapdata[0][0]); 278*54958Sheideman 27954947Sheideman /* Find uid entry in map */ 28054947Sheideman 28154947Sheideman uid = umap_findid(credp->cr_uid,usermap,unentries); 28254947Sheideman 28354947Sheideman if (uid != -1) { 28454947Sheideman credp->cr_uid = 28554947Sheideman (u_short)uid; 28654947Sheideman } else 287*54958Sheideman credp->cr_uid = (u_short)NOBODY; 28854947Sheideman 28954947Sheideman /* Find gid entry in map */ 29054947Sheideman 29154947Sheideman gid = umap_findid(credp->cr_gid,groupmap,gnentries); 29254947Sheideman 29354947Sheideman if (gid != -1) { 29454947Sheideman credp->cr_gid = 29554947Sheideman (u_short)gid; 29654947Sheideman } else 297*54958Sheideman credp->cr_gid = (u_short)NULLGROUP; 29854947Sheideman 29954947Sheideman /* Now we must map each of the set of groups in the cr_groups 30054947Sheideman structure. */ 30154947Sheideman 30254947Sheideman i = 0; 30354947Sheideman while (credp->cr_groups[i] != 0) 30454947Sheideman { 30554947Sheideman gid = umap_findid(credp->cr_groups[i],groupmap, 30654947Sheideman gnentries); 30754947Sheideman 30854947Sheideman if (gid != -1) 30954947Sheideman credp->cr_groups[i++] = (u_short)gid; 31054947Sheideman else 31154947Sheideman credp->cr_groups[i++] = (u_short)NULLGROUP; 31254947Sheideman 31354947Sheideman } 31454947Sheideman } 31554947Sheideman 31654947Sheideman /* umap_findid is called by various routines in umap_vnodeops.c to 31754947Sheideman * find a user or group id in a map. 31854947Sheideman */ 31954947Sheideman 32054947Sheideman umap_findid(id,map,nentries) 32154947Sheideman ushort id; 32254947Sheideman int map[][2]; 32354947Sheideman int nentries; 32454947Sheideman { 32554947Sheideman int i; 32654947Sheideman 32754947Sheideman /* Find uid entry in map */ 32854947Sheideman i = 0; 32954947Sheideman while ((i<nentries) && ((u_short)(map[i][0] ) != id)) 33054947Sheideman i++; 33154947Sheideman 33254947Sheideman if ( i < nentries ) 33354947Sheideman return (map[i][1]); 33454947Sheideman else 33554947Sheideman return (-1); 33654947Sheideman 33754947Sheideman } 33854947Sheideman 33954947Sheideman /* umap_reverse_findid is called by umap_getattr() in umap_vnodeops.c to 34054947Sheideman * find a user or group id in a map, in reverse. 34154947Sheideman */ 34254947Sheideman 34354947Sheideman umap_reverse_findid(id,map,nentries) 34454947Sheideman ushort id; 34554947Sheideman int map[][2]; 34654947Sheideman int nentries; 34754947Sheideman { 34854947Sheideman int i; 34954947Sheideman 35054947Sheideman /* Find uid entry in map */ 35154947Sheideman i = 0; 35254947Sheideman while ((i<nentries) && ((u_short)(map[i][1] ) != id)) 35354947Sheideman i++; 35454947Sheideman 35554947Sheideman if ( i < nentries ) 35654947Sheideman return (map[i][0]); 35754947Sheideman else 35854947Sheideman return (-1); 35954947Sheideman 36054947Sheideman } 36154947Sheideman 362