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*55052Smckusick * @(#)umap_vnops.c 1.3 (Berkeley) 07/12/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> 26*55052Smckusick #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) 37*55052Smckusick struct vop_generic_args /* { 38*55052Smckusick struct vnodeop_desc *a_desc; 39*55052Smckusick <other random data follows, presumably> 40*55052Smckusick } */ *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) 229*55052Smckusick struct vop_getattr_args /* { 230*55052Smckusick struct vnode *a_vp; 231*55052Smckusick struct vattr *a_vap; 232*55052Smckusick struct ucred *a_cred; 233*55052Smckusick struct proc *a_p; 234*55052Smckusick } */ *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)) 242*55052Smckusick 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 296*55052Smckusick return (0); 29754948Sheideman } 29854948Sheideman 29954948Sheideman int 300*55052Smckusick umap_inactive(ap) 301*55052Smckusick struct vop_inactive_args /* { 302*55052Smckusick struct vnode *a_vp; 303*55052Smckusick } */ *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 */ 312*55052Smckusick return (0); 31354948Sheideman } 31454948Sheideman 31554948Sheideman int 316*55052Smckusick umap_reclaim(ap) 317*55052Smckusick struct vop_reclaim_args /* { 318*55052Smckusick struct vnode *a_vp; 319*55052Smckusick } */ *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); 331*55052Smckusick return (0); 33254948Sheideman } 33354948Sheideman 33454948Sheideman int 335*55052Smckusick umap_strategy(ap) 336*55052Smckusick struct vop_strategy_args /* { 337*55052Smckusick struct buf *a_bp; 338*55052Smckusick } */ *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 351*55052Smckusick return (error); 35254948Sheideman } 35354948Sheideman 35454948Sheideman int 355*55052Smckusick umap_bwrite(ap) 356*55052Smckusick struct vop_bwrite_args /* { 357*55052Smckusick struct buf *a_bp; 358*55052Smckusick } */ *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 371*55052Smckusick return (error); 37254948Sheideman } 37354948Sheideman 37454948Sheideman 37554948Sheideman int 376*55052Smckusick umap_print(ap) 377*55052Smckusick struct vop_print_args /* { 378*55052Smckusick struct vnode *a_vp; 379*55052Smckusick } */ *ap; 38054948Sheideman { 38154948Sheideman register struct vnode *vp = ap->a_vp; 38254948Sheideman printf ("\ttag VT_UMAPFS, vp=%x, lowervp=%x\n", vp, UMAPVPTOLOWERVP(vp)); 383*55052Smckusick return (0); 38454948Sheideman } 38554948Sheideman 38654960Sheideman int 38754960Sheideman umap_rename(ap) 388*55052Smckusick struct vop_rename_args /* { 389*55052Smckusick struct vnode *a_fdvp; 390*55052Smckusick struct vnode *a_fvp; 391*55052Smckusick struct componentname *a_fcnp; 392*55052Smckusick struct vnode *a_tdvp; 393*55052Smckusick struct vnode *a_tvp; 394*55052Smckusick struct componentname *a_tcnp; 395*55052Smckusick } */ *ap; 39654960Sheideman { 39754960Sheideman int error; 39854960Sheideman struct componentname *compnamep; 39954960Sheideman struct ucred *compcredp, *savecompcredp; 40054960Sheideman struct vnode *vp; 40154948Sheideman 40254960Sheideman /* Now map the second componentname structure kept in this vop's 40354960Sheideman * arguments. 40454960Sheideman */ 40554960Sheideman 40654960Sheideman vp = ap->a_fdvp; 40754960Sheideman compnamep = ap->a_tcnp; 40854960Sheideman compcredp = compnamep->cn_cred; 40954960Sheideman 41054960Sheideman savecompcredp = compcredp; 41154960Sheideman compcredp = compnamep->cn_cred = crdup(savecompcredp); 41254960Sheideman 41354960Sheideman if (umap_bug_bypass && compcredp->cr_uid != 0 ) 41454960Sheideman printf("umap_rename: rename component credit user was %d, group %d\n", 41554960Sheideman compcredp->cr_uid,compcredp->cr_gid); 41654960Sheideman 41754960Sheideman /* Map all ids in the credential structure. */ 41854960Sheideman 41954960Sheideman umap_mapids(vp->v_mount,compcredp); 42054960Sheideman 42154960Sheideman if (umap_bug_bypass && compcredp->cr_uid != 0 ) 42254960Sheideman printf("umap_rename: rename component credit user now %d, group %d\n", 42354960Sheideman compcredp->cr_uid,compcredp->cr_gid); 42454960Sheideman 42554960Sheideman if (error = umap_bypass(ap)) 426*55052Smckusick return (error); 42754960Sheideman 42854960Sheideman /* Restore the additional mapped componentname cred structure. */ 42954960Sheideman 43054960Sheideman crfree(compcredp); 43154960Sheideman compnamep->cn_cred = savecompcredp; 43254960Sheideman 43354960Sheideman } 43454960Sheideman 43554948Sheideman /* 43654948Sheideman * Global vfs data structures 43754948Sheideman */ 43854948Sheideman /* 43954960Sheideman * XXX - strategy,bwrite are hand coded currently. They should 44054948Sheideman * go away with a merged buffer/block cache. 44154948Sheideman * 44254948Sheideman */ 44354948Sheideman int (**umap_vnodeop_p)(); 44454948Sheideman struct vnodeopv_entry_desc umap_vnodeop_entries[] = { 44554948Sheideman { &vop_default_desc, umap_bypass }, 44654948Sheideman 44754948Sheideman { &vop_getattr_desc, umap_getattr }, 44854948Sheideman { &vop_inactive_desc, umap_inactive }, 44954948Sheideman { &vop_reclaim_desc, umap_reclaim }, 45054948Sheideman { &vop_print_desc, umap_print }, 45154948Sheideman 45254948Sheideman { &vop_strategy_desc, umap_strategy }, 45354960Sheideman { &vop_bwrite_desc, umap_bwrite }, 45454948Sheideman 45554960Sheideman { (struct vnodeop_desc*)NULL, (int(*)())NULL } 45654948Sheideman }; 45754948Sheideman struct vnodeopv_desc umap_vnodeop_opv_desc = 45854948Sheideman { &umap_vnodeop_p, umap_vnodeop_entries }; 459