* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
* This code is derived from software donated to Berkeley by
* %sccs.include.redist.c%
* @(#)umap_subr.c 8.6 (Berkeley) %G%
* $Id: lofs_subr.c, v 1.11 1992/05/30 10:05:43 jsp Exp jsp $
#include <miscfs/umapfs/umap.h>
#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */
#define NUMAPNODECACHE 16
#define UMAP_NHASH(vp) ((((u_long) vp)>>LOG2_SIZEVNODE) & (NUMAPNODECACHE-1))
* Each cache entry holds a reference to the target vnode
* along with a pointer to the alias vnode. When an
* entry is added the target vnode is VREF'd. When the
* alias is removed the target vnode is vrele'd.
struct umap_node
*ac_forw
;
struct umap_node
*ac_back
;
static struct umap_node_cache umap_node_cache
[NUMAPNODECACHE
];
* Initialise cache headers
struct umap_node_cache
*ac
;
printf("umapfs_init\n"); /* printed during system boot */
for (ac
= umap_node_cache
; ac
< umap_node_cache
+ NUMAPNODECACHE
; ac
++)
ac
->ac_forw
= ac
->ac_back
= (struct umap_node
*) ac
;
* Compute hash list for given target vnode
static struct umap_node_cache
*
return (&umap_node_cache
[UMAP_NHASH(targetvp
)]);
* umap_findid is called by various routines in umap_vnodeops.c to
* find a user or group id in a map.
umap_findid(id
, map
, nentries
)
/* Find uid entry in map */
while ((i
<nentries
) && ((map
[i
][0]) != id
))
* umap_reverse_findid is called by umap_getattr() in umap_vnodeops.c to
* find a user or group id in a map, in reverse.
umap_reverse_findid(id
, map
, nentries
)
/* Find uid entry in map */
while ((i
<nentries
) && ((map
[i
][1]) != id
))
* Return alias for target vnode if already exists, else 0.
umap_node_find(mp
, targetvp
)
struct umap_node_cache
*hd
;
printf("umap_node_find(mp = %x, target = %x)\n", mp
, targetvp
);
* Find hash base, and then search the (two-way) linked
* list looking for a umap_node structure which is referencing
* the target vnode. If found, the increment the umap_node
* reference count (but NOT the target vnode's VREF counter).
hd
= umap_node_hash(targetvp
);
for (a
= hd
->ac_forw
; a
!= (struct umap_node
*) hd
; a
= a
->umap_forw
) {
if (a
->umap_lowervp
== targetvp
&&
a
->umap_vnode
->v_mount
== mp
) {
* We need vget for the VXLOCK
* stuff, but we don't want to lock
printf ("umap_node_find: vget failed.\n");
printf("umap_node_find(%x, %x): NOT found\n", mp
, targetvp
);
* Make a new umap_node node.
* Vp is the alias vnode, lofsvp is the target vnode.
* Maintain a reference to (targetvp).
umap_node_alloc(mp
, lowervp
, vpp
)
struct umap_node_cache
*hd
;
struct vnode
*othervp
, *vp
;
if (error
= getnewvnode(VT_UMAP
, mp
, umap_vnodeop_p
, vpp
))
MALLOC(xp
, struct umap_node
*, sizeof(struct umap_node
),
vp
->v_type
= lowervp
->v_type
;
xp
->umap_lowervp
= lowervp
;
* Before we insert our new node onto the hash chains,
* check to see if someone else has beaten us to it.
* (We could have slept in MALLOC.)
if (othervp
= umap_node_find(lowervp
)) {
vp
->v_type
= VBAD
; /* node is discarded */
vp
->v_usecount
= 0; /* XXX */
VREF(lowervp
); /* Extra VREF will be vrele'd in umap_node_create */
hd
= umap_node_hash(lowervp
);
* Try to find an existing umap_node vnode refering
* to it, otherwise make a new umap_node vnode which
* contains a reference to the target vnode.
umap_node_create(mp
, targetvp
, newvpp
)
if (aliasvp
= umap_node_find(mp
, targetvp
)) {
* Take another reference to the alias vnode
vprint("umap_node_create: exists", ap
->umap_vnode
);
printf("umap_node_create: create new alias vnode\n");
* Make new vnode reference the umap_node.
if (error
= umap_node_alloc(mp
, targetvp
, &aliasvp
))
* aliasvp is already VREF'd by getnewvnode()
vprint("umap_node_create: alias", aliasvp
);
vprint("umap_node_create: target", targetvp
);
int umap_checkvp_barrier
= 1;
umap_checkvp(vp
, fil
, lno
)
struct umap_node
*a
= VTOUMAP(vp
);
* Can't do this check because vop_reclaim runs
if (vp
->v_op
!= umap_vnodeop_p
) {
printf ("umap_checkvp: on non-umap-node\n");
while (umap_checkvp_barrier
) /*WAIT*/ ;
if (a
->umap_lowervp
== NULL
) {
/* Should never happen */
printf("vp = %x, ZERO ptr\n", vp
);
for (p
= (u_long
*) a
, i
= 0; i
< 8; i
++)
while (umap_checkvp_barrier
) /*WAIT*/ ;
if (a
->umap_lowervp
->v_usecount
< 1) {
printf("vp = %x, unref'ed lowervp\n", vp
);
for (p
= (u_long
*) a
, i
= 0; i
< 8; i
++)
while (umap_checkvp_barrier
) /*WAIT*/ ;
panic ("umap with unref'ed lowervp");
printf("umap %x/%d -> %x/%d [%s, %d]\n",
a
->umap_vnode
, a
->umap_vnode
->v_usecount
,
a
->umap_lowervp
, a
->umap_lowervp
->v_usecount
,
return (a
->umap_lowervp
);
/* umap_mapids maps all of the ids in a credential, both user and group. */
umap_mapids(v_mount
, credp
)
int i
, unentries
, gnentries
;
u_long
*groupmap
, *usermap
;
unentries
= MOUNTTOUMAPMOUNT(v_mount
)->info_nentries
;
usermap
= &(MOUNTTOUMAPMOUNT(v_mount
)->info_mapdata
[0][0]);
gnentries
= MOUNTTOUMAPMOUNT(v_mount
)->info_gnentries
;
groupmap
= &(MOUNTTOUMAPMOUNT(v_mount
)->info_gmapdata
[0][0]);
/* Find uid entry in map */
uid
= (uid_t
) umap_findid(credp
->cr_uid
, usermap
, unentries
);
credp
->cr_uid
= (uid_t
) NOBODY
;
/* cr_gid is the same as cr_groups[0] in 4BSD */
/* Find gid entry in map */
gid
= (gid_t
) umap_findid(credp
->cr_gid
, groupmap
, gnentries
);
credp
->cr_gid
= NULLGROUP
;
/* Now we must map each of the set of groups in the cr_groups
while (credp
->cr_groups
[i
] != 0) {
gid
= (gid_t
) umap_findid(credp
->cr_groups
[i
],
credp
->cr_groups
[i
++] = gid
;
credp
->cr_groups
[i
++] = NULLGROUP
;