* Copyright (c) 1992 The Regents of the University of California
* This code is derived from software donated to Berkeley by
* the UCLA Ficus project.
* %sccs.include.redist.c%
* @(#)umap_vnops.c 1.2 (Berkeley) %G%
* @(#)umap_vnops.c 1.5 (Berkeley) 7/10/92
int umap_bug_bypass
= 0; /* for debugging: enables bypass printf'ing */
* This is the 10-Apr-92 bypass routine.
* See null_vnops.c:null_bypass for more details.
struct vop_generic_args
*ap
;
extern int (**umap_vnodeop_p
)(); /* not extern, really "forward" */
int *gmapdata
, gnentries
;
struct ucred
**credpp
,*credp
, *savecredp
, *saveucredp
, *savecompcredp
;
register struct vnode
**this_vp_p
;
struct vnode
*old_vps
[VDESC_MAX_VPS
], *vp1
;
struct vnode
**vps_p
[VDESC_MAX_VPS
];
struct vnodeop_desc
*descp
= ap
->a_desc
;
struct componentname
**compnamepp
;
printf ("umap_bypass: %s\n", descp
->vdesc_name
);
* We require at least one vp.
if (descp
->vdesc_vp_offsets
== NULL
||
descp
->vdesc_vp_offsets
[0] == VDESC_NO_OFFSET
)
panic ("umap_bypass: no vp's in map.\n");
* Map the vnodes going in.
* Later, we'll invoke the operation based on
* the first mapped vnode's operation vector.
reles
= descp
->vdesc_flags
;
for (i
= 0; i
< VDESC_MAX_VPS
; reles
>>= 1, i
++) {
if (descp
->vdesc_vp_offsets
[i
] == VDESC_NO_OFFSET
)
break; /* bail out at end of list */
VOPARG_OFFSETTO(struct vnode
**,descp
->vdesc_vp_offsets
[i
],ap
);
* We're not guaranteed that any but the first vnode
* are of our type. Check for and don't map any
* that aren't. (Must map first vp or vclean fails.)
if (i
&& (*this_vp_p
)->v_op
!= umap_vnodeop_p
) {
*(vps_p
[i
]) = UMAPVPTOLOWERVP(*this_vp_p
);
* Fix the credentials. (That's the purpose of this layer.)
if (descp
->vdesc_cred_offset
!= VDESC_NO_OFFSET
) {
credpp
= VOPARG_OFFSETTO(struct ucred
**,
descp
->vdesc_cred_offset
, ap
);
(*credpp
) = crdup(savecredp
);
if (umap_bug_bypass
&& credp
->cr_uid
!= 0 )
printf("umap_bypass: user was %d, group %d\n",
credp
->cr_uid
,credp
->cr_gid
);
/* Map all ids in the credential structure. */
umap_mapids(vp1
->v_mount
,credp
);
if (umap_bug_bypass
&& credp
->cr_uid
!= 0 )
printf("umap_bypass: user now %d, group %d\n",
credp
->cr_uid
,credp
->cr_gid
);
/* BSD often keeps a credential in the componentname structure
* for speed. If there is one, it better get mapped, too.
if (descp
->vdesc_componentname_offset
!= VDESC_NO_OFFSET
) {
compnamepp
= VOPARG_OFFSETTO(struct componentname
**,
descp
->vdesc_componentname_offset
, ap
);
compcredp
= (*compnamepp
)->cn_cred
;
savecompcredp
= compcredp
;
compcredp
= (*compnamepp
)->cn_cred
= crdup(savecompcredp
);
if (umap_bug_bypass
&& compcredp
->cr_uid
!= 0 )
printf("umap_bypass: component credit user was %d, group %d\n",
compcredp
->cr_uid
,compcredp
->cr_gid
);
/* Map all ids in the credential structure. */
umap_mapids(vp1
->v_mount
,compcredp
);
if (umap_bug_bypass
&& compcredp
->cr_uid
!= 0 )
printf("umap_bypass: component credit user now %d, group %d\n",
compcredp
->cr_uid
,compcredp
->cr_gid
);
* Call the operation on the lower layer
* with the modified argument structure.
error
= VCALL(*(vps_p
[0]), descp
->vdesc_offset
, ap
);
* Maintain the illusion of call-by-value
* by restoring vnodes in the argument structure
* to their original value.
reles
= descp
->vdesc_flags
;
for (i
= 0; i
< VDESC_MAX_VPS
; reles
>>= 1, i
++) {
if (descp
->vdesc_vp_offsets
[i
] == VDESC_NO_OFFSET
)
break; /* bail out at end of list */
*(vps_p
[i
]) = old_vps
[i
];
* Map the possible out-going vpp
* (Assumes that the lower layer always returns
* a VREF'ed vpp unless it gets an error.)
if (descp
->vdesc_vpp_offset
!= VDESC_NO_OFFSET
&&
!(descp
->vdesc_flags
& VDESC_NOMAP_VPP
) &&
if (descp
->vdesc_flags
& VDESC_VPP_WILLRELE
)
vppp
= VOPARG_OFFSETTO(struct vnode
***,
descp
->vdesc_vpp_offset
,ap
);
error
= umap_node_create(old_vps
[0]->v_mount
, **vppp
, *vppp
);
* Free duplicate cred structure and restore old one.
if (descp
->vdesc_cred_offset
!= VDESC_NO_OFFSET
) {
if (umap_bug_bypass
&& credp
->cr_uid
!= 0 )
printf("umap_bypass: returning-user was %d\n", credp
->cr_uid
);
if (umap_bug_bypass
&& (*credpp
)->cr_uid
!= 0 )
printf("umap_bypass: returning-user now %d\n\n",
if (descp
->vdesc_componentname_offset
!= VDESC_NO_OFFSET
) {
if (umap_bug_bypass
&& compcredp
->cr_uid
!= 0 )
printf("umap_bypass: returning-component-user was %d\n",
(*compnamepp
)->cn_cred
= savecompcredp
;
if (umap_bug_bypass
&& (*credpp
)->cr_uid
!= 0 )
printf("umap_bypass: returning-component-user now %d\n\n",
* We handle getattr to change the fsid.
struct vop_getattr_args
*ap
;
int error
, tmpid
, *mapdata
, nentries
, *gmapdata
, gnentries
;
struct vnodeop_desc
*descp
= ap
->a_desc
;
if (error
= umap_bypass(ap
))
/* Requires that arguments be restored. */
ap
->a_vap
->va_fsid
= ap
->a_vp
->v_mount
->mnt_stat
.f_fsid
.val
[0];
* Umap needs to map the uid and gid returned by a stat
* into the proper values for this site. This involves
* finding the returned uid in the mapping information,
* translating it into the uid on the other end,
* and filling in the proper field in the vattr
* structure pointed to by ap->a_vap. The group
* is easier, since currently all groups will be
* translate to the NULLGROUP.
printf("umap_getattr: mapped uid = %d, mapped gid = %d\n",uid
,
vp1p
= VOPARG_OFFSETTO(struct vnode
**,descp
->vdesc_vp_offsets
[0],ap
);
nentries
= MOUNTTOUMAPMOUNT((*vp1p
)->v_mount
)->info_nentries
;
mapdata
= &(MOUNTTOUMAPMOUNT((*vp1p
)->v_mount
)->info_mapdata
[0][0]);
gnentries
= MOUNTTOUMAPMOUNT((*vp1p
)->v_mount
)->info_gnentries
;
gmapdata
= &(MOUNTTOUMAPMOUNT((*vp1p
)->v_mount
)->info_gmapdata
[0][0]);
/* Reverse map the uid for the vnode. Since it's a reverse
map, we can't use umap_mapids() to do it. */
tmpid
= umap_reverse_findid(uid
,mapdata
,nentries
);
ap
->a_vap
->va_uid
= (uid_t
)tmpid
;
printf("umap_getattr: original uid = %d\n",uid
);
ap
->a_vap
->va_uid
= (uid_t
)NOBODY
;
/* Reverse map the gid for the vnode. */
tmpid
= umap_reverse_findid(gid
,gmapdata
,gnentries
);
ap
->a_vap
->va_gid
= (gid_t
)tmpid
;
printf("umap_getattr: original gid = %d\n",gid
);
ap
->a_vap
->va_gid
= (gid_t
)NULLGROUP
;
struct vop_inactive_args
*ap
;
* Do nothing (and _don't_ bypass).
* Wait to vrele lowervp until reclaim,
* so that until then our umap_node is in the
struct vop_reclaim_args
*ap
;
struct vnode
*vp
= ap
->a_vp
;
struct umap_node
*xp
= VTOUMAP(vp
);
struct vnode
*lowervp
= xp
->umap_lowervp
;
/* After this assignment, this node will not be re-used. */
FREE(vp
->v_data
, M_TEMP
);
struct vop_strategy_args
*ap
;
struct buf
*bp
= ap
->a_bp
;
bp
->b_vp
= UMAPVPTOLOWERVP(bp
->b_vp
);
error
= VOP_STRATEGY(ap
->a_bp
);
struct vop_bwrite_args
*ap
;
struct buf
*bp
= ap
->a_bp
;
bp
->b_vp
= UMAPVPTOLOWERVP(bp
->b_vp
);
error
= VOP_BWRITE(ap
->a_bp
);
struct vop_print_args
*ap
;
register struct vnode
*vp
= ap
->a_vp
;
printf ("\ttag VT_UMAPFS, vp=%x, lowervp=%x\n", vp
, UMAPVPTOLOWERVP(vp
));
struct vop_rename_args
*ap
;
struct componentname
*compnamep
;
struct ucred
*compcredp
, *savecompcredp
;
/* Now map the second componentname structure kept in this vop's
compcredp
= compnamep
->cn_cred
;
savecompcredp
= compcredp
;
compcredp
= compnamep
->cn_cred
= crdup(savecompcredp
);
if (umap_bug_bypass
&& compcredp
->cr_uid
!= 0 )
printf("umap_rename: rename component credit user was %d, group %d\n",
compcredp
->cr_uid
,compcredp
->cr_gid
);
/* Map all ids in the credential structure. */
umap_mapids(vp
->v_mount
,compcredp
);
if (umap_bug_bypass
&& compcredp
->cr_uid
!= 0 )
printf("umap_rename: rename component credit user now %d, group %d\n",
compcredp
->cr_uid
,compcredp
->cr_gid
);
if (error
= umap_bypass(ap
))
/* Restore the additional mapped componentname cred structure. */
compnamep
->cn_cred
= savecompcredp
;
* Global vfs data structures
* XXX - strategy,bwrite are hand coded currently. They should
* go away with a merged buffer/block cache.
int (**umap_vnodeop_p
)();
struct vnodeopv_entry_desc umap_vnodeop_entries
[] = {
{ &vop_default_desc
, umap_bypass
},
{ &vop_getattr_desc
, umap_getattr
},
{ &vop_inactive_desc
, umap_inactive
},
{ &vop_reclaim_desc
, umap_reclaim
},
{ &vop_print_desc
, umap_print
},
{ &vop_strategy_desc
, umap_strategy
},
{ &vop_bwrite_desc
, umap_bwrite
},
{ (struct vnodeop_desc
*)NULL
, (int(*)())NULL
}
struct vnodeopv_desc umap_vnodeop_opv_desc
=
{ &umap_vnodeop_p
, umap_vnodeop_entries
};