154947Sheideman /* 263248Sbostic * Copyright (c) 1992, 1993 363248Sbostic * The Regents of the University of California. All rights reserved. 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 * 11*65491Spendry * @(#)umap_subr.c 8.4 (Berkeley) 01/05/94 1254947Sheideman * 13*65491Spendry * $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> 2455031Smckusick #include <miscfs/umapfs/umap.h> 2554947Sheideman 2654947Sheideman #define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */ 2754947Sheideman #define NUMAPNODECACHE 16 28*65491Spendry #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) 67*65491Spendry struct vnode *targetvp; 6854947Sheideman { 6955031Smckusick 7054947Sheideman return (&umap_node_cache[UMAP_NHASH(targetvp)]); 7154947Sheideman } 7254947Sheideman 7354947Sheideman /* 74*65491Spendry * umap_findid is called by various routines in umap_vnodeops.c to 75*65491Spendry * find a user or group id in a map. 76*65491Spendry */ 77*65491Spendry static u_long 78*65491Spendry umap_findid(id, map, nentries) 79*65491Spendry u_long id; 80*65491Spendry u_long map[][2]; 81*65491Spendry int nentries; 82*65491Spendry { 83*65491Spendry int i; 84*65491Spendry 85*65491Spendry /* Find uid entry in map */ 86*65491Spendry i = 0; 87*65491Spendry while ((i<nentries) && ((map[i][0]) != id)) 88*65491Spendry i++; 89*65491Spendry 90*65491Spendry if (i < nentries) 91*65491Spendry return (map[i][1]); 92*65491Spendry else 93*65491Spendry return (-1); 94*65491Spendry 95*65491Spendry } 96*65491Spendry 97*65491Spendry /* 98*65491Spendry * umap_reverse_findid is called by umap_getattr() in umap_vnodeops.c to 99*65491Spendry * find a user or group id in a map, in reverse. 100*65491Spendry */ 101*65491Spendry u_long 102*65491Spendry umap_reverse_findid(id, map, nentries) 103*65491Spendry u_long id; 104*65491Spendry u_long map[][2]; 105*65491Spendry int nentries; 106*65491Spendry { 107*65491Spendry int i; 108*65491Spendry 109*65491Spendry /* Find uid entry in map */ 110*65491Spendry i = 0; 111*65491Spendry while ((i<nentries) && ((map[i][1]) != id)) 112*65491Spendry i++; 113*65491Spendry 114*65491Spendry if (i < nentries) 115*65491Spendry return (map[i][0]); 116*65491Spendry else 117*65491Spendry return (-1); 118*65491Spendry 119*65491Spendry } 120*65491Spendry 121*65491Spendry /* 12254947Sheideman * Return alias for target vnode if already exists, else 0. 12354947Sheideman */ 12454958Sheideman static struct vnode * 12554947Sheideman umap_node_find(mp, targetvp) 12654947Sheideman struct mount *mp; 12754947Sheideman struct vnode *targetvp; 12854947Sheideman { 12954947Sheideman struct umap_node_cache *hd; 13054947Sheideman struct umap_node *a; 13154958Sheideman struct vnode *vp; 13254947Sheideman 13354947Sheideman #ifdef UMAPFS_DIAGNOSTIC 13454947Sheideman printf("umap_node_find(mp = %x, target = %x)\n", mp, targetvp); 13554947Sheideman #endif 13654947Sheideman 13754947Sheideman /* 13854947Sheideman * Find hash base, and then search the (two-way) linked 13954947Sheideman * list looking for a umap_node structure which is referencing 14054947Sheideman * the target vnode. If found, the increment the umap_node 14154947Sheideman * reference count (but NOT the target vnode's VREF counter). 14254947Sheideman */ 14354947Sheideman hd = umap_node_hash(targetvp); 14454947Sheideman 14554958Sheideman loop: 14654947Sheideman for (a = hd->ac_forw; a != (struct umap_node *) hd; a = a->umap_forw) { 14755031Smckusick if (a->umap_lowervp == targetvp && 14855031Smckusick a->umap_vnode->v_mount == mp) { 14954958Sheideman vp = UMAPTOV(a); 15054958Sheideman /* 15154958Sheideman * We need vget for the VXLOCK 15254958Sheideman * stuff, but we don't want to lock 15354958Sheideman * the lower node. 15454958Sheideman */ 15565132Smckusick if (vget(vp, 0)) { 156*65491Spendry #ifdef UMAPFS_DIAGNOSTIC 157*65491Spendry printf ("umap_node_find: vget failed.\n"); 158*65491Spendry #endif 15954958Sheideman goto loop; 16055031Smckusick } 16154958Sheideman return (vp); 16254947Sheideman } 16354947Sheideman } 16454947Sheideman 16554947Sheideman #ifdef UMAPFS_DIAGNOSTIC 16654947Sheideman printf("umap_node_find(%x, %x): NOT found\n", mp, targetvp); 16754947Sheideman #endif 16854947Sheideman 16954947Sheideman return (0); 17054947Sheideman } 17154947Sheideman 17254947Sheideman /* 17354958Sheideman * Make a new umap_node node. 17454958Sheideman * Vp is the alias vnode, lofsvp is the target vnode. 17554958Sheideman * Maintain a reference to (targetvp). 17654958Sheideman */ 17754958Sheideman static int 17854958Sheideman umap_node_alloc(mp, lowervp, vpp) 17954958Sheideman struct mount *mp; 18054958Sheideman struct vnode *lowervp; 18154958Sheideman struct vnode **vpp; 18254958Sheideman { 18354958Sheideman struct umap_node_cache *hd; 18454958Sheideman struct umap_node *xp; 18554958Sheideman struct vnode *othervp, *vp; 18654958Sheideman int error; 18754958Sheideman 18865423Spendry if (error = getnewvnode(VT_UMAP, mp, umap_vnodeop_p, vpp)) 18965423Spendry return (error); 19054958Sheideman vp = *vpp; 19154958Sheideman 19255031Smckusick MALLOC(xp, struct umap_node *, sizeof(struct umap_node), 19355031Smckusick M_TEMP, M_WAITOK); 19454958Sheideman vp->v_type = lowervp->v_type; 19554958Sheideman xp->umap_vnode = vp; 19654958Sheideman vp->v_data = xp; 19754958Sheideman xp->umap_lowervp = lowervp; 19854958Sheideman /* 19954958Sheideman * Before we insert our new node onto the hash chains, 20054958Sheideman * check to see if someone else has beaten us to it. 20154958Sheideman * (We could have slept in MALLOC.) 20254958Sheideman */ 20354958Sheideman if (othervp = umap_node_find(lowervp)) { 20454958Sheideman FREE(xp, M_TEMP); 20554958Sheideman vp->v_type = VBAD; /* node is discarded */ 20654958Sheideman vp->v_usecount = 0; /* XXX */ 20754958Sheideman *vpp = othervp; 20855031Smckusick return (0); 20955031Smckusick } 21054958Sheideman VREF(lowervp); /* Extra VREF will be vrele'd in umap_node_create */ 21154958Sheideman hd = umap_node_hash(lowervp); 21254958Sheideman insque(xp, hd); 21355031Smckusick return (0); 21454958Sheideman } 21554958Sheideman 21654958Sheideman 21754958Sheideman /* 21854947Sheideman * Try to find an existing umap_node vnode refering 21954947Sheideman * to it, otherwise make a new umap_node vnode which 22054947Sheideman * contains a reference to the target vnode. 22154947Sheideman */ 22254947Sheideman int 22354947Sheideman umap_node_create(mp, targetvp, newvpp) 22454947Sheideman struct mount *mp; 22554947Sheideman struct vnode *targetvp; 22654947Sheideman struct vnode **newvpp; 22754947Sheideman { 22854947Sheideman struct vnode *aliasvp; 22954947Sheideman 23054958Sheideman if (aliasvp = umap_node_find(mp, targetvp)) { 23154947Sheideman /* 23254947Sheideman * Take another reference to the alias vnode 23354947Sheideman */ 23454947Sheideman #ifdef UMAPFS_DIAGNOSTIC 23554947Sheideman vprint("umap_node_create: exists", ap->umap_vnode); 23654947Sheideman #endif 23754958Sheideman /* VREF(aliasvp); */ 23854947Sheideman } else { 23954947Sheideman int error; 24054947Sheideman 24154947Sheideman /* 24254947Sheideman * Get new vnode. 24354947Sheideman */ 24454947Sheideman #ifdef UMAPFS_DIAGNOSTIC 24554947Sheideman printf("umap_node_create: create new alias vnode\n"); 24654947Sheideman #endif 24754947Sheideman /* 24854947Sheideman * Make new vnode reference the umap_node. 24954947Sheideman */ 25054958Sheideman if (error = umap_node_alloc(mp, targetvp, &aliasvp)) 25155031Smckusick return (error); 25254947Sheideman 25354947Sheideman /* 25454947Sheideman * aliasvp is already VREF'd by getnewvnode() 25554947Sheideman */ 25654947Sheideman } 25754947Sheideman 25854947Sheideman vrele(targetvp); 25954947Sheideman 26054947Sheideman #ifdef UMAPFS_DIAGNOSTIC 26154947Sheideman vprint("umap_node_create: alias", aliasvp); 26254947Sheideman vprint("umap_node_create: target", targetvp); 26354947Sheideman #endif 26454947Sheideman 26554947Sheideman *newvpp = aliasvp; 26654947Sheideman return (0); 26754947Sheideman } 26855031Smckusick 26954947Sheideman #ifdef UMAPFS_DIAGNOSTIC 27054947Sheideman int umap_checkvp_barrier = 1; 27154947Sheideman struct vnode * 27254947Sheideman umap_checkvp(vp, fil, lno) 27354947Sheideman struct vnode *vp; 27454947Sheideman char *fil; 27554947Sheideman int lno; 27654947Sheideman { 27754947Sheideman struct umap_node *a = VTOUMAP(vp); 27854947Sheideman #if 0 27954947Sheideman /* 28054947Sheideman * Can't do this check because vop_reclaim runs 28154947Sheideman * with funny vop vector. 28254947Sheideman */ 28354947Sheideman if (vp->v_op != umap_vnodeop_p) { 28454947Sheideman printf ("umap_checkvp: on non-umap-node\n"); 28554947Sheideman while (umap_checkvp_barrier) /*WAIT*/ ; 28654947Sheideman panic("umap_checkvp"); 28755031Smckusick } 28854947Sheideman #endif 28954947Sheideman if (a->umap_lowervp == NULL) { 29054947Sheideman /* Should never happen */ 29154947Sheideman int i; u_long *p; 29254947Sheideman printf("vp = %x, ZERO ptr\n", vp); 29354947Sheideman for (p = (u_long *) a, i = 0; i < 8; i++) 29454947Sheideman printf(" %x", p[i]); 29554947Sheideman printf("\n"); 29654947Sheideman /* wait for debugger */ 29754947Sheideman while (umap_checkvp_barrier) /*WAIT*/ ; 29854947Sheideman panic("umap_checkvp"); 29954947Sheideman } 30054947Sheideman if (a->umap_lowervp->v_usecount < 1) { 30154947Sheideman int i; u_long *p; 30254947Sheideman printf("vp = %x, unref'ed lowervp\n", vp); 30354947Sheideman for (p = (u_long *) a, i = 0; i < 8; i++) 30454947Sheideman printf(" %x", p[i]); 30554947Sheideman printf("\n"); 30654947Sheideman /* wait for debugger */ 30754947Sheideman while (umap_checkvp_barrier) /*WAIT*/ ; 30854947Sheideman panic ("umap with unref'ed lowervp"); 30955031Smckusick } 31054947Sheideman #if 0 31154947Sheideman printf("umap %x/%d -> %x/%d [%s, %d]\n", 31254947Sheideman a->umap_vnode, a->umap_vnode->v_usecount, 31354947Sheideman a->umap_lowervp, a->umap_lowervp->v_usecount, 31454947Sheideman fil, lno); 31554947Sheideman #endif 31655031Smckusick return (a->umap_lowervp); 31754947Sheideman } 31854947Sheideman #endif 31954947Sheideman 32054947Sheideman /* umap_mapids maps all of the ids in a credential, both user and group. */ 32154947Sheideman 322*65491Spendry void 323*65491Spendry umap_mapids(v_mount, credp) 32454958Sheideman struct mount *v_mount; 32554947Sheideman struct ucred *credp; 32654947Sheideman { 327*65491Spendry int i, unentries, gnentries, *groupmap, *usermap; 328*65491Spendry uid_t uid; 329*65491Spendry gid_t gid; 33054947Sheideman 33154958Sheideman unentries = MOUNTTOUMAPMOUNT(v_mount)->info_nentries; 33254958Sheideman usermap = &(MOUNTTOUMAPMOUNT(v_mount)->info_mapdata[0][0]); 33354958Sheideman gnentries = MOUNTTOUMAPMOUNT(v_mount)->info_gnentries; 33454958Sheideman groupmap = &(MOUNTTOUMAPMOUNT(v_mount)->info_gmapdata[0][0]); 33554958Sheideman 33654947Sheideman /* Find uid entry in map */ 33754947Sheideman 338*65491Spendry uid = (uid_t) umap_findid(credp->cr_uid, usermap, unentries); 33954947Sheideman 340*65491Spendry if (uid != -1) 341*65491Spendry credp->cr_uid = uid; 342*65491Spendry else 343*65491Spendry credp->cr_uid = (uid_t) NOBODY; 34454947Sheideman 345*65491Spendry #ifdef notdef 346*65491Spendry /* cr_gid is the same as cr_groups[0] in 4BSD */ 347*65491Spendry 34854947Sheideman /* Find gid entry in map */ 34954947Sheideman 350*65491Spendry gid = (gid_t) umap_findid(credp->cr_gid, groupmap, gnentries); 35154947Sheideman 352*65491Spendry if (gid != -1) 353*65491Spendry credp->cr_gid = gid; 354*65491Spendry else 355*65491Spendry credp->cr_gid = NULLGROUP; 356*65491Spendry #endif 35754947Sheideman 35854947Sheideman /* Now we must map each of the set of groups in the cr_groups 35954947Sheideman structure. */ 36054947Sheideman 36154947Sheideman i = 0; 362*65491Spendry while (credp->cr_groups[i] != 0) { 363*65491Spendry gid = (gid_t) umap_findid(credp->cr_groups[i], 364*65491Spendry groupmap, gnentries); 365*65491Spendry 366*65491Spendry if (gid != -1) 367*65491Spendry credp->cr_groups[i++] = gid; 36854947Sheideman else 369*65491Spendry credp->cr_groups[i++] = NULLGROUP; 37054947Sheideman } 37154947Sheideman } 372