umap_subr.c

来自「早期freebsd实现」· C语言 代码 · 共 398 行

C
398
字号
/* * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software donated to Berkeley by * Jan-Simon Pendry. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 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 * SUCH DAMAGE. * *	@(#)umap_subr.c	8.6 (Berkeley) 1/26/94 * * $Id: lofs_subr.c, v 1.11 1992/05/30 10:05:43 jsp Exp jsp $ */#include <sys/param.h>#include <sys/systm.h>#include <sys/time.h>#include <sys/types.h>#include <sys/vnode.h>#include <sys/mount.h>#include <sys/namei.h>#include <sys/malloc.h>#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))/* * Null layer cache: * 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. *//* * Cache head */struct umap_node_cache {	struct umap_node	*ac_forw;	struct umap_node	*ac_back;};static struct umap_node_cache umap_node_cache[NUMAPNODECACHE];/* * Initialise cache headers */umapfs_init(){	struct umap_node_cache *ac;#ifdef UMAPFS_DIAGNOSTIC	printf("umapfs_init\n");		/* printed during system boot */#endif	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 *umap_node_hash(targetvp)	struct vnode *targetvp;{	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. */static u_longumap_findid(id, map, nentries)	u_long id;	u_long map[][2];	int nentries;{	int i;	/* Find uid entry in map */	i = 0;	while ((i<nentries) && ((map[i][0]) != id))		i++;	if (i < nentries)		return (map[i][1]);	else		return (-1);}/* * umap_reverse_findid is called by umap_getattr() in umap_vnodeops.c to * find a user or group id in a map, in reverse. */u_longumap_reverse_findid(id, map, nentries)	u_long id;	u_long map[][2];	int nentries;{	int i;	/* Find uid entry in map */	i = 0;	while ((i<nentries) && ((map[i][1]) != id))		i++;	if (i < nentries)		return (map[i][0]);	else		return (-1);}/* * Return alias for target vnode if already exists, else 0. */static struct vnode *umap_node_find(mp, targetvp)	struct mount *mp;	struct vnode *targetvp;{	struct umap_node_cache *hd;	struct umap_node *a;	struct vnode *vp;#ifdef UMAPFS_DIAGNOSTIC	printf("umap_node_find(mp = %x, target = %x)\n", mp, targetvp);#endif	/*	 * 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); loop:	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) {			vp = UMAPTOV(a);			/*			 * We need vget for the VXLOCK			 * stuff, but we don't want to lock			 * the lower node.			 */			if (vget(vp, 0)) {#ifdef UMAPFS_DIAGNOSTIC				printf ("umap_node_find: vget failed.\n");#endif				goto loop;			}			return (vp);		}	}#ifdef UMAPFS_DIAGNOSTIC	printf("umap_node_find(%x, %x): NOT found\n", mp, targetvp);#endif	return (0);}/* * Make a new umap_node node. * Vp is the alias vnode, lofsvp is the target vnode. * Maintain a reference to (targetvp). */static intumap_node_alloc(mp, lowervp, vpp)	struct mount *mp;	struct vnode *lowervp;	struct vnode **vpp;{	struct umap_node_cache *hd;	struct umap_node *xp;	struct vnode *othervp, *vp;	int error;	if (error = getnewvnode(VT_UMAP, mp, umap_vnodeop_p, vpp))		return (error);	vp = *vpp;	MALLOC(xp, struct umap_node *, sizeof(struct umap_node),	    M_TEMP, M_WAITOK);	vp->v_type = lowervp->v_type;	xp->umap_vnode = vp;	vp->v_data = xp;	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)) {		FREE(xp, M_TEMP);		vp->v_type = VBAD;	/* node is discarded */		vp->v_usecount = 0;	/* XXX */		*vpp = othervp;		return (0);	}	VREF(lowervp);   /* Extra VREF will be vrele'd in umap_node_create */	hd = umap_node_hash(lowervp);	insque(xp, hd);	return (0);}/* * 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. */intumap_node_create(mp, targetvp, newvpp)	struct mount *mp;	struct vnode *targetvp;	struct vnode **newvpp;{	struct vnode *aliasvp;	if (aliasvp = umap_node_find(mp, targetvp)) {		/*		 * Take another reference to the alias vnode		 */#ifdef UMAPFS_DIAGNOSTIC		vprint("umap_node_create: exists", ap->umap_vnode);#endif		/* VREF(aliasvp); */	} else {		int error;		/*		 * Get new vnode.		 */#ifdef UMAPFS_DIAGNOSTIC		printf("umap_node_create: create new alias vnode\n");#endif		/*		 * Make new vnode reference the umap_node.		 */		if (error = umap_node_alloc(mp, targetvp, &aliasvp))			return (error);		/*		 * aliasvp is already VREF'd by getnewvnode()		 */	}	vrele(targetvp);#ifdef UMAPFS_DIAGNOSTIC	vprint("umap_node_create: alias", aliasvp);	vprint("umap_node_create: target", targetvp);#endif	*newvpp = aliasvp;	return (0);}#ifdef UMAPFS_DIAGNOSTICint umap_checkvp_barrier = 1;struct vnode *umap_checkvp(vp, fil, lno)	struct vnode *vp;	char *fil;	int lno;{	struct umap_node *a = VTOUMAP(vp);#if 0	/*	 * Can't do this check because vop_reclaim runs	 * with funny vop vector.	 */	if (vp->v_op != umap_vnodeop_p) {		printf ("umap_checkvp: on non-umap-node\n");		while (umap_checkvp_barrier) /*WAIT*/ ;		panic("umap_checkvp");	}#endif	if (a->umap_lowervp == NULL) {		/* Should never happen */		int i; u_long *p;		printf("vp = %x, ZERO ptr\n", vp);		for (p = (u_long *) a, i = 0; i < 8; i++)			printf(" %x", p[i]);		printf("\n");		/* wait for debugger */		while (umap_checkvp_barrier) /*WAIT*/ ;		panic("umap_checkvp");	}	if (a->umap_lowervp->v_usecount < 1) {		int i; u_long *p;		printf("vp = %x, unref'ed lowervp\n", vp);		for (p = (u_long *) a, i = 0; i < 8; i++)			printf(" %x", p[i]);		printf("\n");		/* wait for debugger */		while (umap_checkvp_barrier) /*WAIT*/ ;		panic ("umap with unref'ed lowervp");	}#if 0	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,		fil, lno);#endif	return (a->umap_lowervp);}#endif/* umap_mapids maps all of the ids in a credential, both user and group. */voidumap_mapids(v_mount, credp)	struct mount *v_mount;	struct ucred *credp;{	int i, unentries, gnentries;	u_long *groupmap, *usermap;	uid_t uid;	gid_t gid;	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);	if (uid != -1)		credp->cr_uid = uid;	else		credp->cr_uid = (uid_t) NOBODY;#ifdef notdef	/* 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);	if (gid != -1)		credp->cr_gid = gid;	else		credp->cr_gid = NULLGROUP;#endif	/* Now we must map each of the set of groups in the cr_groups 		structure. */	i = 0;	while (credp->cr_groups[i] != 0) {		gid = (gid_t) umap_findid(credp->cr_groups[i],					groupmap, gnentries);		if (gid != -1)			credp->cr_groups[i++] = gid;		else			credp->cr_groups[i++] = NULLGROUP;	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?