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