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