diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2003-05-12 21:02:11 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2003-05-12 21:02:11 +0000 |
commit | 5aabec7aaeb472ceb236b7d6afd3ec732db1cdef (patch) | |
tree | a56e94c7de277a39c06f611e35fd7862484ddf36 /sys/miscfs | |
parent | 104c9cee2b7581512ef5cf06fb24402ea5fa56c5 (diff) |
umapfs uses the new layer stuff now too.
Diffstat (limited to 'sys/miscfs')
-rw-r--r-- | sys/miscfs/umapfs/umap.h | 73 | ||||
-rw-r--r-- | sys/miscfs/umapfs/umap_subr.c | 368 | ||||
-rw-r--r-- | sys/miscfs/umapfs/umap_vfsops.c | 321 | ||||
-rw-r--r-- | sys/miscfs/umapfs/umap_vnops.c | 477 |
4 files changed, 434 insertions, 805 deletions
diff --git a/sys/miscfs/umapfs/umap.h b/sys/miscfs/umapfs/umap.h index 7b879f8f162..89184907c29 100644 --- a/sys/miscfs/umapfs/umap.h +++ b/sys/miscfs/umapfs/umap.h @@ -1,5 +1,5 @@ -/* $OpenBSD: umap.h,v 1.9 2002/03/14 01:27:08 millert Exp $ */ -/* $NetBSD: umap.h,v 1.6 1996/02/09 22:41:00 christos Exp $ */ +/* $OpenBSD: umap.h,v 1.10 2003/05/12 21:02:10 tedu Exp $ */ +/* $NetBSD: umap.h,v 1.9 1999/07/08 01:19:06 wrstuden Exp $ */ /* * Copyright (c) 1992, 1993 @@ -37,63 +37,80 @@ * SUCH DAMAGE. * * from: @(#)null_vnops.c 1.5 (Berkeley) 7/10/92 - * @(#)umap.h 8.3 (Berkeley) 1/21/94 + * @(#)umap.h 8.4 (Berkeley) 8/20/94 */ +#include <miscfs/genfs/layer.h> + #define UMAPFILEENTRIES 64 #define GMAPFILEENTRIES 16 #define NOBODY 32767 #define NULLGROUP 65534 -typedef u_int32_t id_t; -typedef id_t (*id_map_t)[2]; - struct umap_args { - char *target; /* Target of loopback */ - int unentries; /* # of entries in user map array */ - int gnentries; /* # of entries in group map array */ - id_map_t umapdata; /* pointer to array of user mappings */ - id_map_t gmapdata; /* pointer to array of group mappings */ + struct layer_args la; /* generic layerfs args. Includes + * target and export info */ +#define umap_target la.target +#define umap_export la.export + int unentries; /* # of entries in user map array */ + int gnentries; /* # of entries in group map array */ + u_long (*mapdata)[2]; /* pointer to array of user mappings */ + u_long (*gmapdata)[2]; /* pointer to array of group mappings */ }; +#ifdef _KERNEL + struct umap_mount { - struct mount *umapm_vfs; - struct vnode *umapm_rootvp; /* Reference to root umap_node */ - int info_unentries; /* number of uid mappings */ + struct layer_mount lm; + int info_unentries; /* number of uid mappings */ int info_gnentries; /* number of gid mappings */ - id_t info_umapdata[UMAPFILEENTRIES][2]; /* mapping data for + u_long info_umapdata[UMAPFILEENTRIES][2]; /* mapping data for user mapping in ficus */ - id_t info_gmapdata[GMAPFILEENTRIES][2]; /*mapping data for + u_long info_gmapdata[GMAPFILEENTRIES][2]; /*mapping data for group mapping in ficus */ }; +#define umapm_vfs lm.layerm_vfs +#define umapm_rootvp lm.layerm_rootvp +#define umapm_export lm.layerm_export +#define umapm_flags lm.layerm_flags +#define umapm_size lm.layerm_size +#define umapm_tag lm.layerm_tag +#define umapm_bypass lm.layerm_bypass +#define umapm_alloc lm.layerm_alloc +#define umapm_vnodeop_p lm.layerm_vnodeop_p +#define umapm_node_hashtbl lm.layerm_node_hashtbl +#define umapm_node_hash lm.layerm_node_hash +#define umapm_hashlock lm.layerm_hashlock -#ifdef _KERNEL /* * A cache of vnode references */ struct umap_node { - LIST_ENTRY(umap_node) umap_hash; /* Hash list */ - struct vnode *umap_lowervp; /* Aliased vnode - VREFed once */ - struct vnode *umap_vnode; /* Back pointer to vnode/umap_node */ + struct layer_node ln; }; -extern int umap_node_create(struct mount *mp, struct vnode *target, struct vnode **vpp); -extern id_t umap_reverse_findid(id_t id, id_map_t, int nentries); -extern void umap_mapids(struct mount *v_mount, struct ucred *credp); +u_long umap_reverse_findid(u_long id, u_long map[][2], int nentries); +void umap_mapids(struct mount *v_mount, struct ucred *credp); + +#define umap_hash ln.layer_hash +#define umap_lowervp ln.layer_lowervp +#define umap_vnode ln.layer_vnode +#define umap_flags ln.layer_flags #define MOUNTTOUMAPMOUNT(mp) ((struct umap_mount *)((mp)->mnt_data)) #define VTOUMAP(vp) ((struct umap_node *)(vp)->v_data) #define UMAPTOV(xp) ((xp)->umap_vnode) #ifdef UMAPFS_DIAGNOSTIC -extern struct vnode *umap_checkvp(struct vnode *vp, char *fil, int lno); -#define UMAPVPTOLOWERVP(vp) umap_checkvp((vp), __FILE__, __LINE__) +#define UMAPVPTOLOWERVP(vp) layer_checkvp((vp), __FILE__, __LINE__) #else #define UMAPVPTOLOWERVP(vp) (VTOUMAP(vp)->umap_lowervp) #endif -extern int (**umap_vnodeop_p)(void *); -extern struct vfsops umap_vfsops; +extern int (**umapfs_vnodeop_p)(void *); +extern struct vfsops umapfs_vfsops; + +int umap_bypass(void *); -int umapfs_init(struct vfsconf *); +#define NUMAPNODECACHE 16 #endif /* _KERNEL */ diff --git a/sys/miscfs/umapfs/umap_subr.c b/sys/miscfs/umapfs/umap_subr.c index 7c5d9fffa68..4f4cfb7c846 100644 --- a/sys/miscfs/umapfs/umap_subr.c +++ b/sys/miscfs/umapfs/umap_subr.c @@ -1,8 +1,40 @@ -/* $OpenBSD: umap_subr.c,v 1.14 2002/06/14 21:35:00 todd Exp $ */ -/* $NetBSD: umap_subr.c,v 1.8 1996/03/05 02:35:39 thorpej Exp $ */ +/* $OpenBSD: umap_subr.c,v 1.15 2003/05/12 21:02:10 tedu Exp $ */ +/* $NetBSD: umap_subr.c,v 1.19 2001/11/15 09:48:23 lukem Exp $ */ /* - * Copyright (c) 1992, 1993 + * Copyright (c) 1999 National Aeronautics & Space Administration + * All rights reserved. + * + * This software was written by William Studenmund of the + * Numerical Aerospace Simulation Facility, NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the National Aeronautics & Space Administration + * nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NATIONAL AERONAUTICS & SPACE ADMINISTRATION + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ADMINISTRATION OR CONTRIB- + * UTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright (c) 1992, 1993, 1995 * The Regents of the University of California. All rights reserved. * * This code is derived from software donated to Berkeley by @@ -37,14 +69,14 @@ * SUCH DAMAGE. * * from: Id: lofs_subr.c, v 1.11 1992/05/30 10:05:43 jsp Exp - * @(#)umap_subr.c 8.6 (Berkeley) 1/26/94 + * @(#)umap_subr.c 8.9 (Berkeley) 5/14/95 */ + #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> #include <sys/time.h> -#include <sys/types.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/namei.h> @@ -52,54 +84,22 @@ #include <miscfs/specfs/specdev.h> #include <miscfs/umapfs/umap.h> -#define LOG2_SIZEVNODE 7 /* log2(sizeof struct vnode) */ -#define NUMAPNODECACHE 16 - -/* - * Null layer cache: - * Each cache entry holds a reference to the target vnode - * along with a pointer to the alias vnode. When an - * entry is added the target vnode is VREF'd. When the - * alias is removed the target vnode is vrele'd. - */ - -#define UMAP_NHASH(vp) \ - (&umap_node_hashtbl[(((u_long)vp)>>LOG2_SIZEVNODE) & umap_node_hash]) -LIST_HEAD(umap_node_hashhead, umap_node) *umap_node_hashtbl; -u_long umap_node_hash; - -static id_t umap_findid(id_t, id_map_t, int); -static struct vnode *umap_node_find(struct mount *, struct vnode *); -static int umap_node_alloc(struct mount *, struct vnode *, - struct vnode **); - -/* - * Initialise cache headers - */ -int -umapfs_init(struct vfsconf *vfsp) -{ - -#ifdef UMAPFS_DIAGNOSTIC - printf("umapfs_init\n"); /* printed during system boot */ -#endif - umap_node_hashtbl = hashinit(NUMAPNODECACHE, M_CACHE, M_WAITOK, &umap_node_hash); - return (0); -} +u_long umap_findid(u_long, u_long [][2], int); +int umap_node_alloc(struct mount *, struct vnode *, struct vnode **); /* * umap_findid is called by various routines in umap_vnodeops.c to * find a user or group id in a map. */ -static id_t +u_long umap_findid(id, map, nentries) - id_t id; - id_map_t map; - int nentries; + u_long id; + u_long map[][2]; + int nentries; { int i; - /* Find {g,u}id entry in map */ + /* Find uid entry in map */ i = 0; while ((i<nentries) && ((map[i][0]) != id)) i++; @@ -115,11 +115,11 @@ umap_findid(id, map, nentries) * umap_reverse_findid is called by umap_getattr() in umap_vnodeops.c to * find a user or group id in a map, in reverse. */ -id_t +u_long umap_reverse_findid(id, map, nentries) - id_t id; - id_map_t map; - int nentries; + u_long id; + u_long map[][2]; + int nentries; { int i; @@ -135,264 +135,6 @@ umap_reverse_findid(id, map, nentries) } -/* - * Return alias for target vnode if already exists, else 0. - */ -static struct vnode * -umap_node_find(mp, targetvp) - struct mount *mp; - struct vnode *targetvp; -{ - struct proc *p = curproc; - struct umap_node_hashhead *hd; - struct umap_node *a; - struct vnode *vp; - -#ifdef UMAPFS_DIAGNOSTIC - printf("umap_node_find(mp = %p, target = %p)\n", mp, targetvp); -#endif - - /* - * Find hash base, and then search the (two-way) linked - * list looking for a umap_node structure which is referencing - * the target vnode. If found, the increment the umap_node - * reference count (but NOT the target vnode's VREF counter). - */ - hd = UMAP_NHASH(targetvp); -loop: - for (a = hd->lh_first; a != 0; a = a->umap_hash.le_next) { - if (a->umap_lowervp == targetvp && - a->umap_vnode->v_mount == mp) { - vp = UMAPTOV(a); - /* - * We need vget for the VXLOCK - * stuff, but we don't want to lock - * the lower node. - */ - if (vget(vp, 0, p)) { -#ifdef UMAPFS_DIAGNOSTIC - printf ("umap_node_find: vget failed.\n"); -#endif - goto loop; - } - return (vp); - } - } - -#ifdef UMAPFS_DIAGNOSTIC - printf("umap_node_find(%p, %p): NOT found\n", mp, targetvp); -#endif - - return (0); -} - -/* - * Make a new umap_node node. - * Vp is the alias vnode, lowervp is the target vnode. - * Maintain a reference to lowervp. - */ -static int -umap_node_alloc(mp, lowervp, vpp) - struct mount *mp; - struct vnode *lowervp; - struct vnode **vpp; -{ - struct umap_node_hashhead *hd; - struct umap_node *xp; - struct vnode *vp, *nvp; - int error; - struct proc *p = curproc; - extern int (**dead_vnodeop_p)(void *); - - if ((error = getnewvnode(VT_UMAP, mp, umap_vnodeop_p, &vp)) != 0) - return (error); - vp->v_type = lowervp->v_type; - - MALLOC(xp, struct umap_node *, sizeof(struct umap_node), M_TEMP, - M_WAITOK); - if (vp->v_type == VBLK || vp->v_type == VCHR) { - MALLOC(vp->v_specinfo, struct specinfo *, - sizeof(struct specinfo), M_VNODE, M_WAITOK); - vp->v_rdev = lowervp->v_rdev; - } - - vp->v_data = xp; - xp->umap_vnode = vp; - xp->umap_lowervp = lowervp; - /* - * Before we insert our new node onto the hash chains, - * check to see if someone else has beaten us to it. - * (We could have slept in MALLOC.) - */ - if ((nvp = umap_node_find(mp, lowervp)) != NULL) { - *vpp = nvp; - - /* free the substructures we've allocated. */ - FREE(xp, M_TEMP); - if (vp->v_type == VBLK || vp->v_type == VCHR) - FREE(vp->v_specinfo, M_VNODE); - - vp->v_type = VBAD; /* node is discarded */ - vp->v_op = dead_vnodeop_p; /* so ops will still work */ - vrele(vp); /* get rid of it. */ - return (0); - } - - /* - * XXX if it's a device node, it needs to be checkalias()ed. - * however, for locking reasons, that's just not possible. - * so we have to do most of the dirty work inline. Note that - * this is a limited case; we know that there's going to be - * an alias, and we know that that alias will be a "real" - * device node, i.e. not tagged VT_NON. - */ - if (vp->v_type == VBLK || vp->v_type == VCHR) { - struct vnode *cvp, **cvpp; - - cvpp = &speclisth[SPECHASH(vp->v_rdev)]; -loop: - for (cvp = *cvpp; cvp; cvp = cvp->v_specnext) { - if (vp->v_rdev != cvp->v_rdev || - vp->v_type != cvp->v_type) - continue; - - /* - * Alias, but not in use, so flush it out. - */ - if (cvp->v_usecount == 0) { - vgone(cvp); - goto loop; - } - if (vget(cvp, 0, p)) /* can't lock; will die! */ - goto loop; - break; - } - - vp->v_hashchain = cvpp; - vp->v_specnext = *cvpp; - vp->v_specmountpoint = NULL; - *cvpp = vp; -#ifdef DIAGNOSTIC - if (cvp == NULLVP) - panic("umap_node_alloc: no alias for device"); -#endif - vp->v_flag |= VALIASED; - cvp->v_flag |= VALIASED; - vrele(cvp); - } - /* XXX end of transmogrified checkalias() */ - - *vpp = vp; - VREF(lowervp); /* Extra VREF will be vrele'd in umap_node_create */ - hd = UMAP_NHASH(lowervp); - LIST_INSERT_HEAD(hd, xp, umap_hash); - return (0); -} - - -/* - * Try to find an existing umap_node vnode referring - * to it, otherwise make a new umap_node vnode which - * contains a reference to the target vnode. - */ -int -umap_node_create(mp, targetvp, newvpp) - struct mount *mp; - struct vnode *targetvp; - struct vnode **newvpp; -{ - struct vnode *aliasvp; - - if ((aliasvp = umap_node_find(mp, targetvp)) != NULL) { - /* - * Take another reference to the alias vnode - */ -#ifdef UMAPFS_DIAGNOSTIC - vprint("umap_node_create: exists", aliasvp); -#endif - /* VREF(aliasvp); */ - } else { - int error; - - /* - * Get new vnode. - */ -#ifdef UMAPFS_DIAGNOSTIC - printf("umap_node_create: create new alias vnode\n"); -#endif - /* - * Make new vnode reference the umap_node. - */ - if ((error = umap_node_alloc(mp, targetvp, &aliasvp)) != 0) - return (error); - - /* - * aliasvp is already VREF'd by getnewvnode() - */ - } - - vrele(targetvp); - -#ifdef UMAPFS_DIAGNOSTIC - vprint("umap_node_create: alias", aliasvp); - vprint("umap_node_create: target", targetvp); -#endif - - *newvpp = aliasvp; - return (0); -} - -#ifdef UMAPFS_DIAGNOSTIC -int umap_checkvp_barrier = 1; -struct vnode * -umap_checkvp(vp, fil, lno) - struct vnode *vp; - char *fil; - int lno; -{ - struct umap_node *a = VTOUMAP(vp); -#ifdef notyet - /* - * Can't do this check because vop_reclaim runs - * with funny vop vector. - */ - if (vp->v_op != umap_vnodeop_p) { - printf ("umap_checkvp: on non-umap-node\n"); - while (umap_checkvp_barrier) /*WAIT*/ ; - panic("umap_checkvp"); - } -#endif - if (a->umap_lowervp == NULL) { - /* Should never happen */ - int i; u_long *p; - printf("vp = %p, ZERO ptr\n", vp); - for (p = (u_long *) a, i = 0; i < 8; i++) - printf(" %lx", p[i]); - printf("\n"); - /* wait for debugger */ - while (umap_checkvp_barrier) /*WAIT*/ ; - panic("umap_checkvp"); - } - if (a->umap_lowervp->v_usecount < 1) { - int i; u_long *p; - printf("vp = %p, unref'ed lowervp\n", vp); - for (p = (u_long *) a, i = 0; i < 8; i++) - printf(" %lx", p[i]); - printf("\n"); - /* wait for debugger */ - while (umap_checkvp_barrier) /*WAIT*/ ; - panic ("umap with unref'ed lowervp"); - } -#ifdef notyet - printf("umap %p/%d -> %p/%d [%s, %d]\n", - a->umap_vnode, a->umap_vnode->v_usecount, - a->umap_lowervp, a->umap_lowervp->v_usecount, - fil, lno); -#endif - return (a->umap_lowervp); -} -#endif - /* umap_mapids maps all of the ids in a credential, both user and group. */ void @@ -400,18 +142,18 @@ umap_mapids(v_mount, credp) struct mount *v_mount; struct ucred *credp; { - int i, unentries, gnentries; - uid_t uid; - gid_t gid; - id_map_t usermap, groupmap; + int i, unentries, gnentries; + uid_t uid; + gid_t gid; + u_long (*usermap)[2], (*groupmap)[2]; if (credp == NOCRED) return; unentries = MOUNTTOUMAPMOUNT(v_mount)->info_unentries; - usermap = MOUNTTOUMAPMOUNT(v_mount)->info_umapdata; + usermap = MOUNTTOUMAPMOUNT(v_mount)->info_umapdata; gnentries = MOUNTTOUMAPMOUNT(v_mount)->info_gnentries; - groupmap = MOUNTTOUMAPMOUNT(v_mount)->info_gmapdata; + groupmap = MOUNTTOUMAPMOUNT(v_mount)->info_gmapdata; /* Find uid entry in map */ @@ -438,7 +180,7 @@ umap_mapids(v_mount, credp) /* Now we must map each of the set of groups in the cr_groups structure. */ - for ( i = 0 ; credp->cr_groups[i] != 0 ; i++ ) { + for(i=0; i < credp->cr_ngroups; i++) { gid = (gid_t) umap_findid(credp->cr_groups[i], groupmap, gnentries); diff --git a/sys/miscfs/umapfs/umap_vfsops.c b/sys/miscfs/umapfs/umap_vfsops.c index 1b289d5b8eb..0e2a482d1e1 100644 --- a/sys/miscfs/umapfs/umap_vfsops.c +++ b/sys/miscfs/umapfs/umap_vfsops.c @@ -1,5 +1,5 @@ -/* $OpenBSD: umap_vfsops.c,v 1.19 2003/02/24 22:32:46 tedu Exp $ */ -/* $NetBSD: umap_vfsops.c,v 1.9 1996/02/09 22:41:05 christos Exp $ */ +/* $OpenBSD: umap_vfsops.c,v 1.20 2003/05/12 21:02:10 tedu Exp $ */ +/* $NetBSD: umap_vfsops.c,v 1.35 2002/09/21 18:09:31 christos Exp $ */ /* * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * from: @(#)null_vfsops.c 1.5 (Berkeley) 7/10/92 - * @(#)umap_vfsops.c 8.3 (Berkeley) 1/21/94 + * @(#)umap_vfsops.c 8.8 (Berkeley) 5/14/95 */ /* @@ -45,29 +45,21 @@ * (See mount_umap(8) for a description of this layer.) */ + #include <sys/param.h> #include <sys/systm.h> -#include <sys/time.h> #include <sys/proc.h> -#include <sys/types.h> +#include <sys/time.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/namei.h> #include <sys/malloc.h> #include <miscfs/umapfs/umap.h> +#include <miscfs/genfs/layer_extern.h> int umapfs_mount(struct mount *, const char *, void *, - struct nameidata *, struct proc *); -int umapfs_start(struct mount *, int, struct proc *); + struct nameidata *, struct proc *); int umapfs_unmount(struct mount *, int, struct proc *); -int umapfs_root(struct mount *, struct vnode **); -int umapfs_quotactl(struct mount *, int, uid_t, caddr_t, - struct proc *); -int umapfs_statfs(struct mount *, struct statfs *, struct proc *); -int umapfs_sync(struct mount *, int, struct ucred *, struct proc *); -int umapfs_vget(struct mount *, ino_t, struct vnode **); -int umapfs_fhtovp(struct mount *, struct fid *, struct vnode **); -int umapfs_vptofh(struct vnode *, struct fid *); /* * Mount umap layer @@ -82,42 +74,57 @@ umapfs_mount(mp, path, data, ndp, p) { struct umap_args args; struct vnode *lowerrootvp, *vp; - struct vnode *umapm_rootvp; struct umap_mount *amp; size_t size; int error; #ifdef UMAPFS_DIAGNOSTIC int i; +#endif +#if 0 + if (mp->mnt_flag & MNT_GETARGS) { + amp = MOUNTTOUMAPMOUNT(mp); + if (amp == NULL) + return EIO; + args.la.target = NULL; + vfs_showexport(mp, &args.la.export, &->umapm_export); + args.nentries = amp->info_nentries; + args.gnentries = amp->info_gnentries; + return copyout(&args, data, sizeof(args)); + } +#endif + + /* only for root */ + if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) + return error; +#ifdef UMAPFS_DIAGNOSTIC printf("umapfs_mount(mp = %p)\n", mp); #endif /* - * Don't allow users to play with umapfs (when usermount is true). + * Get argument */ - if (p->p_ucred->cr_uid != 0) - return EPERM; + error = copyin(data, (caddr_t)&args, sizeof(struct umap_args)); + if (error) + return (error); /* - * Update is a no-op + * Update only does export updating. */ if (mp->mnt_flag & MNT_UPDATE) { - return (EOPNOTSUPP); - /* return (VFS_MOUNT(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, path, data, ndp, p));*/ + amp = MOUNTTOUMAPMOUNT(mp); + if (args.umap_target == 0) + return (vfs_export(mp, &->umapm_export, + &args.umap_export)); + else + return (EOPNOTSUPP); } /* - * Get argument - */ - error = copyin(data, &args, sizeof(struct umap_args)); - if (error) - return (error); - - /* * Find lower node */ - NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF, - UIO_USERSPACE, args.target, p); + NDINIT(ndp, LOOKUP, FOLLOW|LOCKLEAF, + UIO_USERSPACE, args.umap_target, p); if ((error = namei(ndp)) != 0) return (error); @@ -128,8 +135,6 @@ umapfs_mount(mp, path, data, ndp, p) #ifdef UMAPFS_DIAGNOSTIC printf("vp = %p, check for VDIR...\n", lowerrootvp); #endif - vrele(ndp->ni_dvp); - ndp->ni_dvp = 0; if (lowerrootvp->v_type != VDIR) { vput(lowerrootvp); @@ -142,83 +147,96 @@ umapfs_mount(mp, path, data, ndp, p) amp = (struct umap_mount *) malloc(sizeof(struct umap_mount), M_MISCFSMNT, M_WAITOK); + memset((caddr_t)amp, 0, sizeof(struct umap_mount)); - /* - * Save reference to underlying FS - */ + mp->mnt_data = (qaddr_t)amp; amp->umapm_vfs = lowerrootvp->v_mount; + if (amp->umapm_vfs->mnt_flag & MNT_LOCAL) + mp->mnt_flag |= MNT_LOCAL; /* * Now copy in the number of entries and maps for umap mapping. */ - if (args.unentries < 0 || args.unentries > UMAPFILEENTRIES || - args.gnentries < 0 || args.gnentries > GMAPFILEENTRIES) { + if (args.unentries > UMAPFILEENTRIES || args.gnentries > GMAPFILEENTRIES) { vput(lowerrootvp); return (error); } + amp->info_unentries = args.unentries; amp->info_gnentries = args.gnentries; - error = copyin(args.umapdata, (caddr_t)amp->info_umapdata, - 2*sizeof(**amp->info_umapdata)*args.unentries); - if (error) + error = copyin(args.mapdata, (caddr_t)amp->info_umapdata, + 2*sizeof(u_long)*args.unentries); + if (error) { + vput(lowerrootvp); return (error); + } #ifdef UMAPFS_DIAGNOSTIC printf("umap_mount:unentries %d\n",args.unentries); for (i = 0; i < args.unentries; i++) - printf(" %d maps to %d\n", amp->info_umapdata[i][0], + printf(" %ld maps to %ld\n", amp->info_umapdata[i][0], amp->info_umapdata[i][1]); #endif error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata, - 2*sizeof(**amp->info_gmapdata)*args.gnentries); - if (error) + 2*sizeof(u_long)*args.gnentries); + if (error) { + vput(lowerrootvp); return (error); + } #ifdef UMAPFS_DIAGNOSTIC printf("umap_mount:gnentries %d\n",args.gnentries); for (i = 0; i < args.gnentries; i++) - printf(" group %d maps to %d\n", + printf("\tgroup %ld maps to %ld\n", amp->info_gmapdata[i][0], amp->info_gmapdata[i][1]); #endif - /* - * Save reference. Each mount also holds - * a reference on the root vnode. + * Make sure the mount point's sufficiently initialized + * that the node create call will work. */ - error = umap_node_create(mp, lowerrootvp, &vp); + vfs_getnewfsid(mp); + amp->umapm_size = sizeof(struct umap_node); + amp->umapm_tag = VT_UMAP; + amp->umapm_bypass = umap_bypass; + amp->umapm_alloc = layer_node_alloc; /* the default alloc is fine */ + amp->umapm_vnodeop_p = umapfs_vnodeop_p; + simple_lock_init(&->umapm_hashlock); + amp->umapm_node_hashtbl = hashinit(NUMAPNODECACHE, M_CACHE, + M_WAITOK, &->umapm_node_hash); + + /* - * Unlock the node (either the lower or the alias) + * fix up umap node for root vnode. */ - VOP_UNLOCK(vp, 0, p); + error = layer_node_create(mp, lowerrootvp, &vp); /* * Make sure the node alias worked */ if (error) { - vrele(lowerrootvp); + vput(lowerrootvp); free(amp, M_MISCFSMNT); return (error); } + /* + * Unlock the node (either the lower or the alias) + */ + VOP_UNLOCK(vp, 0, p); /* * Keep a held reference to the root vnode. * It is vrele'd in umapfs_unmount. */ - umapm_rootvp = vp; - umapm_rootvp->v_flag |= VROOT; - amp->umapm_rootvp = umapm_rootvp; - if (UMAPVPTOLOWERVP(umapm_rootvp)->v_mount->mnt_flag & MNT_LOCAL) - mp->mnt_flag |= MNT_LOCAL; - mp->mnt_data = (qaddr_t) amp; - vfs_getnewfsid(mp); + vp->v_flag |= VROOT; + amp->umapm_rootvp = vp; (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); - bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); - (void) copyinstr(args.target, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, - &size); - bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); + memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size); + (void) copyinstr(args.umap_target, mp->mnt_stat.f_mntfromname, + MNAMELEN - 1, &size); + memset(mp->mnt_stat.f_mntfromname + size, 0, MNAMELEN - size); #ifdef UMAPFS_DIAGNOSTIC printf("umapfs_mount: lower %s, alias at %s\n", mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname); @@ -227,21 +245,6 @@ umapfs_mount(mp, path, data, ndp, p) } /* - * VFS start. Nothing needed here - the start routine - * on the underlying filesystem will have been called - * when that filesystem was mounted. - */ -int -umapfs_start(mp, flags, p) - struct mount *mp; - int flags; - struct proc *p; -{ - - return (0); -} - -/* * Free reference to umap layer */ int @@ -250,7 +253,7 @@ umapfs_unmount(mp, mntflags, p) int mntflags; struct proc *p; { - struct vnode *umapm_rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; + struct vnode *rootvp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; int error; int flags = 0; @@ -258,9 +261,8 @@ umapfs_unmount(mp, mntflags, p) printf("umapfs_unmount(mp = %p)\n", mp); #endif - if (mntflags & MNT_FORCE) { + if (mntflags & MNT_FORCE) flags |= FORCECLOSE; - } /* * Clear out buffer cache. I don't think we @@ -272,22 +274,22 @@ umapfs_unmount(mp, mntflags, p) if (mntinvalbuf(mp, 1)) return (EBUSY); #endif - if (umapm_rootvp->v_usecount > 1 && !(flags & FORCECLOSE)) + if (rootvp->v_usecount > 1) return (EBUSY); - if ((error = vflush(mp, umapm_rootvp, flags)) != 0) + if ((error = vflush(mp, rootvp, flags)) != 0) return (error); #ifdef UMAPFS_DIAGNOSTIC - vprint("alias root of lower", umapm_rootvp); + vprint("alias root of lower", rootvp); #endif /* * Release reference on underlying root vnode */ - vrele(umapm_rootvp); + vrele(rootvp); /* * And blow it away for future re-use */ - vgone(umapm_rootvp); + vgone(rootvp); /* * Finally, throw away the umap_mount structure */ @@ -296,138 +298,25 @@ umapfs_unmount(mp, mntflags, p) return (0); } -int -umapfs_root(mp, vpp) - struct mount *mp; - struct vnode **vpp; -{ - struct proc *p = curproc; - struct vnode *vp; +extern const struct vnodeopv_desc umapfs_vnodeop_opv_desc; -#ifdef UMAPFS_DIAGNOSTIC - printf("umapfs_root(mp = %p, vp = %p->%p)\n", mp, - MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, - UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) - ); -#endif - - /* - * Return locked reference to root. - */ - vp = MOUNTTOUMAPMOUNT(mp)->umapm_rootvp; - VREF(vp); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - *vpp = vp; - return (0); -} - -int -umapfs_quotactl(mp, cmd, uid, arg, p) - struct mount *mp; - int cmd; - uid_t uid; - caddr_t arg; - struct proc *p; -{ - return VFS_QUOTACTL(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, cmd, uid, arg, p); -} - -int -umapfs_statfs(mp, sbp, p) - struct mount *mp; - struct statfs *sbp; - struct proc *p; -{ - int error; - struct statfs mstat; - -#ifdef UMAPFS_DIAGNOSTIC - printf("umapfs_statfs(mp = %p, vp = %p->%p)\n", mp, - MOUNTTOUMAPMOUNT(mp)->umapm_rootvp, - UMAPVPTOLOWERVP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp) - ); -#endif - - bzero(&mstat, sizeof(mstat)); - - error = VFS_STATFS(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, &mstat, p); - if (error) - return (error); - - /* now copy across the "interesting" information and fake the rest */ - sbp->f_flags = mstat.f_flags; - sbp->f_bsize = mstat.f_bsize; - sbp->f_iosize = mstat.f_iosize; - sbp->f_blocks = mstat.f_blocks; - sbp->f_bfree = mstat.f_bfree; - sbp->f_bavail = mstat.f_bavail; - sbp->f_files = mstat.f_files; - sbp->f_ffree = mstat.f_ffree; - if (sbp != &mp->mnt_stat) { - bcopy(&mp->mnt_stat.f_fsid, &sbp->f_fsid, sizeof(sbp->f_fsid)); - bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); - bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); - } - strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN); - return (0); -} - -int -umapfs_sync(mp, waitfor, cred, p) - struct mount *mp; - int waitfor; - struct ucred *cred; - struct proc *p; -{ - /* - * XXX - Assumes no data cached at umap layer. - */ - return (0); -} - -int -umapfs_vget(mp, ino, vpp) - struct mount *mp; - ino_t ino; - struct vnode **vpp; -{ - return VFS_VGET(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, ino, vpp); -} - -int -umapfs_fhtovp(mp, fidp, vpp) - struct mount *mp; - struct fid *fidp; - struct vnode **vpp; -{ - return VFS_FHTOVP(MOUNTTOUMAPMOUNT(mp)->umapm_vfs, fidp, vpp); -} - -int -umapfs_vptofh(vp, fhp) - struct vnode *vp; - struct fid *fhp; -{ - return VFS_VPTOFH(UMAPVPTOLOWERVP(vp), fhp); -} - -#define umapfs_sysctl ((int (*)(int *, u_int, void *, size_t *, void *, \ - size_t, struct proc *))eopnotsupp) -#define umapfs_checkexp ((int (*)(struct mount *, struct mbuf *, \ - int *, struct ucred **))eopnotsupp) +const struct vnodeopv_desc * const umapfs_vnodeopv_descs[] = { + &umapfs_vnodeop_opv_desc, + NULL, +}; -struct vfsops umap_vfsops = { +struct vfsops umapfs_vfsops = { umapfs_mount, - umapfs_start, + layerfs_start, umapfs_unmount, - umapfs_root, - umapfs_quotactl, - umapfs_statfs, - umapfs_sync, - umapfs_vget, - umapfs_fhtovp, - umapfs_vptofh, - umapfs_init, - umapfs_sysctl, - umapfs_checkexp + layerfs_root, + layerfs_quotactl, + layerfs_statfs, + layerfs_sync, + layerfs_vget, + layerfs_fhtovp, + layerfs_vptofh, + layerfs_init, + layerfs_sysctl, + layerfs_checkexp, }; diff --git a/sys/miscfs/umapfs/umap_vnops.c b/sys/miscfs/umapfs/umap_vnops.c index c6334821e56..ef8585c0654 100644 --- a/sys/miscfs/umapfs/umap_vnops.c +++ b/sys/miscfs/umapfs/umap_vnops.c @@ -1,5 +1,5 @@ -/* $OpenBSD: umap_vnops.c,v 1.15 2002/06/23 03:07:22 deraadt Exp $ */ -/* $NetBSD: umap_vnops.c,v 1.5.4.1 1996/05/25 22:13:35 jtc Exp $ */ +/* $OpenBSD: umap_vnops.c,v 1.16 2003/05/12 21:02:10 tedu Exp $ */ +/* $NetBSD: umap_vnops.c,v 1.22 2002/01/04 07:19:34 chs Exp $ */ /* * Copyright (c) 1992, 1993 @@ -36,38 +36,29 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)umap_vnops.c 8.3 (Berkeley) 1/5/94 + * @(#)umap_vnops.c 8.6 (Berkeley) 5/22/95 */ /* * Umap Layer */ + #include <sys/param.h> #include <sys/systm.h> #include <sys/time.h> -#include <sys/types.h> #include <sys/vnode.h> #include <sys/mount.h> #include <sys/namei.h> #include <sys/malloc.h> #include <sys/buf.h> -#include <miscfs/nullfs/null.h> #include <miscfs/umapfs/umap.h> +#include <miscfs/genfs/layer_extern.h> - -int umap_bug_bypass = 0; /* for debugging: enables bypass printf'ing */ - -int umap_bypass(void *); +int umap_lookup(void *); int umap_getattr(void *); -int umap_inactive(void *); -int umap_reclaim(void *); int umap_print(void *); int umap_rename(void *); -int umap_strategy(void *); -int umap_bwrite(void *); -int umap_unlock(void *); -int umap_lock(void *); /* * Global vfs data structures @@ -77,28 +68,36 @@ int umap_lock(void *); * go away with a merged buffer/block cache. * */ -int (**umap_vnodeop_p)(void *); -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_rename_desc, umap_rename }, - { &vop_lock_desc, umap_lock }, - { &vop_unlock_desc, umap_unlock }, - { &vop_strategy_desc, umap_strategy }, - { &vop_bwrite_desc, umap_bwrite }, - +int (**umapfs_vnodeop_p)(void *); +struct vnodeopv_entry_desc umapfs_vnodeop_entries[] = { + { &vop_default_desc, umap_bypass }, + + { &vop_lookup_desc, umap_lookup }, + { &vop_getattr_desc, umap_getattr }, + { &vop_print_desc, umap_print }, + { &vop_rename_desc, umap_rename }, + + { &vop_lock_desc, layer_lock }, + { &vop_unlock_desc, layer_unlock }, + { &vop_islocked_desc, layer_islocked }, + { &vop_fsync_desc, layer_fsync }, + { &vop_inactive_desc, layer_inactive }, + { &vop_reclaim_desc, layer_reclaim }, + { &vop_open_desc, layer_open }, + { &vop_setattr_desc, layer_setattr }, + { &vop_access_desc, layer_access }, + + { &vop_strategy_desc, layer_strategy }, + { &vop_bwrite_desc, layer_bwrite }, + { &vop_bmap_desc, layer_bmap }, { NULL, NULL } }; -struct vnodeopv_desc umap_vnodeop_opv_desc = - { &umap_vnodeop_p, umap_vnodeop_entries }; +const struct vnodeopv_desc umapfs_vnodeop_opv_desc = + { &umapfs_vnodeop_p, umapfs_vnodeop_entries }; /* - * This is the 10-Apr-92 bypass routine. - * See null_vnops.c:null_bypass for more details. + * This is the 08-June-1999 bypass routine. + * See layer_vnops.c:layer_bypass for more details. */ int umap_bypass(v) @@ -112,26 +111,31 @@ umap_bypass(v) struct ucred *savecredp = 0, *savecompcredp = 0; struct ucred *compcredp = 0; struct vnode **this_vp_p; - int error = 0; - struct vnode *old_vps[VDESC_MAX_VPS]; - struct vnode *vp1 = 0; + int error, error1; + int (**our_vnodeop_p)(void *); + struct vnode *old_vps[VDESC_MAX_VPS], *vp0; struct vnode **vps_p[VDESC_MAX_VPS]; struct vnode ***vppp; struct vnodeop_desc *descp = ap->a_desc; - int reles, i; + int reles, i, flags; struct componentname **compnamepp = 0; - if (umap_bug_bypass) - printf ("umap_bypass: %s\n", descp->vdesc_name); - #ifdef SAFETY /* * 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."); + panic ("umap_bypass: no vp's in map.\n"); #endif + vps_p[0] = VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[0], + ap); + vp0 = *vps_p[0]; + flags = MOUNTTOUMAPMOUNT(vp0->v_mount)->umapm_flags; + our_vnodeop_p = vp0->v_op; + + if (flags & LAYERFS_MBYPASSDEBUG) + printf("umap_bypass: %s\n", descp->vdesc_name); /* * Map the vnodes going in. @@ -145,18 +149,14 @@ umap_bypass(v) vps_p[i] = this_vp_p = VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[i], ap); - if (i == 0) { - vp1 = *vps_p[0]; - } - /* * 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 == NULLVP || - (*this_vp_p)->v_op != umap_vnodeop_p)) { + if (i && ((*this_vp_p)==NULL || + (*this_vp_p)->v_op != our_vnodeop_p)) { old_vps[i] = NULL; } else { old_vps[i] = *this_vp_p; @@ -171,26 +171,28 @@ umap_bypass(v) * 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)) != NOCRED ) { + if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) { + + credpp = VOPARG_OFFSETTO(struct ucred**, + descp->vdesc_cred_offset, ap); /* Save old values */ savecredp = *credpp; - *credpp = crdup(savecredp); + if (savecredp != NOCRED) + *credpp = crdup(savecredp); credp = *credpp; - if (umap_bug_bypass && credp->cr_uid != 0) - printf("umap_bypass: user was %u, group %u\n", + if ((flags & LAYERFS_MBYPASSDEBUG) && 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); + umap_mapids(vp0->v_mount, credp); - if (umap_bug_bypass && credp->cr_uid != 0) - printf("umap_bypass: user now %u, group %u\n", + if ((flags & LAYERFS_MBYPASSDEBUG) && credp->cr_uid != 0) + printf("umap_bypass: user now %d, group %d\n", credp->cr_uid, credp->cr_gid); } @@ -198,24 +200,26 @@ umap_bypass(v) * 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)))->cn_cred != NOCRED ) { + if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) { + + compnamepp = VOPARG_OFFSETTO(struct componentname**, + descp->vdesc_componentname_offset, ap); savecompcredp = (*compnamepp)->cn_cred; - (*compnamepp)->cn_cred = crdup(savecompcredp); + if (savecompcredp != NOCRED) + (*compnamepp)->cn_cred = crdup(savecompcredp); compcredp = (*compnamepp)->cn_cred; - if (umap_bug_bypass && compcredp->cr_uid != 0) - printf("umap_bypass: component credit user was %u, group %u\n", + if ((flags & LAYERFS_MBYPASSDEBUG) && 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); + umap_mapids(vp0->v_mount, compcredp); - if (umap_bug_bypass && compcredp->cr_uid != 0) - printf("umap_bypass: component credit user now %u, group %u\n", + if ((flags & LAYERFS_MBYPASSDEBUG) && compcredp->cr_uid != 0) + printf("umap_bypass: component credit user now %d, group %d\n", compcredp->cr_uid, compcredp->cr_gid); } @@ -234,12 +238,14 @@ umap_bypass(v) 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 */ - if (old_vps[i] != NULLVP) { + if (old_vps[i]) { *(vps_p[i]) = old_vps[i]; - if (reles & 1) + if (reles & VDESC_VP0_WILLUNLOCK) + LAYERFS_UPPERUNLOCK(*(vps_p[i]), 0, error1); + if (reles & VDESC_VP0_WILLRELE) vrele(*(vps_p[i])); - }; - }; + } + } /* * Map the possible out-going vpp @@ -249,47 +255,151 @@ umap_bypass(v) if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET && !(descp->vdesc_flags & VDESC_NOMAP_VPP) && !error) { - 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); - } + if (descp->vdesc_flags & VDESC_VPP_WILLRELE) + goto out; + vppp = VOPARG_OFFSETTO(struct vnode***, + descp->vdesc_vpp_offset, ap); + error = layer_node_create(old_vps[0]->v_mount, **vppp, *vppp); } + out: /* * Free duplicate cred structure and restore old one. */ - if (descp->vdesc_cred_offset != VDESC_NO_OFFSET - && *credpp != NOCRED) { - if (umap_bug_bypass && credp && credp->cr_uid != 0) - printf("umap_bypass: returning-user was %u\n", - credp->cr_uid); - - crfree(credp); - *credpp = savecredp; - if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0) - printf("umap_bypass: returning-user now %u\n\n", - savecredp->cr_uid); + if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) { + if ((flags & LAYERFS_MBYPASSDEBUG) && credp && + credp->cr_uid != 0) + printf("umap_bypass: returning-user was %d\n", + credp->cr_uid); + + if (savecredp != NOCRED) { + crfree(credp); + *credpp = savecredp; + if ((flags & LAYERFS_MBYPASSDEBUG) && credpp && + (*credpp)->cr_uid != 0) + printf("umap_bypass: returning-user now %d\n\n", + savecredp->cr_uid); + } + } + + if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET) { + if ((flags & LAYERFS_MBYPASSDEBUG) && compcredp && + compcredp->cr_uid != 0) + printf("umap_bypass: returning-component-user was %d\n", + compcredp->cr_uid); + + if (savecompcredp != NOCRED) { + crfree(compcredp); + (*compnamepp)->cn_cred = savecompcredp; + if ((flags & LAYERFS_MBYPASSDEBUG) && savecompcredp && + savecompcredp->cr_uid != 0) + printf("umap_bypass: returning-component-user now %d\n", + savecompcredp->cr_uid); + } + } + + return (error); +} + +/* + * This is based on the 08-June-1999 bypass routine. + * See layer_vnops.c:layer_bypass for more details. + */ +int +umap_lookup(v) + void *v; +{ + struct vop_lookup_args /* { + struct vnodeop_desc *a_desc; + struct vnode * a_dvp; + struct vnode ** a_vpp; + struct componentname * a_cnp; + } */ *ap = v; + struct componentname *cnp = ap->a_cnp; + struct ucred *savecompcredp = NULL; + struct ucred *compcredp = NULL; + struct vnode *dvp, *vp, *ldvp; + struct mount *mp; + int error; + int i, flags, cnf = cnp->cn_flags; + + dvp = ap->a_dvp; + mp = dvp->v_mount; + + if ((cnf & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && + (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) + return (EROFS); + + flags = MOUNTTOUMAPMOUNT(mp)->umapm_flags; + ldvp = UMAPVPTOLOWERVP(dvp); + + if (flags & LAYERFS_MBYPASSDEBUG) + printf("umap_lookup\n"); + + /* + * Fix the credentials. (That's the purpose of this layer.) + * + * BSD often keeps a credential in the componentname structure + * for speed. If there is one, it better get mapped, too. + */ + + if ((savecompcredp = cnp->cn_cred)) { + compcredp = crdup(savecompcredp); + cnp->cn_cred = compcredp; + + if ((flags & LAYERFS_MBYPASSDEBUG) && compcredp->cr_uid != 0) + printf("umap_lookup: component credit user was %d, group %d\n", + compcredp->cr_uid, compcredp->cr_gid); + + /* Map all ids in the credential structure. */ + umap_mapids(mp, compcredp); } - if (descp->vdesc_componentname_offset != VDESC_NO_OFFSET - && savecompcredp != NOCRED ) { - if (umap_bug_bypass && compcredp && compcredp->cr_uid != 0) - printf("umap_bypass: returning-component-user was %u\n", - compcredp->cr_uid); + if ((flags & LAYERFS_MBYPASSDEBUG) && compcredp->cr_uid != 0) + printf("umap_lookup: component credit user now %d, group %d\n", + compcredp->cr_uid, compcredp->cr_gid); + + ap->a_dvp = ldvp; + error = VCALL(ldvp, ap->a_desc->vdesc_offset, ap); + vp = *ap->a_vpp; + if (error == EJUSTRETURN && (cnf & ISLASTCN) && + (dvp->v_mount->mnt_flag & MNT_RDONLY) && + (cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)) + error = EROFS; + + /* Do locking fixup as appropriate. See layer_lookup() for info */ + if ((cnp->cn_flags & PDIRUNLOCK)) { + LAYERFS_UPPERUNLOCK(dvp, 0, i); + } + if (ldvp == vp) { + *ap->a_vpp = dvp; + VREF(dvp); + vrele(vp); + } else if (vp != NULL) { + error = layer_node_create(mp, vp, ap->a_vpp); + } + + /* + * Free duplicate cred structure and restore old one. + */ + if ((flags & LAYERFS_MBYPASSDEBUG) && compcredp && + compcredp->cr_uid != 0) + printf("umap_lookup: returning-component-user was %d\n", + compcredp->cr_uid); + + if (savecompcredp != NOCRED) { crfree(compcredp); - (*compnamepp)->cn_cred = savecompcredp; - if (umap_bug_bypass && credpp && (*credpp)->cr_uid != 0) - printf("umap_bypass: returning-component-user now %u\n", + cnp->cn_cred = savecompcredp; + if ((flags & LAYERFS_MBYPASSDEBUG) && savecompcredp && + savecompcredp->cr_uid != 0) + printf("umap_lookup: returning-component-user now %d\n", savecompcredp->cr_uid); } return (error); } - /* * We handle getattr to change the fsid. */ @@ -303,18 +413,20 @@ umap_getattr(v) struct ucred *a_cred; struct proc *a_p; } */ *ap = v; - uid_t uid; - gid_t gid; - int error, tmpid, unentries, gnentries; - id_map_t umapdata, gmapdata; - struct vnode **vp1p; - struct vnodeop_desc *descp = ap->a_desc; + uid_t uid; + gid_t gid; + int error, tmpid, unentries, gnentries, flags; + u_long (*mapdata)[2]; + u_long (*gmapdata)[2]; + struct vnode **vp1p; + const struct vnodeop_desc *descp = ap->a_desc; if ((error = umap_bypass(ap)) != 0) return (error); /* Requires that arguments be restored. */ ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; + flags = MOUNTTOUMAPMOUNT(ap->a_vp->v_mount)->umapm_flags; /* * Umap needs to map the uid and gid returned by a stat * into the proper values for this site. This involves @@ -330,25 +442,25 @@ umap_getattr(v) uid = ap->a_vap->va_uid; gid = ap->a_vap->va_gid; - if (umap_bug_bypass) - printf("umap_getattr: mapped uid = %u, mapped gid = %u\n", uid, + if ((flags & LAYERFS_MBYPASSDEBUG)) + printf("umap_getattr: mapped uid = %d, mapped gid = %d\n", uid, gid); vp1p = VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[0], ap); unentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_unentries; - umapdata = (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_umapdata); + mapdata = (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_umapdata); gnentries = MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gnentries; - gmapdata = (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gmapdata); + gmapdata = (MOUNTTOUMAPMOUNT((*vp1p)->v_mount)->info_gmapdata); /* 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, umapdata, unentries); + tmpid = umap_reverse_findid(uid, mapdata, unentries); if (tmpid != -1) { ap->a_vap->va_uid = (uid_t) tmpid; - if (umap_bug_bypass) - printf("umap_getattr: original uid = %u\n", uid); + if ((flags & LAYERFS_MBYPASSDEBUG)) + printf("umap_getattr: original uid = %d\n", uid); } else ap->a_vap->va_uid = (uid_t) NOBODY; @@ -358,145 +470,14 @@ umap_getattr(v) if (tmpid != -1) { ap->a_vap->va_gid = (gid_t) tmpid; - if (umap_bug_bypass) - printf("umap_getattr: original gid = %u\n", gid); + if ((flags & LAYERFS_MBYPASSDEBUG)) + printf("umap_getattr: original gid = %d\n", gid); } else ap->a_vap->va_gid = (gid_t) NULLGROUP; return (0); } -/*ARGSUSED*/ -int -umap_inactive(v) - void *v; -{ - struct vop_inactive_args /* { - struct vnode *a_vp; - struct proc *a_p; - } */ *ap = v; - /* - * Do nothing (and _don't_ bypass). - * Wait to vrele lowervp until reclaim, - * so that until then our umap_node is in the - * cache and reusable. - * - */ - VOP_UNLOCK(ap->a_vp, 0, ap->a_p); - return (0); -} - -/* - * We need to process our own vnode lock and then clear the - * interlock flag as it applies only to our vnode, not the - * vnodes below us on the stack. - */ -int -umap_lock(v) - void *v; -{ - struct vop_lock_args /* { - struct vnode *a_vp; - int a_flags; - struct proc *a_p; - } */ *ap = v; - -#if 0 - vop_generic_lock(ap); -#endif - if ((ap->a_flags & LK_TYPE_MASK) == LK_DRAIN) - return (0); - ap->a_flags &= ~LK_INTERLOCK; - return (umap_bypass(ap)); -} - -/* - * We need to process our own vnode unlock and then clear the - * interlock flag as it applies only to our vnode, not the - * vnodes below us on the stack. - */ -int -umap_unlock(v) - void *v; -{ - struct vop_unlock_args /* { - struct vnode *a_vp; - int a_flags; - struct proc *a_p; - } */ *ap = v; - -#if 0 - vop_generic_unlock(ap); -#endif - ap->a_flags &= ~LK_INTERLOCK; - return (umap_bypass(ap)); -} - - - -int -umap_reclaim(v) - void *v; -{ - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap = v; - 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. */ - xp->umap_lowervp = NULL; - LIST_REMOVE(xp, umap_hash); - FREE(vp->v_data, M_TEMP); - vp->v_data = NULL; - vrele(lowervp); - return (0); -} - -int -umap_strategy(v) - void *v; -{ - struct vop_strategy_args /* { - struct buf *a_bp; - } */ *ap = v; - struct buf *bp = ap->a_bp; - int error; - struct vnode *savedvp; - - savedvp = bp->b_vp; - bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp); - - error = VOP_STRATEGY(ap->a_bp); - - bp->b_vp = savedvp; - - return (error); -} - -int -umap_bwrite(v) - void *v; -{ - struct vop_bwrite_args /* { - struct buf *a_bp; - } */ *ap = v; - struct buf *bp = ap->a_bp; - int error; - struct vnode *savedvp; - - savedvp = bp->b_vp; - bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp); - - error = VOP_BWRITE(ap->a_bp); - - bp->b_vp = savedvp; - - return (error); -} - - int umap_print(v) void *v; @@ -522,34 +503,35 @@ umap_rename(v) struct vnode *a_tvp; struct componentname *a_tcnp; } */ *ap = v; - int error; + int error, flags; struct componentname *compnamep; struct ucred *compcredp, *savecompcredp; struct vnode *vp; /* * Rename is irregular, having two componentname structures. - * We need to map the cred in the second structure, + * We need to map the cre in the second structure, * and then bypass takes care of the rest. */ vp = ap->a_fdvp; + flags = MOUNTTOUMAPMOUNT(vp->v_mount)->umapm_flags; compnamep = ap->a_tcnp; 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 %u, group %u\n", + if ((flags & LAYERFS_MBYPASSDEBUG) && 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 %u, group %u\n", + if ((flags & LAYERFS_MBYPASSDEBUG) && compcredp->cr_uid != 0) + printf("umap_rename: rename component credit user now %d, group %d\n", compcredp->cr_uid, compcredp->cr_gid); error = umap_bypass(ap); @@ -561,4 +543,3 @@ umap_rename(v) return error; } - |