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*65491Spendry * @(#)umap_vnops.c 8.3 (Berkeley) 01/05/94 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" */ 43*65491Spendry struct ucred **credpp = 0, *credp = 0; 44*65491Spendry struct ucred *savecredp, *savecompcredp = 0; 45*65491Spendry struct ucred *compcredp = 0; 46*65491Spendry struct vnode **this_vp_p; 4754948Sheideman int error; 48*65491Spendry struct vnode *old_vps[VDESC_MAX_VPS]; 49*65491Spendry 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; 54*65491Spendry 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 = 78*65491Spendry VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[i], ap); 7954948Sheideman 80*65491Spendry 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 116*65491Spendry if (umap_bug_bypass && credp->cr_uid != 0) 11754948Sheideman printf("umap_bypass: user was %d, group %d\n", 118*65491Spendry credp->cr_uid, credp->cr_gid); 11954948Sheideman 12054948Sheideman /* Map all ids in the credential structure. */ 12154948Sheideman 122*65491Spendry umap_mapids(vp1->v_mount, credp); 12354948Sheideman 124*65491Spendry if (umap_bug_bypass && credp->cr_uid != 0) 12554948Sheideman printf("umap_bypass: user now %d, group %d\n", 126*65491Spendry 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 142*65491Spendry if (umap_bug_bypass && compcredp->cr_uid != 0) 14354960Sheideman printf("umap_bypass: component credit user was %d, group %d\n", 144*65491Spendry compcredp->cr_uid, compcredp->cr_gid); 14554960Sheideman 14654960Sheideman /* Map all ids in the credential structure. */ 14754960Sheideman 148*65491Spendry umap_mapids(vp1->v_mount, compcredp); 14954960Sheideman 150*65491Spendry if (umap_bug_bypass && compcredp->cr_uid != 0) 15154960Sheideman printf("umap_bypass: component credit user now %d, group %d\n", 152*65491Spendry 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***, 188*65491Spendry 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) { 197*65491Spendry if (umap_bug_bypass && credp && credp->cr_uid != 0) 198*65491Spendry printf("umap_bypass: returning-user was %d\n", 199*65491Spendry credp->cr_uid); 20054948Sheideman 20154948Sheideman crfree(credp); 20254948Sheideman (*credpp) = savecredp; 203*65491Spendry 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) { 209*65491Spendry if (umap_bug_bypass && compcredp && compcredp->cr_uid != 0) 21054960Sheideman printf("umap_bypass: returning-component-user was %d\n", 211*65491Spendry compcredp->cr_uid); 21254960Sheideman 21354960Sheideman crfree(compcredp); 21454960Sheideman (*compnamepp)->cn_cred = savecompcredp; 215*65491Spendry if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0) 216*65491Spendry printf("umap_bypass: returning-component-user now %d\n", 217*65491Spendry 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; 237*65491Spendry int error, tmpid, nentries, gnentries; 238*65491Spendry 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) 263*65491Spendry printf("umap_getattr: mapped uid = %d, mapped gid = %d\n", uid, 26454948Sheideman gid); 26554948Sheideman 266*65491Spendry vp1p = VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[0], ap); 26754960Sheideman nentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_nentries; 268*65491Spendry mapdata = (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_mapdata); 26954960Sheideman gnentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gnentries; 270*65491Spendry 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 275*65491Spendry tmpid = umap_reverse_findid(uid, mapdata, nentries); 27654948Sheideman 277*65491Spendry if (tmpid != -1) { 27854948Sheideman 279*65491Spendry ap->a_vap->va_uid = (uid_t) tmpid; 28054948Sheideman if (umap_bug_bypass) 281*65491Spendry printf("umap_getattr: original uid = %d\n", uid); 28254948Sheideman } else 283*65491Spendry ap->a_vap->va_uid = (uid_t) NOBODY; 28454948Sheideman 28554948Sheideman /* Reverse map the gid for the vnode. */ 28654948Sheideman 287*65491Spendry tmpid = umap_reverse_findid(gid, gmapdata, gnentries); 28854948Sheideman 28954948Sheideman if (tmpid != -1) { 29054948Sheideman 291*65491Spendry ap->a_vap->va_gid = (gid_t) tmpid; 29254948Sheideman if (umap_bug_bypass) 293*65491Spendry printf("umap_getattr: original gid = %d\n", gid); 29454948Sheideman } else 295*65491Spendry ap->a_vap->va_gid = (gid_t) NULLGROUP; 29654948Sheideman 29755052Smckusick return (0); 29854948Sheideman } 29954948Sheideman 30054948Sheideman int 30155052Smckusick umap_inactive(ap) 30255052Smckusick struct vop_inactive_args /* { 30355052Smckusick struct vnode *a_vp; 30455052Smckusick } */ *ap; 30554948Sheideman { 30654948Sheideman /* 30754948Sheideman * Do nothing (and _don't_ bypass). 30854948Sheideman * Wait to vrele lowervp until reclaim, 30954948Sheideman * so that until then our umap_node is in the 31054948Sheideman * cache and reusable. 31154948Sheideman * 31254948Sheideman */ 31355052Smckusick return (0); 31454948Sheideman } 31554948Sheideman 31654948Sheideman int 31755052Smckusick umap_reclaim(ap) 31855052Smckusick struct vop_reclaim_args /* { 31955052Smckusick struct vnode *a_vp; 32055052Smckusick } */ *ap; 32154948Sheideman { 32254960Sheideman struct vnode *vp = ap->a_vp; 32354960Sheideman struct umap_node *xp = VTOUMAP(vp); 32454960Sheideman struct vnode *lowervp = xp->umap_lowervp; 32554960Sheideman 32654960Sheideman /* After this assignment, this node will not be re-used. */ 32754960Sheideman xp->umap_lowervp = NULL; 32854960Sheideman remque(xp); 32954960Sheideman FREE(vp->v_data, M_TEMP); 33054960Sheideman vp->v_data = NULL; 331*65491Spendry vrele(lowervp); 33255052Smckusick return (0); 33354948Sheideman } 33454948Sheideman 33554948Sheideman int 33655052Smckusick umap_strategy(ap) 33755052Smckusick struct vop_strategy_args /* { 33855052Smckusick struct buf *a_bp; 33955052Smckusick } */ *ap; 34054948Sheideman { 34154960Sheideman struct buf *bp = ap->a_bp; 34254960Sheideman int error; 34354960Sheideman struct vnode *savedvp; 34454948Sheideman 34554960Sheideman savedvp = bp->b_vp; 34654960Sheideman bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp); 34754960Sheideman 34854960Sheideman error = VOP_STRATEGY(ap->a_bp); 34954960Sheideman 35054960Sheideman bp->b_vp = savedvp; 35154960Sheideman 35255052Smckusick return (error); 35354948Sheideman } 35454948Sheideman 35554948Sheideman int 35655052Smckusick umap_bwrite(ap) 35755052Smckusick struct vop_bwrite_args /* { 35855052Smckusick struct buf *a_bp; 35955052Smckusick } */ *ap; 36054948Sheideman { 36154960Sheideman struct buf *bp = ap->a_bp; 36254948Sheideman int error; 36354948Sheideman struct vnode *savedvp; 36454948Sheideman 36554960Sheideman savedvp = bp->b_vp; 36654960Sheideman bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp); 36754948Sheideman 36854960Sheideman error = VOP_BWRITE(ap->a_bp); 36954948Sheideman 37054960Sheideman bp->b_vp = savedvp; 37154948Sheideman 37255052Smckusick return (error); 37354948Sheideman } 37454948Sheideman 37554948Sheideman 37654948Sheideman int 37755052Smckusick umap_print(ap) 37855052Smckusick struct vop_print_args /* { 37955052Smckusick struct vnode *a_vp; 38055052Smckusick } */ *ap; 38154948Sheideman { 382*65491Spendry struct vnode *vp = ap->a_vp; 383*65491Spendry printf("\ttag VT_UMAPFS, vp=%x, lowervp=%x\n", vp, UMAPVPTOLOWERVP(vp)); 38455052Smckusick return (0); 38554948Sheideman } 38654948Sheideman 38754960Sheideman int 38854960Sheideman umap_rename(ap) 38955052Smckusick struct vop_rename_args /* { 39055052Smckusick struct vnode *a_fdvp; 39155052Smckusick struct vnode *a_fvp; 39255052Smckusick struct componentname *a_fcnp; 39355052Smckusick struct vnode *a_tdvp; 39455052Smckusick struct vnode *a_tvp; 39555052Smckusick struct componentname *a_tcnp; 39655052Smckusick } */ *ap; 39754960Sheideman { 39854960Sheideman int error; 39954960Sheideman struct componentname *compnamep; 40054960Sheideman struct ucred *compcredp, *savecompcredp; 40154960Sheideman struct vnode *vp; 40254948Sheideman 40355585Sheideman /* 40455585Sheideman * Rename is irregular, having two componentname structures. 40555585Sheideman * We need to map the cre in the second structure, 40655585Sheideman * and then bypass takes care of the rest. 40754960Sheideman */ 40854960Sheideman 40954960Sheideman vp = ap->a_fdvp; 41054960Sheideman compnamep = ap->a_tcnp; 41154960Sheideman compcredp = compnamep->cn_cred; 41254960Sheideman 41354960Sheideman savecompcredp = compcredp; 41454960Sheideman compcredp = compnamep->cn_cred = crdup(savecompcredp); 41554960Sheideman 416*65491Spendry if (umap_bug_bypass && compcredp->cr_uid != 0) 41754960Sheideman printf("umap_rename: rename component credit user was %d, group %d\n", 418*65491Spendry compcredp->cr_uid, compcredp->cr_gid); 41954960Sheideman 42054960Sheideman /* Map all ids in the credential structure. */ 42154960Sheideman 422*65491Spendry umap_mapids(vp->v_mount, compcredp); 42354960Sheideman 424*65491Spendry if (umap_bug_bypass && compcredp->cr_uid != 0) 42554960Sheideman printf("umap_rename: rename component credit user now %d, group %d\n", 426*65491Spendry compcredp->cr_uid, compcredp->cr_gid); 42754960Sheideman 42855585Sheideman error = umap_bypass(ap); 42954960Sheideman 43054960Sheideman /* Restore the additional mapped componentname cred structure. */ 43154960Sheideman 43254960Sheideman crfree(compcredp); 43354960Sheideman compnamep->cn_cred = savecompcredp; 43455585Sheideman 43555585Sheideman return error; 43654960Sheideman } 43754960Sheideman 43854948Sheideman /* 43954948Sheideman * Global vfs data structures 44054948Sheideman */ 44154948Sheideman /* 442*65491Spendry * XXX - strategy, bwrite are hand coded currently. They should 44354948Sheideman * go away with a merged buffer/block cache. 44454948Sheideman * 44554948Sheideman */ 44654948Sheideman int (**umap_vnodeop_p)(); 44754948Sheideman struct vnodeopv_entry_desc umap_vnodeop_entries[] = { 44854948Sheideman { &vop_default_desc, umap_bypass }, 44954948Sheideman 45054948Sheideman { &vop_getattr_desc, umap_getattr }, 45154948Sheideman { &vop_inactive_desc, umap_inactive }, 45254948Sheideman { &vop_reclaim_desc, umap_reclaim }, 45354948Sheideman { &vop_print_desc, umap_print }, 45455585Sheideman { &vop_rename_desc, umap_rename }, 45554948Sheideman 45654948Sheideman { &vop_strategy_desc, umap_strategy }, 45754960Sheideman { &vop_bwrite_desc, umap_bwrite }, 45854948Sheideman 459*65491Spendry { (struct vnodeop_desc*) NULL, (int(*)()) NULL } 46054948Sheideman }; 46154948Sheideman struct vnodeopv_desc umap_vnodeop_opv_desc = 46254948Sheideman { &umap_vnodeop_p, umap_vnodeop_entries }; 463