* Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
* This code is derived from software donated to Berkeley by
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)umap_subr.c 8.9 (Berkeley) 5/14/95
* From: $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
* 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.
(&umap_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & umap_node_hash])
LIST_HEAD(umap_node_hashhead
, umap_node
) *umap_node_hashtbl
;
* Initialise cache headers
printf("umapfs_init\n"); /* printed during system boot */
umap_node_hashtbl
= hashinit(NUMAPNODECACHE
, M_CACHE
, &umap_node_hash
);
* 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 proc
*p
= curproc
; /* XXX */
struct umap_node_hashhead
*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_NHASH(targetvp
);
for (a
= hd
->lh_first
; a
!= 0; a
= a
->umap_hash
.le_next
) {
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_hashhead
*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_NHASH(lowervp
);
LIST_INSERT_HEAD(hd
, xp
, umap_hash
);
* 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
;