xref: /csrg-svn/sys/miscfs/umapfs/umap_vnops.c (revision 54960)
154948Sheideman /*
254948Sheideman  * Copyright (c) 1992 The Regents of the University of California
354948Sheideman  * All rights reserved.
454948Sheideman  *
5*54960Sheideman  * This code is derived from software donated to Berkeley by
6*54960Sheideman  * the UCLA Ficus project.
754948Sheideman  *
854948Sheideman  * %sccs.include.redist.c%
954948Sheideman  *
10*54960Sheideman  *	@(#)umap_vnops.c	1.2 (Berkeley) 07/11/92
1154948Sheideman  *
12*54960Sheideman  * @(#)umap_vnops.c       1.5 (Berkeley) 7/10/92
1354948Sheideman  */
1454948Sheideman 
1554948Sheideman /*
1654948Sheideman  * Umap Layer
1754948Sheideman  */
1854948Sheideman 
1954948Sheideman #include <sys/param.h>
2054948Sheideman #include <sys/systm.h>
2154948Sheideman #include <sys/time.h>
2254948Sheideman #include <sys/types.h>
2354948Sheideman #include <sys/vnode.h>
2454948Sheideman #include <sys/mount.h>
2554948Sheideman #include <sys/namei.h>
2654948Sheideman #include <sys/malloc.h>
2754948Sheideman #include <sys/buf.h>
2854948Sheideman #include <umapfs/umap.h>
2954948Sheideman 
3054948Sheideman 
3154948Sheideman int umap_bug_bypass = 0;   /* for debugging: enables bypass printf'ing */
3254948Sheideman 
3354948Sheideman /*
3454948Sheideman  * This is the 10-Apr-92 bypass routine.
35*54960Sheideman  * See null_vnops.c:null_bypass for more details.
3654948Sheideman  */
3754948Sheideman int
3854948Sheideman umap_bypass(ap)
3954948Sheideman 	struct vop_generic_args *ap;
4054948Sheideman {
4154948Sheideman 	extern int (**umap_vnodeop_p)();  /* not extern, really "forward" */
4254948Sheideman 	int *mapdata, nentries ;
4354948Sheideman 	int *gmapdata, gnentries ;
44*54960Sheideman 	struct ucred **credpp,*credp, *savecredp, *saveucredp, *savecompcredp ;
45*54960Sheideman 	struct ucred *compcredp;
4654948Sheideman 	register struct vnode **this_vp_p;
4754948Sheideman 	int error;
48*54960Sheideman 	struct vnode *old_vps[VDESC_MAX_VPS], *vp1;
4954948Sheideman 	struct vnode **vps_p[VDESC_MAX_VPS];
5054948Sheideman 	struct vnode ***vppp;
5154948Sheideman 	struct vnodeop_desc *descp = ap->a_desc;
5254948Sheideman 	int reles, i;
53*54960Sheideman 	struct componentname **compnamepp;
5454948Sheideman 
5554948Sheideman 	if (umap_bug_bypass)
5654948Sheideman 		printf ("umap_bypass: %s\n", descp->vdesc_name);
5754948Sheideman 
5854948Sheideman #ifdef SAFETY
5954948Sheideman 	/*
6054948Sheideman 	 * We require at least one vp.
6154948Sheideman 	 */
62*54960Sheideman 	if (descp->vdesc_vp_offsets == NULL ||
63*54960Sheideman 	    descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET)
6454948Sheideman 		panic ("umap_bypass: no vp's in map.\n");
6554948Sheideman #endif
6654948Sheideman 
6754948Sheideman 	/*
6854948Sheideman 	 * Map the vnodes going in.
6954948Sheideman 	 * Later, we'll invoke the operation based on
7054948Sheideman 	 * the first mapped vnode's operation vector.
7154948Sheideman 	 */
7254948Sheideman 	reles = descp->vdesc_flags;
73*54960Sheideman 	for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
74*54960Sheideman 		if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
7554948Sheideman 			break;   /* bail out at end of list */
7654948Sheideman 		vps_p[i] = this_vp_p =
7754948Sheideman 			VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[i],ap);
7854948Sheideman 
7954948Sheideman 		if (i == 0)
8054948Sheideman 		{
8154948Sheideman 			vp1 = *vps_p[0];
8254948Sheideman 		}
8354948Sheideman 
8454948Sheideman 		/*
8554948Sheideman 		 * We're not guaranteed that any but the first vnode
8654948Sheideman 		 * are of our type.  Check for and don't map any
87*54960Sheideman 		 * that aren't.  (Must map first vp or vclean fails.)
8854948Sheideman 		 */
8954948Sheideman 
90*54960Sheideman 		if (i && (*this_vp_p)->v_op != umap_vnodeop_p) {
91*54960Sheideman 			old_vps[i] = NULL;
9254948Sheideman 		} else {
9354948Sheideman 			old_vps[i] = *this_vp_p;
9454948Sheideman 			*(vps_p[i]) = UMAPVPTOLOWERVP(*this_vp_p);
9554948Sheideman 			if (reles & 1)
9654948Sheideman 				VREF(*this_vp_p);
97*54960Sheideman 		}
9854948Sheideman 
99*54960Sheideman 	}
10054948Sheideman 
101*54960Sheideman 	/*
102*54960Sheideman 	 * Fix the credentials.  (That's the purpose of this layer.)
103*54960Sheideman 	 */
10454948Sheideman 
10554948Sheideman 	if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
10654948Sheideman 
10754948Sheideman 		credpp = VOPARG_OFFSETTO(struct ucred**,
10854948Sheideman 		    descp->vdesc_cred_offset, ap);
10954948Sheideman 
11054948Sheideman 		/* Save old values */
11154948Sheideman 
11254948Sheideman 		savecredp = (*credpp);
113*54960Sheideman 		(*credpp) = crdup(savecredp);
11454948Sheideman 		credp = *credpp;
11554948Sheideman 
11654948Sheideman 		if (umap_bug_bypass && credp->cr_uid != 0 )
11754948Sheideman 			printf("umap_bypass: user was %d, group %d\n",
11854948Sheideman 			    credp->cr_uid,credp->cr_gid);
11954948Sheideman 
12054948Sheideman 		/* Map all ids in the credential structure. */
12154948Sheideman 
122*54960Sheideman 		umap_mapids(vp1->v_mount,credp);
12354948Sheideman 
12454948Sheideman 		if (umap_bug_bypass && credp->cr_uid != 0 )
12554948Sheideman 			printf("umap_bypass: user now %d, group %d\n",
12654948Sheideman 			    credp->cr_uid,credp->cr_gid);
12754948Sheideman 	}
12854948Sheideman 
129*54960Sheideman 	/* BSD often keeps a credential in the componentname structure
130*54960Sheideman 	 * for speed.  If there is one, it better get mapped, too.
131*54960Sheideman 	 */
132*54960Sheideman 
133*54960Sheideman 	if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) {
134*54960Sheideman 
135*54960Sheideman 		compnamepp = VOPARG_OFFSETTO(struct componentname**,
136*54960Sheideman 		    descp->vdesc_componentname_offset, ap);
137*54960Sheideman 
138*54960Sheideman 		compcredp = (*compnamepp)->cn_cred;
139*54960Sheideman 		savecompcredp = compcredp;
140*54960Sheideman 		compcredp = (*compnamepp)->cn_cred = crdup(savecompcredp);
141*54960Sheideman 
142*54960Sheideman 		if (umap_bug_bypass && compcredp->cr_uid != 0 )
143*54960Sheideman 			printf("umap_bypass: component credit user was %d, group %d\n",
144*54960Sheideman 			    compcredp->cr_uid,compcredp->cr_gid);
145*54960Sheideman 
146*54960Sheideman 		/* Map all ids in the credential structure. */
147*54960Sheideman 
148*54960Sheideman 		umap_mapids(vp1->v_mount,compcredp);
149*54960Sheideman 
150*54960Sheideman 		if (umap_bug_bypass && compcredp->cr_uid != 0 )
151*54960Sheideman 			printf("umap_bypass: component credit user now %d, group %d\n",
152*54960Sheideman 			    compcredp->cr_uid,compcredp->cr_gid);
153*54960Sheideman 	}
154*54960Sheideman 
15554948Sheideman 	/*
15654948Sheideman 	 * Call the operation on the lower layer
15754948Sheideman 	 * with the modified argument structure.
15854948Sheideman 	 */
15954948Sheideman 	error = VCALL(*(vps_p[0]), descp->vdesc_offset, ap);
16054948Sheideman 
16154948Sheideman 	/*
16254948Sheideman 	 * Maintain the illusion of call-by-value
16354948Sheideman 	 * by restoring vnodes in the argument structure
16454948Sheideman 	 * to their original value.
16554948Sheideman 	 */
16654948Sheideman 	reles = descp->vdesc_flags;
167*54960Sheideman 	for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
168*54960Sheideman 		if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
16954948Sheideman 			break;   /* bail out at end of list */
17054948Sheideman 		if (old_vps[i]) {
17154948Sheideman 			*(vps_p[i]) = old_vps[i];
17254948Sheideman 			if (reles & 1)
17354948Sheideman 				vrele(*(vps_p[i]));
17454948Sheideman 		};
17554948Sheideman 	};
17654948Sheideman 
17754948Sheideman 	/*
17854948Sheideman 	 * Map the possible out-going vpp
17954948Sheideman 	 * (Assumes that the lower layer always returns
18054948Sheideman 	 * a VREF'ed vpp unless it gets an error.)
18154948Sheideman 	 */
18254948Sheideman 	if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET &&
18354948Sheideman 	    !(descp->vdesc_flags & VDESC_NOMAP_VPP) &&
18454948Sheideman 	    !error) {
185*54960Sheideman 		if (descp->vdesc_flags & VDESC_VPP_WILLRELE)
186*54960Sheideman 			goto out;
187*54960Sheideman 		vppp = VOPARG_OFFSETTO(struct vnode***,
18854948Sheideman 				 descp->vdesc_vpp_offset,ap);
18954948Sheideman 		error = umap_node_create(old_vps[0]->v_mount, **vppp, *vppp);
19054948Sheideman 	};
19154948Sheideman 
192*54960Sheideman  out:
19354948Sheideman 	/*
19454948Sheideman 	 * Free duplicate cred structure and restore old one.
19554948Sheideman 	 */
19654948Sheideman 	if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
19754948Sheideman 		if (umap_bug_bypass && credp->cr_uid != 0 )
19854948Sheideman 		printf("umap_bypass: returning-user was %d\n", credp->cr_uid);
19954948Sheideman 
20054948Sheideman 		crfree(credp);
20154948Sheideman 		(*credpp) = savecredp;
20254948Sheideman 		if (umap_bug_bypass && (*credpp)->cr_uid != 0 )
20354948Sheideman 		 	printf("umap_bypass: returning-user now %d\n\n",
20454948Sheideman 			    (*credpp)->cr_uid);
20554948Sheideman 	}
20654948Sheideman 
207*54960Sheideman 	if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) {
208*54960Sheideman 		if (umap_bug_bypass && compcredp->cr_uid != 0 )
209*54960Sheideman 		printf("umap_bypass: returning-component-user was %d\n",
210*54960Sheideman 		    compcredp->cr_uid);
211*54960Sheideman 
212*54960Sheideman 		crfree(compcredp);
213*54960Sheideman 		(*compnamepp)->cn_cred = savecompcredp;
214*54960Sheideman 		if (umap_bug_bypass && (*credpp)->cr_uid != 0 )
215*54960Sheideman 		 	printf("umap_bypass: returning-component-user now %d\n\n",
216*54960Sheideman 			    compcredp->cr_uid);
217*54960Sheideman 	}
218*54960Sheideman 
21954948Sheideman 	return (error);
22054948Sheideman }
22154948Sheideman 
22254948Sheideman 
22354948Sheideman /*
22454948Sheideman  *  We handle getattr to change the fsid.
22554948Sheideman  */
22654948Sheideman int
22754948Sheideman umap_getattr(ap)
22854948Sheideman 	struct vop_getattr_args *ap;
22954948Sheideman {
23054948Sheideman 	short uid, gid;
23154948Sheideman 	int error, tmpid, *mapdata, nentries, *gmapdata, gnentries;
232*54960Sheideman 	struct vnode **vp1p;
233*54960Sheideman 	struct vnodeop_desc *descp = ap->a_desc;
23454948Sheideman 
235*54960Sheideman 	if (error = umap_bypass(ap))
23654948Sheideman 		return error;
23754948Sheideman 	/* Requires that arguments be restored. */
23854948Sheideman 	ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
23954948Sheideman 
240*54960Sheideman 	/*
241*54960Sheideman 	 * Umap needs to map the uid and gid returned by a stat
242*54960Sheideman 	 * into the proper values for this site.  This involves
243*54960Sheideman 	 * finding the returned uid in the mapping information,
244*54960Sheideman 	 * translating it into the uid on the other end,
245*54960Sheideman 	 * and filling in the proper field in the vattr
246*54960Sheideman 	 * structure pointed to by ap->a_vap.  The group
247*54960Sheideman 	 * is easier, since currently all groups will be
248*54960Sheideman 	 * translate to the NULLGROUP.
249*54960Sheideman 	 */
25054948Sheideman 
25154948Sheideman 	/* Find entry in map */
25254948Sheideman 
25354948Sheideman 	uid = ap->a_vap->va_uid;
25454948Sheideman 	gid = ap->a_vap->va_gid;
25554948Sheideman 	if (umap_bug_bypass)
25654948Sheideman 		printf("umap_getattr: mapped uid = %d, mapped gid = %d\n",uid,
25754948Sheideman 		    gid);
25854948Sheideman 
25954948Sheideman 	vp1p = VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[0],ap);
260*54960Sheideman 	nentries =  MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_nentries;
261*54960Sheideman 	mapdata =  &(MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_mapdata[0][0]);
262*54960Sheideman 	gnentries =  MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gnentries;
263*54960Sheideman 	gmapdata =  &(MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gmapdata[0][0]);
26454948Sheideman 
26554948Sheideman 	/* Reverse map the uid for the vnode.  Since it's a reverse
26654948Sheideman 		map, we can't use umap_mapids() to do it. */
26754948Sheideman 
26854948Sheideman 	tmpid = umap_reverse_findid(uid,mapdata,nentries);
26954948Sheideman 
27054948Sheideman 	if (tmpid != -1 ) {
27154948Sheideman 
27254948Sheideman 		ap->a_vap->va_uid = (uid_t)tmpid;
27354948Sheideman 		if (umap_bug_bypass)
27454948Sheideman 			printf("umap_getattr: original uid = %d\n",uid);
27554948Sheideman 	} else
27654948Sheideman 		ap->a_vap->va_uid = (uid_t)NOBODY;
27754948Sheideman 
27854948Sheideman 	/* Reverse map the gid for the vnode. */
27954948Sheideman 
28054948Sheideman 	tmpid = umap_reverse_findid(gid,gmapdata,gnentries);
28154948Sheideman 
28254948Sheideman 	if (tmpid != -1) {
28354948Sheideman 
28454948Sheideman 		ap->a_vap->va_gid = (gid_t)tmpid;
28554948Sheideman 		if (umap_bug_bypass)
28654948Sheideman 			printf("umap_getattr: original gid = %d\n",gid);
28754948Sheideman 	} else
28854948Sheideman 		ap->a_vap->va_gid = (gid_t)NULLGROUP;
28954948Sheideman 
29054948Sheideman 	return 0;
29154948Sheideman }
29254948Sheideman 
29354948Sheideman int
29454948Sheideman umap_inactive (ap)
29554948Sheideman 	struct vop_inactive_args *ap;
29654948Sheideman {
29754948Sheideman 	/*
29854948Sheideman 	 * Do nothing (and _don't_ bypass).
29954948Sheideman 	 * Wait to vrele lowervp until reclaim,
30054948Sheideman 	 * so that until then our umap_node is in the
30154948Sheideman 	 * cache and reusable.
30254948Sheideman 	 *
30354948Sheideman 	 */
30454948Sheideman 	return 0;
30554948Sheideman }
30654948Sheideman 
30754948Sheideman int
30854948Sheideman umap_reclaim (ap)
30954948Sheideman 	struct vop_reclaim_args *ap;
31054948Sheideman {
311*54960Sheideman 	struct vnode *vp = ap->a_vp;
312*54960Sheideman 	struct umap_node *xp = VTOUMAP(vp);
313*54960Sheideman 	struct vnode *lowervp = xp->umap_lowervp;
314*54960Sheideman 
315*54960Sheideman 	/* After this assignment, this node will not be re-used. */
316*54960Sheideman 	xp->umap_lowervp = NULL;
317*54960Sheideman 	remque(xp);
318*54960Sheideman 	FREE(vp->v_data, M_TEMP);
319*54960Sheideman 	vp->v_data = NULL;
320*54960Sheideman 	vrele (lowervp);
321*54960Sheideman 	return 0;
32254948Sheideman }
32354948Sheideman 
32454948Sheideman int
325*54960Sheideman umap_strategy (ap)
326*54960Sheideman 	struct vop_strategy_args *ap;
32754948Sheideman {
328*54960Sheideman 	struct buf *bp = ap->a_bp;
329*54960Sheideman 	int error;
330*54960Sheideman 	struct vnode *savedvp;
33154948Sheideman 
332*54960Sheideman 	savedvp = bp->b_vp;
333*54960Sheideman 	bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp);
334*54960Sheideman 
335*54960Sheideman 	error = VOP_STRATEGY(ap->a_bp);
336*54960Sheideman 
337*54960Sheideman 	bp->b_vp = savedvp;
338*54960Sheideman 
339*54960Sheideman 	return error;
34054948Sheideman }
34154948Sheideman 
34254948Sheideman int
343*54960Sheideman umap_bwrite (ap)
344*54960Sheideman 	struct vop_bwrite_args *ap;
34554948Sheideman {
346*54960Sheideman 	struct buf *bp = ap->a_bp;
34754948Sheideman 	int error;
34854948Sheideman 	struct vnode *savedvp;
34954948Sheideman 
350*54960Sheideman 	savedvp = bp->b_vp;
351*54960Sheideman 	bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp);
35254948Sheideman 
353*54960Sheideman 	error = VOP_BWRITE(ap->a_bp);
35454948Sheideman 
355*54960Sheideman 	bp->b_vp = savedvp;
35654948Sheideman 
35754948Sheideman 	return error;
35854948Sheideman }
35954948Sheideman 
36054948Sheideman 
36154948Sheideman int
36254948Sheideman umap_print (ap)
36354948Sheideman 	struct vop_print_args *ap;
36454948Sheideman {
36554948Sheideman 	register struct vnode *vp = ap->a_vp;
36654948Sheideman 	printf ("\ttag VT_UMAPFS, vp=%x, lowervp=%x\n", vp, UMAPVPTOLOWERVP(vp));
36754948Sheideman 	return 0;
36854948Sheideman }
36954948Sheideman 
370*54960Sheideman int
371*54960Sheideman umap_rename(ap)
372*54960Sheideman 	struct vop_rename_args *ap;
373*54960Sheideman {
374*54960Sheideman 	int error;
375*54960Sheideman 	struct componentname *compnamep;
376*54960Sheideman 	struct ucred *compcredp, *savecompcredp;
377*54960Sheideman 	struct vnode *vp;
37854948Sheideman 
379*54960Sheideman 	/* Now map the second componentname structure kept in this vop's
380*54960Sheideman 	 * arguments.
381*54960Sheideman 	 */
382*54960Sheideman 
383*54960Sheideman 	vp = ap->a_fdvp;
384*54960Sheideman 	compnamep = ap->a_tcnp;
385*54960Sheideman 	compcredp = compnamep->cn_cred;
386*54960Sheideman 
387*54960Sheideman 	savecompcredp = compcredp;
388*54960Sheideman 	compcredp = compnamep->cn_cred = crdup(savecompcredp);
389*54960Sheideman 
390*54960Sheideman 	if (umap_bug_bypass && compcredp->cr_uid != 0 )
391*54960Sheideman 		printf("umap_rename: rename component credit user was %d, group %d\n",
392*54960Sheideman 		    compcredp->cr_uid,compcredp->cr_gid);
393*54960Sheideman 
394*54960Sheideman 	/* Map all ids in the credential structure. */
395*54960Sheideman 
396*54960Sheideman 	umap_mapids(vp->v_mount,compcredp);
397*54960Sheideman 
398*54960Sheideman 	if (umap_bug_bypass && compcredp->cr_uid != 0 )
399*54960Sheideman 		printf("umap_rename: rename component credit user now %d, group %d\n",
400*54960Sheideman 		    compcredp->cr_uid,compcredp->cr_gid);
401*54960Sheideman 
402*54960Sheideman 	if (error = umap_bypass(ap))
403*54960Sheideman 		return error;
404*54960Sheideman 
405*54960Sheideman 	/* Restore the additional mapped componentname cred structure. */
406*54960Sheideman 
407*54960Sheideman 	crfree(compcredp);
408*54960Sheideman 	compnamep->cn_cred = savecompcredp;
409*54960Sheideman 
410*54960Sheideman }
411*54960Sheideman 
41254948Sheideman /*
41354948Sheideman  * Global vfs data structures
41454948Sheideman  */
41554948Sheideman /*
416*54960Sheideman  * XXX - strategy,bwrite are hand coded currently.  They should
41754948Sheideman  * go away with a merged buffer/block cache.
41854948Sheideman  *
41954948Sheideman  */
42054948Sheideman int (**umap_vnodeop_p)();
42154948Sheideman struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
42254948Sheideman 	{ &vop_default_desc, umap_bypass },
42354948Sheideman 
42454948Sheideman 	{ &vop_getattr_desc, umap_getattr },
42554948Sheideman 	{ &vop_inactive_desc, umap_inactive },
42654948Sheideman 	{ &vop_reclaim_desc, umap_reclaim },
42754948Sheideman 	{ &vop_print_desc, umap_print },
42854948Sheideman 
42954948Sheideman 	{ &vop_strategy_desc, umap_strategy },
430*54960Sheideman 	{ &vop_bwrite_desc, umap_bwrite },
43154948Sheideman 
432*54960Sheideman 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
43354948Sheideman };
43454948Sheideman struct vnodeopv_desc umap_vnodeop_opv_desc =
43554948Sheideman 	{ &umap_vnodeop_p, umap_vnodeop_entries };
436