154948Sheideman /* 263248Sbostic * Copyright (c) 1992, 1993 363248Sbostic * The Regents of the University of California. 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*69445Smckusick * @(#)umap_vnops.c 8.5 (Berkeley) 05/14/95 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" */ 4365491Spendry struct ucred **credpp = 0, *credp = 0; 4465491Spendry struct ucred *savecredp, *savecompcredp = 0; 4565491Spendry struct ucred *compcredp = 0; 4665491Spendry struct vnode **this_vp_p; 4754948Sheideman int error; 4865491Spendry struct vnode *old_vps[VDESC_MAX_VPS]; 4965491Spendry struct vnode *vp1 = 0; 5054948Sheideman struct vnode **vps_p[VDESC_MAX_VPS]; 5154948Sheideman struct vnode ***vppp; 5254948Sheideman struct vnodeop_desc *descp = ap->a_desc; 5354948Sheideman int reles, i; 5465491Spendry struct componentname **compnamepp = 0; 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 = 7865491Spendry VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[i], ap); 7954948Sheideman 8065491Spendry if (i == 0) { 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 8754960Sheideman * that aren't. (Must map first vp or vclean fails.) 8854948Sheideman */ 8954948Sheideman 9054960Sheideman if (i && (*this_vp_p)->v_op != umap_vnodeop_p) { 9154960Sheideman 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); 9754960Sheideman } 9854948Sheideman 9954960Sheideman } 10054948Sheideman 10154960Sheideman /* 10254960Sheideman * Fix the credentials. (That's the purpose of this layer.) 10354960Sheideman */ 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); 11354960Sheideman (*credpp) = crdup(savecredp); 11454948Sheideman credp = *credpp; 11554948Sheideman 11665491Spendry if (umap_bug_bypass && credp->cr_uid != 0) 11754948Sheideman printf("umap_bypass: user was %d, group %d\n", 11865491Spendry credp->cr_uid, credp->cr_gid); 11954948Sheideman 12054948Sheideman /* Map all ids in the credential structure. */ 12154948Sheideman 12265491Spendry umap_mapids(vp1->v_mount, credp); 12354948Sheideman 12465491Spendry if (umap_bug_bypass && credp->cr_uid != 0) 12554948Sheideman printf("umap_bypass: user now %d, group %d\n", 12665491Spendry credp->cr_uid, credp->cr_gid); 12754948Sheideman } 12854948Sheideman 12954960Sheideman /* BSD often keeps a credential in the componentname structure 13054960Sheideman * for speed. If there is one, it better get mapped, too. 13154960Sheideman */ 13254960Sheideman 13354960Sheideman if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) { 13454960Sheideman 13554960Sheideman compnamepp = VOPARG_OFFSETTO(struct componentname**, 13654960Sheideman descp->vdesc_componentname_offset, ap); 13754960Sheideman 13854960Sheideman compcredp = (*compnamepp)->cn_cred; 13954960Sheideman savecompcredp = compcredp; 14054960Sheideman compcredp = (*compnamepp)->cn_cred = crdup(savecompcredp); 14154960Sheideman 14265491Spendry if (umap_bug_bypass && compcredp->cr_uid != 0) 14354960Sheideman printf("umap_bypass: component credit user was %d, group %d\n", 14465491Spendry compcredp->cr_uid, compcredp->cr_gid); 14554960Sheideman 14654960Sheideman /* Map all ids in the credential structure. */ 14754960Sheideman 14865491Spendry umap_mapids(vp1->v_mount, compcredp); 14954960Sheideman 15065491Spendry if (umap_bug_bypass && compcredp->cr_uid != 0) 15154960Sheideman printf("umap_bypass: component credit user now %d, group %d\n", 15265491Spendry compcredp->cr_uid, compcredp->cr_gid); 15354960Sheideman } 15454960Sheideman 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; 16754960Sheideman for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) { 16854960Sheideman 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) { 18554960Sheideman if (descp->vdesc_flags & VDESC_VPP_WILLRELE) 18654960Sheideman goto out; 18754960Sheideman vppp = VOPARG_OFFSETTO(struct vnode***, 18865491Spendry descp->vdesc_vpp_offset, ap); 18954948Sheideman error = umap_node_create(old_vps[0]->v_mount, **vppp, *vppp); 19054948Sheideman }; 19154948Sheideman 19254960Sheideman out: 19354948Sheideman /* 19454948Sheideman * Free duplicate cred structure and restore old one. 19554948Sheideman */ 19654948Sheideman if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) { 19765491Spendry if (umap_bug_bypass && credp && credp->cr_uid != 0) 19865491Spendry printf("umap_bypass: returning-user was %d\n", 19965491Spendry credp->cr_uid); 20054948Sheideman 20154948Sheideman crfree(credp); 20254948Sheideman (*credpp) = savecredp; 20365491Spendry if (umap_bug_bypass && credpp && (*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) { 20965491Spendry if (umap_bug_bypass && compcredp && compcredp->cr_uid != 0) 21054960Sheideman printf("umap_bypass: returning-component-user was %d\n", 21165491Spendry compcredp->cr_uid); 21254960Sheideman 21354960Sheideman crfree(compcredp); 21454960Sheideman (*compnamepp)->cn_cred = savecompcredp; 21565491Spendry if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0) 21665491Spendry printf("umap_bypass: returning-component-user now %d\n", 21765491Spendry 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; 23765491Spendry int error, tmpid, nentries, gnentries; 23865491Spendry u_long (*mapdata)[2], (*gmapdata)[2]; 23954960Sheideman struct vnode **vp1p; 24054960Sheideman struct vnodeop_desc *descp = ap->a_desc; 24154948Sheideman 24254960Sheideman if (error = umap_bypass(ap)) 24355052Smckusick return (error); 24454948Sheideman /* Requires that arguments be restored. */ 24554948Sheideman ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; 24654948Sheideman 24754960Sheideman /* 24854960Sheideman * Umap needs to map the uid and gid returned by a stat 24954960Sheideman * into the proper values for this site. This involves 25054960Sheideman * finding the returned uid in the mapping information, 25154960Sheideman * translating it into the uid on the other end, 25254960Sheideman * and filling in the proper field in the vattr 25354960Sheideman * structure pointed to by ap->a_vap. The group 25454960Sheideman * is easier, since currently all groups will be 25554960Sheideman * translate to the NULLGROUP. 25654960Sheideman */ 25754948Sheideman 25854948Sheideman /* Find entry in map */ 25954948Sheideman 26054948Sheideman uid = ap->a_vap->va_uid; 26154948Sheideman gid = ap->a_vap->va_gid; 26254948Sheideman if (umap_bug_bypass) 26365491Spendry printf("umap_getattr: mapped uid = %d, mapped gid = %d\n", uid, 26454948Sheideman gid); 26554948Sheideman 26665491Spendry vp1p = VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[0], ap); 26754960Sheideman nentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_nentries; 26865491Spendry mapdata = (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_mapdata); 26954960Sheideman gnentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gnentries; 27065491Spendry gmapdata = (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gmapdata); 27154948Sheideman 27254948Sheideman /* Reverse map the uid for the vnode. Since it's a reverse 27354948Sheideman map, we can't use umap_mapids() to do it. */ 27454948Sheideman 27565491Spendry tmpid = umap_reverse_findid(uid, mapdata, nentries); 27654948Sheideman 27765491Spendry if (tmpid != -1) { 27854948Sheideman 27965491Spendry ap->a_vap->va_uid = (uid_t) tmpid; 28054948Sheideman if (umap_bug_bypass) 28165491Spendry printf("umap_getattr: original uid = %d\n", uid); 28254948Sheideman } else 28365491Spendry ap->a_vap->va_uid = (uid_t) NOBODY; 28454948Sheideman 28554948Sheideman /* Reverse map the gid for the vnode. */ 28654948Sheideman 28765491Spendry tmpid = umap_reverse_findid(gid, gmapdata, gnentries); 28854948Sheideman 28954948Sheideman if (tmpid != -1) { 29054948Sheideman 29165491Spendry ap->a_vap->va_gid = (gid_t) tmpid; 29254948Sheideman if (umap_bug_bypass) 29365491Spendry printf("umap_getattr: original gid = %d\n", gid); 29454948Sheideman } else 29565491Spendry ap->a_vap->va_gid = (gid_t) NULLGROUP; 29654948Sheideman 29755052Smckusick return (0); 29854948Sheideman } 29954948Sheideman 300*69445Smckusick /* 301*69445Smckusick * We need to verify that we are not being vgoned and then clear 302*69445Smckusick * the interlock flag as it applies only to our vnode, not the 303*69445Smckusick * vnodes below us on the stack. 304*69445Smckusick */ 30554948Sheideman int 306*69445Smckusick umap_lock(ap) 307*69445Smckusick struct vop_lock_args *ap; 308*69445Smckusick { 309*69445Smckusick struct vnode *vp = ap->a_vp; 310*69445Smckusick int error; 311*69445Smckusick 312*69445Smckusick if ((ap->a_flags & LK_INTERLOCK) == 0) 313*69445Smckusick simple_lock(&vp->v_interlock); 314*69445Smckusick if (vp->v_flag & VXLOCK) { 315*69445Smckusick vp->v_flag |= VXWANT; 316*69445Smckusick simple_unlock(&vp->v_interlock); 317*69445Smckusick tsleep((caddr_t)vp, PINOD, "unionlk1", 0); 318*69445Smckusick return (ENOENT); 319*69445Smckusick } 320*69445Smckusick simple_unlock(&vp->v_interlock); 321*69445Smckusick ap->a_flags &= ~LK_INTERLOCK; 322*69445Smckusick if (error = umap_bypass(ap)) 323*69445Smckusick return (error); 324*69445Smckusick return (0); 325*69445Smckusick } 326*69445Smckusick 327*69445Smckusick int 32855052Smckusick umap_inactive(ap) 32955052Smckusick struct vop_inactive_args /* { 33055052Smckusick struct vnode *a_vp; 33155052Smckusick } */ *ap; 33254948Sheideman { 33354948Sheideman /* 33454948Sheideman * Do nothing (and _don't_ bypass). 33554948Sheideman * Wait to vrele lowervp until reclaim, 33654948Sheideman * so that until then our umap_node is in the 33754948Sheideman * cache and reusable. 33854948Sheideman * 33954948Sheideman */ 34055052Smckusick return (0); 34154948Sheideman } 34254948Sheideman 34354948Sheideman int 34455052Smckusick umap_reclaim(ap) 34555052Smckusick struct vop_reclaim_args /* { 34655052Smckusick struct vnode *a_vp; 34755052Smckusick } */ *ap; 34854948Sheideman { 34954960Sheideman struct vnode *vp = ap->a_vp; 35054960Sheideman struct umap_node *xp = VTOUMAP(vp); 35154960Sheideman struct vnode *lowervp = xp->umap_lowervp; 35254960Sheideman 35354960Sheideman /* After this assignment, this node will not be re-used. */ 35454960Sheideman xp->umap_lowervp = NULL; 35567717Smckusick LIST_REMOVE(xp, umap_hash); 35654960Sheideman FREE(vp->v_data, M_TEMP); 35754960Sheideman vp->v_data = NULL; 35865491Spendry vrele(lowervp); 35955052Smckusick return (0); 36054948Sheideman } 36154948Sheideman 36254948Sheideman int 36355052Smckusick umap_strategy(ap) 36455052Smckusick struct vop_strategy_args /* { 36555052Smckusick struct buf *a_bp; 36655052Smckusick } */ *ap; 36754948Sheideman { 36854960Sheideman struct buf *bp = ap->a_bp; 36954960Sheideman int error; 37054960Sheideman struct vnode *savedvp; 37154948Sheideman 37254960Sheideman savedvp = bp->b_vp; 37354960Sheideman bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp); 37454960Sheideman 37554960Sheideman error = VOP_STRATEGY(ap->a_bp); 37654960Sheideman 37754960Sheideman bp->b_vp = savedvp; 37854960Sheideman 37955052Smckusick return (error); 38054948Sheideman } 38154948Sheideman 38254948Sheideman int 38355052Smckusick umap_bwrite(ap) 38455052Smckusick struct vop_bwrite_args /* { 38555052Smckusick struct buf *a_bp; 38655052Smckusick } */ *ap; 38754948Sheideman { 38854960Sheideman struct buf *bp = ap->a_bp; 38954948Sheideman int error; 39054948Sheideman struct vnode *savedvp; 39154948Sheideman 39254960Sheideman savedvp = bp->b_vp; 39354960Sheideman bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp); 39454948Sheideman 39554960Sheideman error = VOP_BWRITE(ap->a_bp); 39654948Sheideman 39754960Sheideman bp->b_vp = savedvp; 39854948Sheideman 39955052Smckusick return (error); 40054948Sheideman } 40154948Sheideman 40254948Sheideman 40354948Sheideman int 40455052Smckusick umap_print(ap) 40555052Smckusick struct vop_print_args /* { 40655052Smckusick struct vnode *a_vp; 40755052Smckusick } */ *ap; 40854948Sheideman { 40965491Spendry struct vnode *vp = ap->a_vp; 41065491Spendry printf("\ttag VT_UMAPFS, vp=%x, lowervp=%x\n", vp, UMAPVPTOLOWERVP(vp)); 41155052Smckusick return (0); 41254948Sheideman } 41354948Sheideman 41454960Sheideman int 41554960Sheideman umap_rename(ap) 41655052Smckusick struct vop_rename_args /* { 41755052Smckusick struct vnode *a_fdvp; 41855052Smckusick struct vnode *a_fvp; 41955052Smckusick struct componentname *a_fcnp; 42055052Smckusick struct vnode *a_tdvp; 42155052Smckusick struct vnode *a_tvp; 42255052Smckusick struct componentname *a_tcnp; 42355052Smckusick } */ *ap; 42454960Sheideman { 42554960Sheideman int error; 42654960Sheideman struct componentname *compnamep; 42754960Sheideman struct ucred *compcredp, *savecompcredp; 42854960Sheideman struct vnode *vp; 42954948Sheideman 43055585Sheideman /* 43155585Sheideman * Rename is irregular, having two componentname structures. 43255585Sheideman * We need to map the cre in the second structure, 43355585Sheideman * and then bypass takes care of the rest. 43454960Sheideman */ 43554960Sheideman 43654960Sheideman vp = ap->a_fdvp; 43754960Sheideman compnamep = ap->a_tcnp; 43854960Sheideman compcredp = compnamep->cn_cred; 43954960Sheideman 44054960Sheideman savecompcredp = compcredp; 44154960Sheideman compcredp = compnamep->cn_cred = crdup(savecompcredp); 44254960Sheideman 44365491Spendry if (umap_bug_bypass && compcredp->cr_uid != 0) 44454960Sheideman printf("umap_rename: rename component credit user was %d, group %d\n", 44565491Spendry compcredp->cr_uid, compcredp->cr_gid); 44654960Sheideman 44754960Sheideman /* Map all ids in the credential structure. */ 44854960Sheideman 44965491Spendry umap_mapids(vp->v_mount, compcredp); 45054960Sheideman 45165491Spendry if (umap_bug_bypass && compcredp->cr_uid != 0) 45254960Sheideman printf("umap_rename: rename component credit user now %d, group %d\n", 45365491Spendry compcredp->cr_uid, compcredp->cr_gid); 45454960Sheideman 45555585Sheideman error = umap_bypass(ap); 45654960Sheideman 45754960Sheideman /* Restore the additional mapped componentname cred structure. */ 45854960Sheideman 45954960Sheideman crfree(compcredp); 46054960Sheideman compnamep->cn_cred = savecompcredp; 46155585Sheideman 46255585Sheideman return error; 46354960Sheideman } 46454960Sheideman 46554948Sheideman /* 46654948Sheideman * Global vfs data structures 46754948Sheideman */ 46854948Sheideman /* 46965491Spendry * XXX - strategy, bwrite are hand coded currently. They should 47054948Sheideman * go away with a merged buffer/block cache. 47154948Sheideman * 47254948Sheideman */ 47354948Sheideman int (**umap_vnodeop_p)(); 47454948Sheideman struct vnodeopv_entry_desc umap_vnodeop_entries[] = { 47554948Sheideman { &vop_default_desc, umap_bypass }, 47654948Sheideman 47754948Sheideman { &vop_getattr_desc, umap_getattr }, 478*69445Smckusick { &vop_lock_desc, umap_lock }, 47954948Sheideman { &vop_inactive_desc, umap_inactive }, 48054948Sheideman { &vop_reclaim_desc, umap_reclaim }, 48154948Sheideman { &vop_print_desc, umap_print }, 48255585Sheideman { &vop_rename_desc, umap_rename }, 48354948Sheideman 48454948Sheideman { &vop_strategy_desc, umap_strategy }, 48554960Sheideman { &vop_bwrite_desc, umap_bwrite }, 48654948Sheideman 48765491Spendry { (struct vnodeop_desc*) NULL, (int(*)()) NULL } 48854948Sheideman }; 48954948Sheideman struct vnodeopv_desc umap_vnodeop_opv_desc = 49054948Sheideman { &umap_vnodeop_p, umap_vnodeop_entries }; 491