154948Sheideman /* 254948Sheideman * Copyright (c) 1992 The Regents of the University of California 354948Sheideman * All rights reserved. 454948Sheideman * 554960Sheideman * This code is derived from software donated to Berkeley by 654960Sheideman * the UCLA Ficus project. 754948Sheideman * 854948Sheideman * %sccs.include.redist.c% 954948Sheideman * 10*55585Sheideman * @(#)umap_vnops.c 1.4 (Berkeley) 07/23/92 1154948Sheideman */ 1254948Sheideman 1354948Sheideman /* 1454948Sheideman * Umap Layer 1554948Sheideman */ 1654948Sheideman 1754948Sheideman #include <sys/param.h> 1854948Sheideman #include <sys/systm.h> 1954948Sheideman #include <sys/time.h> 2054948Sheideman #include <sys/types.h> 2154948Sheideman #include <sys/vnode.h> 2254948Sheideman #include <sys/mount.h> 2354948Sheideman #include <sys/namei.h> 2454948Sheideman #include <sys/malloc.h> 2554948Sheideman #include <sys/buf.h> 2655052Smckusick #include <miscfs/umapfs/umap.h> 2754948Sheideman 2854948Sheideman 2954948Sheideman int umap_bug_bypass = 0; /* for debugging: enables bypass printf'ing */ 3054948Sheideman 3154948Sheideman /* 3254948Sheideman * This is the 10-Apr-92 bypass routine. 3354960Sheideman * See null_vnops.c:null_bypass for more details. 3454948Sheideman */ 3554948Sheideman int 3654948Sheideman umap_bypass(ap) 3755052Smckusick struct vop_generic_args /* { 3855052Smckusick struct vnodeop_desc *a_desc; 3955052Smckusick <other random data follows, presumably> 4055052Smckusick } */ *ap; 4154948Sheideman { 4254948Sheideman extern int (**umap_vnodeop_p)(); /* not extern, really "forward" */ 4354948Sheideman int *mapdata, nentries ; 4454948Sheideman int *gmapdata, gnentries ; 4554960Sheideman struct ucred **credpp,*credp, *savecredp, *saveucredp, *savecompcredp ; 4654960Sheideman struct ucred *compcredp; 4754948Sheideman register struct vnode **this_vp_p; 4854948Sheideman int error; 4954960Sheideman struct vnode *old_vps[VDESC_MAX_VPS], *vp1; 5054948Sheideman struct vnode **vps_p[VDESC_MAX_VPS]; 5154948Sheideman struct vnode ***vppp; 5254948Sheideman struct vnodeop_desc *descp = ap->a_desc; 5354948Sheideman int reles, i; 5454960Sheideman struct componentname **compnamepp; 5554948Sheideman 5654948Sheideman if (umap_bug_bypass) 5754948Sheideman printf ("umap_bypass: %s\n", descp->vdesc_name); 5854948Sheideman 5954948Sheideman #ifdef SAFETY 6054948Sheideman /* 6154948Sheideman * We require at least one vp. 6254948Sheideman */ 6354960Sheideman if (descp->vdesc_vp_offsets == NULL || 6454960Sheideman descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET) 6554948Sheideman panic ("umap_bypass: no vp's in map.\n"); 6654948Sheideman #endif 6754948Sheideman 6854948Sheideman /* 6954948Sheideman * Map the vnodes going in. 7054948Sheideman * Later, we'll invoke the operation based on 7154948Sheideman * the first mapped vnode's operation vector. 7254948Sheideman */ 7354948Sheideman reles = descp->vdesc_flags; 7454960Sheideman for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) { 7554960Sheideman if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET) 7654948Sheideman break; /* bail out at end of list */ 7754948Sheideman vps_p[i] = this_vp_p = 7854948Sheideman VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[i],ap); 7954948Sheideman 8054948Sheideman if (i == 0) 8154948Sheideman { 8254948Sheideman vp1 = *vps_p[0]; 8354948Sheideman } 8454948Sheideman 8554948Sheideman /* 8654948Sheideman * We're not guaranteed that any but the first vnode 8754948Sheideman * are of our type. Check for and don't map any 8854960Sheideman * that aren't. (Must map first vp or vclean fails.) 8954948Sheideman */ 9054948Sheideman 9154960Sheideman if (i && (*this_vp_p)->v_op != umap_vnodeop_p) { 9254960Sheideman old_vps[i] = NULL; 9354948Sheideman } else { 9454948Sheideman old_vps[i] = *this_vp_p; 9554948Sheideman *(vps_p[i]) = UMAPVPTOLOWERVP(*this_vp_p); 9654948Sheideman if (reles & 1) 9754948Sheideman VREF(*this_vp_p); 9854960Sheideman } 9954948Sheideman 10054960Sheideman } 10154948Sheideman 10254960Sheideman /* 10354960Sheideman * Fix the credentials. (That's the purpose of this layer.) 10454960Sheideman */ 10554948Sheideman 10654948Sheideman if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) { 10754948Sheideman 10854948Sheideman credpp = VOPARG_OFFSETTO(struct ucred**, 10954948Sheideman descp->vdesc_cred_offset, ap); 11054948Sheideman 11154948Sheideman /* Save old values */ 11254948Sheideman 11354948Sheideman savecredp = (*credpp); 11454960Sheideman (*credpp) = crdup(savecredp); 11554948Sheideman credp = *credpp; 11654948Sheideman 11754948Sheideman if (umap_bug_bypass && credp->cr_uid != 0 ) 11854948Sheideman printf("umap_bypass: user was %d, group %d\n", 11954948Sheideman credp->cr_uid,credp->cr_gid); 12054948Sheideman 12154948Sheideman /* Map all ids in the credential structure. */ 12254948Sheideman 12354960Sheideman umap_mapids(vp1->v_mount,credp); 12454948Sheideman 12554948Sheideman if (umap_bug_bypass && credp->cr_uid != 0 ) 12654948Sheideman printf("umap_bypass: user now %d, group %d\n", 12754948Sheideman credp->cr_uid,credp->cr_gid); 12854948Sheideman } 12954948Sheideman 13054960Sheideman /* BSD often keeps a credential in the componentname structure 13154960Sheideman * for speed. If there is one, it better get mapped, too. 13254960Sheideman */ 13354960Sheideman 13454960Sheideman if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) { 13554960Sheideman 13654960Sheideman compnamepp = VOPARG_OFFSETTO(struct componentname**, 13754960Sheideman descp->vdesc_componentname_offset, ap); 13854960Sheideman 13954960Sheideman compcredp = (*compnamepp)->cn_cred; 14054960Sheideman savecompcredp = compcredp; 14154960Sheideman compcredp = (*compnamepp)->cn_cred = crdup(savecompcredp); 14254960Sheideman 14354960Sheideman if (umap_bug_bypass && compcredp->cr_uid != 0 ) 14454960Sheideman printf("umap_bypass: component credit user was %d, group %d\n", 14554960Sheideman compcredp->cr_uid,compcredp->cr_gid); 14654960Sheideman 14754960Sheideman /* Map all ids in the credential structure. */ 14854960Sheideman 14954960Sheideman umap_mapids(vp1->v_mount,compcredp); 15054960Sheideman 15154960Sheideman if (umap_bug_bypass && compcredp->cr_uid != 0 ) 15254960Sheideman printf("umap_bypass: component credit user now %d, group %d\n", 15354960Sheideman compcredp->cr_uid,compcredp->cr_gid); 15454960Sheideman } 15554960Sheideman 15654948Sheideman /* 15754948Sheideman * Call the operation on the lower layer 15854948Sheideman * with the modified argument structure. 15954948Sheideman */ 16054948Sheideman error = VCALL(*(vps_p[0]), descp->vdesc_offset, ap); 16154948Sheideman 16254948Sheideman /* 16354948Sheideman * Maintain the illusion of call-by-value 16454948Sheideman * by restoring vnodes in the argument structure 16554948Sheideman * to their original value. 16654948Sheideman */ 16754948Sheideman reles = descp->vdesc_flags; 16854960Sheideman for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) { 16954960Sheideman if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET) 17054948Sheideman break; /* bail out at end of list */ 17154948Sheideman if (old_vps[i]) { 17254948Sheideman *(vps_p[i]) = old_vps[i]; 17354948Sheideman if (reles & 1) 17454948Sheideman vrele(*(vps_p[i])); 17554948Sheideman }; 17654948Sheideman }; 17754948Sheideman 17854948Sheideman /* 17954948Sheideman * Map the possible out-going vpp 18054948Sheideman * (Assumes that the lower layer always returns 18154948Sheideman * a VREF'ed vpp unless it gets an error.) 18254948Sheideman */ 18354948Sheideman if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET && 18454948Sheideman !(descp->vdesc_flags & VDESC_NOMAP_VPP) && 18554948Sheideman !error) { 18654960Sheideman if (descp->vdesc_flags & VDESC_VPP_WILLRELE) 18754960Sheideman goto out; 18854960Sheideman vppp = VOPARG_OFFSETTO(struct vnode***, 18954948Sheideman descp->vdesc_vpp_offset,ap); 19054948Sheideman error = umap_node_create(old_vps[0]->v_mount, **vppp, *vppp); 19154948Sheideman }; 19254948Sheideman 19354960Sheideman out: 19454948Sheideman /* 19554948Sheideman * Free duplicate cred structure and restore old one. 19654948Sheideman */ 19754948Sheideman if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) { 19854948Sheideman if (umap_bug_bypass && credp->cr_uid != 0 ) 19954948Sheideman printf("umap_bypass: returning-user was %d\n", credp->cr_uid); 20054948Sheideman 20154948Sheideman crfree(credp); 20254948Sheideman (*credpp) = savecredp; 20354948Sheideman if (umap_bug_bypass && (*credpp)->cr_uid != 0 ) 20454948Sheideman printf("umap_bypass: returning-user now %d\n\n", 20554948Sheideman (*credpp)->cr_uid); 20654948Sheideman } 20754948Sheideman 20854960Sheideman if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) { 20954960Sheideman if (umap_bug_bypass && compcredp->cr_uid != 0 ) 21054960Sheideman printf("umap_bypass: returning-component-user was %d\n", 21154960Sheideman compcredp->cr_uid); 21254960Sheideman 21354960Sheideman crfree(compcredp); 21454960Sheideman (*compnamepp)->cn_cred = savecompcredp; 21554960Sheideman if (umap_bug_bypass && (*credpp)->cr_uid != 0 ) 21654960Sheideman printf("umap_bypass: returning-component-user now %d\n\n", 21754960Sheideman compcredp->cr_uid); 21854960Sheideman } 21954960Sheideman 22054948Sheideman return (error); 22154948Sheideman } 22254948Sheideman 22354948Sheideman 22454948Sheideman /* 22554948Sheideman * We handle getattr to change the fsid. 22654948Sheideman */ 22754948Sheideman int 22854948Sheideman umap_getattr(ap) 22955052Smckusick struct vop_getattr_args /* { 23055052Smckusick struct vnode *a_vp; 23155052Smckusick struct vattr *a_vap; 23255052Smckusick struct ucred *a_cred; 23355052Smckusick struct proc *a_p; 23455052Smckusick } */ *ap; 23554948Sheideman { 23654948Sheideman short uid, gid; 23754948Sheideman int error, tmpid, *mapdata, nentries, *gmapdata, gnentries; 23854960Sheideman struct vnode **vp1p; 23954960Sheideman struct vnodeop_desc *descp = ap->a_desc; 24054948Sheideman 24154960Sheideman if (error = umap_bypass(ap)) 24255052Smckusick return (error); 24354948Sheideman /* Requires that arguments be restored. */ 24454948Sheideman ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; 24554948Sheideman 24654960Sheideman /* 24754960Sheideman * Umap needs to map the uid and gid returned by a stat 24854960Sheideman * into the proper values for this site. This involves 24954960Sheideman * finding the returned uid in the mapping information, 25054960Sheideman * translating it into the uid on the other end, 25154960Sheideman * and filling in the proper field in the vattr 25254960Sheideman * structure pointed to by ap->a_vap. The group 25354960Sheideman * is easier, since currently all groups will be 25454960Sheideman * translate to the NULLGROUP. 25554960Sheideman */ 25654948Sheideman 25754948Sheideman /* Find entry in map */ 25854948Sheideman 25954948Sheideman uid = ap->a_vap->va_uid; 26054948Sheideman gid = ap->a_vap->va_gid; 26154948Sheideman if (umap_bug_bypass) 26254948Sheideman printf("umap_getattr: mapped uid = %d, mapped gid = %d\n",uid, 26354948Sheideman gid); 26454948Sheideman 26554948Sheideman vp1p = VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[0],ap); 26654960Sheideman nentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_nentries; 26754960Sheideman mapdata = &(MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_mapdata[0][0]); 26854960Sheideman gnentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gnentries; 26954960Sheideman gmapdata = &(MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gmapdata[0][0]); 27054948Sheideman 27154948Sheideman /* Reverse map the uid for the vnode. Since it's a reverse 27254948Sheideman map, we can't use umap_mapids() to do it. */ 27354948Sheideman 27454948Sheideman tmpid = umap_reverse_findid(uid,mapdata,nentries); 27554948Sheideman 27654948Sheideman if (tmpid != -1 ) { 27754948Sheideman 27854948Sheideman ap->a_vap->va_uid = (uid_t)tmpid; 27954948Sheideman if (umap_bug_bypass) 28054948Sheideman printf("umap_getattr: original uid = %d\n",uid); 28154948Sheideman } else 28254948Sheideman ap->a_vap->va_uid = (uid_t)NOBODY; 28354948Sheideman 28454948Sheideman /* Reverse map the gid for the vnode. */ 28554948Sheideman 28654948Sheideman tmpid = umap_reverse_findid(gid,gmapdata,gnentries); 28754948Sheideman 28854948Sheideman if (tmpid != -1) { 28954948Sheideman 29054948Sheideman ap->a_vap->va_gid = (gid_t)tmpid; 29154948Sheideman if (umap_bug_bypass) 29254948Sheideman printf("umap_getattr: original gid = %d\n",gid); 29354948Sheideman } else 29454948Sheideman ap->a_vap->va_gid = (gid_t)NULLGROUP; 29554948Sheideman 29655052Smckusick return (0); 29754948Sheideman } 29854948Sheideman 29954948Sheideman int 30055052Smckusick umap_inactive(ap) 30155052Smckusick struct vop_inactive_args /* { 30255052Smckusick struct vnode *a_vp; 30355052Smckusick } */ *ap; 30454948Sheideman { 30554948Sheideman /* 30654948Sheideman * Do nothing (and _don't_ bypass). 30754948Sheideman * Wait to vrele lowervp until reclaim, 30854948Sheideman * so that until then our umap_node is in the 30954948Sheideman * cache and reusable. 31054948Sheideman * 31154948Sheideman */ 31255052Smckusick return (0); 31354948Sheideman } 31454948Sheideman 31554948Sheideman int 31655052Smckusick umap_reclaim(ap) 31755052Smckusick struct vop_reclaim_args /* { 31855052Smckusick struct vnode *a_vp; 31955052Smckusick } */ *ap; 32054948Sheideman { 32154960Sheideman struct vnode *vp = ap->a_vp; 32254960Sheideman struct umap_node *xp = VTOUMAP(vp); 32354960Sheideman struct vnode *lowervp = xp->umap_lowervp; 32454960Sheideman 32554960Sheideman /* After this assignment, this node will not be re-used. */ 32654960Sheideman xp->umap_lowervp = NULL; 32754960Sheideman remque(xp); 32854960Sheideman FREE(vp->v_data, M_TEMP); 32954960Sheideman vp->v_data = NULL; 33054960Sheideman vrele (lowervp); 33155052Smckusick return (0); 33254948Sheideman } 33354948Sheideman 33454948Sheideman int 33555052Smckusick umap_strategy(ap) 33655052Smckusick struct vop_strategy_args /* { 33755052Smckusick struct buf *a_bp; 33855052Smckusick } */ *ap; 33954948Sheideman { 34054960Sheideman struct buf *bp = ap->a_bp; 34154960Sheideman int error; 34254960Sheideman struct vnode *savedvp; 34354948Sheideman 34454960Sheideman savedvp = bp->b_vp; 34554960Sheideman bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp); 34654960Sheideman 34754960Sheideman error = VOP_STRATEGY(ap->a_bp); 34854960Sheideman 34954960Sheideman bp->b_vp = savedvp; 35054960Sheideman 35155052Smckusick return (error); 35254948Sheideman } 35354948Sheideman 35454948Sheideman int 35555052Smckusick umap_bwrite(ap) 35655052Smckusick struct vop_bwrite_args /* { 35755052Smckusick struct buf *a_bp; 35855052Smckusick } */ *ap; 35954948Sheideman { 36054960Sheideman struct buf *bp = ap->a_bp; 36154948Sheideman int error; 36254948Sheideman struct vnode *savedvp; 36354948Sheideman 36454960Sheideman savedvp = bp->b_vp; 36554960Sheideman bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp); 36654948Sheideman 36754960Sheideman error = VOP_BWRITE(ap->a_bp); 36854948Sheideman 36954960Sheideman bp->b_vp = savedvp; 37054948Sheideman 37155052Smckusick return (error); 37254948Sheideman } 37354948Sheideman 37454948Sheideman 37554948Sheideman int 37655052Smckusick umap_print(ap) 37755052Smckusick struct vop_print_args /* { 37855052Smckusick struct vnode *a_vp; 37955052Smckusick } */ *ap; 38054948Sheideman { 38154948Sheideman register struct vnode *vp = ap->a_vp; 38254948Sheideman printf ("\ttag VT_UMAPFS, vp=%x, lowervp=%x\n", vp, UMAPVPTOLOWERVP(vp)); 38355052Smckusick return (0); 38454948Sheideman } 38554948Sheideman 38654960Sheideman int 38754960Sheideman umap_rename(ap) 38855052Smckusick struct vop_rename_args /* { 38955052Smckusick struct vnode *a_fdvp; 39055052Smckusick struct vnode *a_fvp; 39155052Smckusick struct componentname *a_fcnp; 39255052Smckusick struct vnode *a_tdvp; 39355052Smckusick struct vnode *a_tvp; 39455052Smckusick struct componentname *a_tcnp; 39555052Smckusick } */ *ap; 39654960Sheideman { 39754960Sheideman int error; 39854960Sheideman struct componentname *compnamep; 39954960Sheideman struct ucred *compcredp, *savecompcredp; 40054960Sheideman struct vnode *vp; 40154948Sheideman 402*55585Sheideman /* 403*55585Sheideman * Rename is irregular, having two componentname structures. 404*55585Sheideman * We need to map the cre in the second structure, 405*55585Sheideman * and then bypass takes care of the rest. 40654960Sheideman */ 40754960Sheideman 40854960Sheideman vp = ap->a_fdvp; 40954960Sheideman compnamep = ap->a_tcnp; 41054960Sheideman compcredp = compnamep->cn_cred; 41154960Sheideman 41254960Sheideman savecompcredp = compcredp; 41354960Sheideman compcredp = compnamep->cn_cred = crdup(savecompcredp); 41454960Sheideman 41554960Sheideman if (umap_bug_bypass && compcredp->cr_uid != 0 ) 41654960Sheideman printf("umap_rename: rename component credit user was %d, group %d\n", 41754960Sheideman compcredp->cr_uid,compcredp->cr_gid); 41854960Sheideman 41954960Sheideman /* Map all ids in the credential structure. */ 42054960Sheideman 42154960Sheideman umap_mapids(vp->v_mount,compcredp); 42254960Sheideman 42354960Sheideman if (umap_bug_bypass && compcredp->cr_uid != 0 ) 42454960Sheideman printf("umap_rename: rename component credit user now %d, group %d\n", 42554960Sheideman compcredp->cr_uid,compcredp->cr_gid); 42654960Sheideman 427*55585Sheideman error = umap_bypass(ap); 42854960Sheideman 42954960Sheideman /* Restore the additional mapped componentname cred structure. */ 43054960Sheideman 43154960Sheideman crfree(compcredp); 43254960Sheideman compnamep->cn_cred = savecompcredp; 433*55585Sheideman 434*55585Sheideman return error; 43554960Sheideman } 43654960Sheideman 43754948Sheideman /* 43854948Sheideman * Global vfs data structures 43954948Sheideman */ 44054948Sheideman /* 44154960Sheideman * XXX - strategy,bwrite are hand coded currently. They should 44254948Sheideman * go away with a merged buffer/block cache. 44354948Sheideman * 44454948Sheideman */ 44554948Sheideman int (**umap_vnodeop_p)(); 44654948Sheideman struct vnodeopv_entry_desc umap_vnodeop_entries[] = { 44754948Sheideman { &vop_default_desc, umap_bypass }, 44854948Sheideman 44954948Sheideman { &vop_getattr_desc, umap_getattr }, 45054948Sheideman { &vop_inactive_desc, umap_inactive }, 45154948Sheideman { &vop_reclaim_desc, umap_reclaim }, 45254948Sheideman { &vop_print_desc, umap_print }, 453*55585Sheideman { &vop_rename_desc, umap_rename }, 45454948Sheideman 45554948Sheideman { &vop_strategy_desc, umap_strategy }, 45654960Sheideman { &vop_bwrite_desc, umap_bwrite }, 45754948Sheideman 45854960Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 45954948Sheideman }; 46054948Sheideman struct vnodeopv_desc umap_vnodeop_opv_desc = 46154948Sheideman { &umap_vnodeop_p, umap_vnodeop_entries }; 462