Porting from null layer
authorJohn Heidemann <heideman@ucbvax.Berkeley.EDU>
Sun, 12 Jul 1992 06:29:11 +0000 (22:29 -0800)
committerJohn Heidemann <heideman@ucbvax.Berkeley.EDU>
Sun, 12 Jul 1992 06:29:11 +0000 (22:29 -0800)
SCCS-vsn: sys/miscfs/umapfs/umap.h 1.2
SCCS-vsn: sys/miscfs/umapfs/umap_subr.c 1.2
SCCS-vsn: sys/miscfs/umapfs/umap_vfsops.c 1.2
SCCS-vsn: sys/miscfs/umapfs/umap_vnops.c 1.2

usr/src/sys/miscfs/umapfs/umap.h
usr/src/sys/miscfs/umapfs/umap_subr.c
usr/src/sys/miscfs/umapfs/umap_vfsops.c
usr/src/sys/miscfs/umapfs/umap_vnops.c

index f69ae58..1fe8a7c 100644 (file)
@@ -4,45 +4,19 @@
  * All rights reserved.
  *
  * This code is derived from software donated to Berkeley by
  * All rights reserved.
  *
  * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
+ * the UCLA Ficus project.
  *
  *
- * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
+ * %sccs.include.redist.c%
  *
  *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *     @(#)umap.h      1.2 (Berkeley) %G%
  *
  *
- *     @(#)lofs.h      1.1 (Berkeley) 6/3/92
- *
- * $Id: lofs.h,v 1.8 1992/05/30 10:05:43 jsp Exp jsp $
+ * @(#)null_vnops.c       1.5 (Berkeley) 7/10/92
  */
 
 #define MAPFILEENTRIES 64
 #define GMAPFILEENTRIES 16
 #define NOBODY 32767
  */
 
 #define MAPFILEENTRIES 64
 #define GMAPFILEENTRIES 16
 #define NOBODY 32767
-#define UMAPGROUP 65534
+#define NULLGROUP 65534
 
 struct umap_args {
        char            *target;        /* Target of loopback  */
 
 struct umap_args {
        char            *target;        /* Target of loopback  */
@@ -78,6 +52,7 @@ extern int umap_node_create __P((struct mount *mp, struct vnode *target, struct
 
 #define        MOUNTTOUMAPMOUNT(mp) ((struct umap_mount *)((mp)->mnt_data))
 #define        VTOUMAP(vp) ((struct umap_node *)(vp)->v_data)
 
 #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 __P((struct vnode *vp, char *fil, int lno));
 #define        UMAPVPTOLOWERVP(vp) umap_checkvp((vp), __FILE__, __LINE__)
 #ifdef UMAPFS_DIAGNOSTIC
 extern struct vnode *umap_checkvp __P((struct vnode *vp, char *fil, int lno));
 #define        UMAPVPTOLOWERVP(vp) umap_checkvp((vp), __FILE__, __LINE__)
index a08d024..4fc2468 100644 (file)
@@ -69,87 +69,17 @@ struct vnode *targetvp;
        return (&umap_node_cache[UMAP_NHASH(targetvp)]);
 }
 
        return (&umap_node_cache[UMAP_NHASH(targetvp)]);
 }
 
-/*
- * Make a new umap_node node.
- * Vp is the alias vnode, lofsvp is the target vnode.
- * Maintain a reference to (targetvp).
- */
-static void
-umap_node_alloc(vp, targetvp)
-       struct vnode *vp;
-       struct vnode *targetvp;
-{
-       struct umap_node_cache *hd;
-       struct umap_node *a;
-
-#ifdef UMAPFS_DIAGNOSTIC
-       printf("umap_node_alloc(%x, %x)\n", vp, targetvp);
-#endif
-
-       MALLOC(a, struct umap_node *, sizeof(struct umap_node), M_TEMP, M_WAITOK);
-       vp->v_type = targetvp->v_type;
-       a->umap_vnode = vp;
-       vp->v_data = a;
-       VREF(targetvp);   /* Extra VREF will be vrele'd in umap_node_create */
-       a->umap_lowervp = targetvp;
-       hd = umap_node_hash(targetvp);
-       insque(a, hd);
-
-#ifdef UMAPFS_DIAGNOSTIC
-       vprint("umap_node_alloc vp", vp);
-       vprint("umap_node_alloc targetvp", targetvp);
-#endif
-}
-
-#ifdef UMAPFS_DIAGNOSTIC
-/*
- * NEEDSWORK:  The ability to set lowervp to umap here
- * implies that one can never count on lowervp staying umap
- * (even if vp is locked).  This seems quite bad.  Think
- * about these things.
- */
-void
-umap_node_flushmp (mp)
-       struct mount *mp;
-{
-       struct umap_node_cache *ac;
-       int i = 0;
-       struct umap_node *roota;
-
-       printf("umap_node_flushmp (%x)\n", mp);
-
-       roota = VTOUMAP(MOUNTTOUMAPMOUNT(mp)->umapm_rootvp);
-
-       for (ac = umap_node_cache; ac < umap_node_cache + NUMAPNODECACHE; ac++) {
-               struct umap_node *a = ac->ac_forw;
-               while (a != (struct umap_node *) ac) {
-                       if (a != roota && a->umap_vnode->v_mount == mp) {
-                               struct vnode *vp = a->umap_lowervp;
-                               if (vp) {
-                                       a->umap_lowervp = 0;
-                                       vprint("umap_flushmp: would vrele", vp);
-                                       /*vrele(vp);*/
-                                       i++;
-                               }
-                       }
-                       a = a->umap_forw;
-               }
-       }
-       if (i > 0)
-               printf("umap_node: vrele'd %d aliases\n", i);
-}
-#endif
-
 /*
  * Return alias for target vnode if already exists, else 0.
  */
 /*
  * Return alias for target vnode if already exists, else 0.
  */
-static struct umap_node *
+static struct vnode *
 umap_node_find(mp, targetvp)
        struct mount *mp;
        struct vnode *targetvp;
 {
        struct umap_node_cache *hd;
        struct umap_node *a;
 umap_node_find(mp, targetvp)
        struct mount *mp;
        struct vnode *targetvp;
 {
        struct umap_node_cache *hd;
        struct umap_node *a;
+       struct vnode *vp;
 
 #ifdef UMAPFS_DIAGNOSTIC
        printf("umap_node_find(mp = %x, target = %x)\n", mp, targetvp);
 
 #ifdef UMAPFS_DIAGNOSTIC
        printf("umap_node_find(mp = %x, target = %x)\n", mp, targetvp);
@@ -163,13 +93,20 @@ umap_node_find(mp, targetvp)
         */
        hd = umap_node_hash(targetvp);
 
         */
        hd = umap_node_hash(targetvp);
 
+ loop:
        for (a = hd->ac_forw; a != (struct umap_node *) hd; a = a->umap_forw) {
                if (a->umap_lowervp == targetvp && a->umap_vnode->v_mount == mp) {
        for (a = hd->ac_forw; a != (struct umap_node *) hd; a = a->umap_forw) {
                if (a->umap_lowervp == targetvp && a->umap_vnode->v_mount == mp) {
-#ifdef UMAPFS_DIAGNOSTIC
-                       printf("umap_node_find(%x): found (%x,%x)->%x\n",
-                               targetvp, mp, a->umap_vnode, targetvp);
-#endif
-                       return (a);
+                       vp = UMAPTOV(a);
+                       /*
+                        * We need vget for the VXLOCK
+                        * stuff, but we don't want to lock
+                        * the lower node.
+                        */
+                       if (vget_nolock(vp)) {
+                               printf ("null_node_find: vget failed.\n");
+                               goto loop;
+                       };
+                       return (vp);
                }
        }
 
                }
        }
 
@@ -180,6 +117,50 @@ umap_node_find(mp, targetvp)
        return (0);
 }
 
        return (0);
 }
 
+/*
+ * Make a new umap_node node.
+ * Vp is the alias vnode, lofsvp is the target vnode.
+ * Maintain a reference to (targetvp).
+ */
+static int
+umap_node_alloc(mp, lowervp, vpp)
+       struct mount *mp;
+       struct vnode *lowervp;
+       struct vnode **vpp;
+{
+       struct umap_node_cache *hd;
+       struct umap_node *xp;
+       struct vnode *othervp, *vp;
+       int error;
+
+       if (error = getnewvnode(VT_UFS, mp, umap_vnodeop_p, vpp))
+               return (error); /* XXX: VT_UMAP above */
+       vp = *vpp;
+
+       MALLOC(xp, struct umap_node *, sizeof(struct umap_node), M_TEMP, M_WAITOK);
+       vp->v_type = lowervp->v_type;
+       xp->umap_vnode = vp;
+       vp->v_data = xp;
+       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 (othervp = umap_node_find(lowervp)) {
+               FREE(xp, M_TEMP);
+               vp->v_type = VBAD;      /* node is discarded */
+               vp->v_usecount = 0;     /* XXX */
+               *vpp = othervp;
+               return 0;
+       };
+       VREF(lowervp);   /* Extra VREF will be vrele'd in umap_node_create */
+       hd = umap_node_hash(lowervp);
+       insque(xp, hd);
+       return 0;
+}
+
+
 /*
  * Try to find an existing umap_node vnode refering
  * to it, otherwise make a new umap_node vnode which
 /*
  * Try to find an existing umap_node vnode refering
  * to it, otherwise make a new umap_node vnode which
@@ -191,20 +172,16 @@ umap_node_create(mp, targetvp, newvpp)
        struct vnode *targetvp;
        struct vnode **newvpp;
 {
        struct vnode *targetvp;
        struct vnode **newvpp;
 {
-       struct umap_node *ap;
        struct vnode *aliasvp;
 
        struct vnode *aliasvp;
 
-       ap = umap_node_find(mp, targetvp);
-
-       if (ap) {
+       if (aliasvp = umap_node_find(mp, targetvp)) {
                /*
                 * Take another reference to the alias vnode
                 */
 #ifdef UMAPFS_DIAGNOSTIC
                vprint("umap_node_create: exists", ap->umap_vnode);
 #endif
                /*
                 * Take another reference to the alias vnode
                 */
 #ifdef UMAPFS_DIAGNOSTIC
                vprint("umap_node_create: exists", ap->umap_vnode);
 #endif
-               aliasvp = ap->umap_vnode;
-               VREF(aliasvp);
+               /* VREF(aliasvp); */
        } else {
                int error;
 
        } else {
                int error;
 
@@ -214,13 +191,11 @@ umap_node_create(mp, targetvp, newvpp)
 #ifdef UMAPFS_DIAGNOSTIC
                printf("umap_node_create: create new alias vnode\n");
 #endif
 #ifdef UMAPFS_DIAGNOSTIC
                printf("umap_node_create: create new alias vnode\n");
 #endif
-               if (error = getnewvnode(VT_UFS, mp, umap_vnodeop_p, &aliasvp))
-                       return (error); /* XXX: VT_LOFS above */
-
                /*
                 * Make new vnode reference the umap_node.
                 */
                /*
                 * Make new vnode reference the umap_node.
                 */
-               umap_node_alloc(aliasvp, targetvp);
+               if (error = umap_node_alloc(mp, targetvp, &aliasvp))
+                       return error;
 
                /*
                 * aliasvp is already VREF'd by getnewvnode()
 
                /*
                 * aliasvp is already VREF'd by getnewvnode()
@@ -290,34 +265,36 @@ umap_checkvp(vp, fil, lno)
 
 /* umap_mapids maps all of the ids in a credential, both user and group. */
 
 
 /* umap_mapids maps all of the ids in a credential, both user and group. */
 
-umap_mapids(credp,usermap,unentries,groupmap,gnentries)
+umap_mapids(v_mount,credp)
+       struct mount *v_mount;
        struct ucred *credp;
        struct ucred *credp;
-       int * usermap, groupmap;
-       int unentries,gnentries;
 {
 {
-       int i,gid,uid;
+       int i,gid,uid,unentries,gnentries,*groupmap,*usermap;
+
+       unentries =  MOUNTTOUMAPMOUNT(v_mount)->info_nentries;
+       usermap =  &(MOUNTTOUMAPMOUNT(v_mount)->info_mapdata[0][0]);
+       gnentries =  MOUNTTOUMAPMOUNT(v_mount)->info_gnentries;
+       groupmap =  &(MOUNTTOUMAPMOUNT(v_mount)->info_gmapdata[0][0]);
 
        /* Find uid entry in map */
 
        uid = umap_findid(credp->cr_uid,usermap,unentries);
 
        if (uid != -1) {
 
        /* Find uid entry in map */
 
        uid = umap_findid(credp->cr_uid,usermap,unentries);
 
        if (uid != -1) {
-               credp->cr_ruid =
                credp->cr_uid =
                        (u_short)uid;
        } else 
                credp->cr_uid =
                        (u_short)uid;
        } else 
-               credp->cr_ruid = credp->cr_uid = (u_short)NOBODY;
+               credp->cr_uid = (u_short)NOBODY;
 
        /* Find gid entry in map */
 
        gid = umap_findid(credp->cr_gid,groupmap,gnentries);
 
        if (gid != -1) {
 
        /* Find gid entry in map */
 
        gid = umap_findid(credp->cr_gid,groupmap,gnentries);
 
        if (gid != -1) {
-               credp->cr_rgid =
                credp->cr_gid =
                        (u_short)gid;
        } else 
                credp->cr_gid =
                        (u_short)gid;
        } else 
-               credp->cr_rgid = credp->cr_gid = (u_short)NULLGROUP;
+               credp->cr_gid = (u_short)NULLGROUP;
 
        /* Now we must map each of the set of groups in the cr_groups 
                structure. */
 
        /* Now we must map each of the set of groups in the cr_groups 
                structure. */
index bd25c47..9031e5e 100644 (file)
@@ -4,19 +4,18 @@
  * All rights reserved.
  *
  * This code is derived from software donated to Berkeley by
  * All rights reserved.
  *
  * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
+ * the UCLA Ficus project.
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)umap_vfsops.c       1.1 (Berkeley) %G%
+ *     @(#)umap_vfsops.c       1.2 (Berkeley) %G%
  *
  *
- * @(#)lofs_vfsops.c   1.2 (Berkeley) 6/18/92
- * $Id: lofs_vfsops.c,v 1.9 1992/05/30 10:26:24 jsp Exp jsp $
+ * @(#)null_vfsops.c       1.5 (Berkeley) 7/10/92
  */
 
 /*
  */
 
 /*
- * Null Layer
- * (See umap_vnops.c for a description of what this does.)
+ * Umap Layer
+ * (See mount_umap(8) for a descritpion of this layer.)
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -67,7 +66,7 @@ umapfs_mount(mp, path, data, ndp, p)
                return (error);
 
        /*
                return (error);
 
        /*
-        * Find target node
+        * Find lower node
         */
        NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
                UIO_USERSPACE, args.target, p);
         */
        NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
                UIO_USERSPACE, args.target, p);
@@ -75,7 +74,7 @@ umapfs_mount(mp, path, data, ndp, p)
                return (error);
 
        /*
                return (error);
 
        /*
-        * Sanity check on target vnode
+        * Sanity check on lower vnode
         */
        lowerrootvp = ndp->ni_vp;
 #ifdef UMAPFS_DIAGNOSTIC
         */
        lowerrootvp = ndp->ni_vp;
 #ifdef UMAPFS_DIAGNOSTIC
@@ -84,10 +83,6 @@ umapfs_mount(mp, path, data, ndp, p)
        vrele(ndp->ni_dvp);
        ndp->ni_dvp = 0;
 
        vrele(ndp->ni_dvp);
        ndp->ni_dvp = 0;
 
-       /*
-        * NEEDSWORK: Is this really bad, or just not
-        * the way it's been?
-        */
        if (lowerrootvp->v_type != VDIR) {
                vput(lowerrootvp);
                return (EINVAL);
        if (lowerrootvp->v_type != VDIR) {
                vput(lowerrootvp);
                return (EINVAL);
@@ -101,32 +96,37 @@ umapfs_mount(mp, path, data, ndp, p)
                                M_UFSMNT, M_WAITOK);    /* XXX */
 
        /*
                                M_UFSMNT, M_WAITOK);    /* XXX */
 
        /*
-        * Save reference to underlying target FS
+        * Save reference to underlying FS
         */
        amp->umapm_vfs = lowerrootvp->v_mount;
 
        /* 
         * Now copy in the number of entries and maps for umap mapping.
         */
         */
        amp->umapm_vfs = lowerrootvp->v_mount;
 
        /* 
         * Now copy in the number of entries and maps for umap mapping.
         */
-
        amp->info_nentries = args.nentries;
        amp->info_gnentries = args.gnentries;
        error = copyin(args.mapdata, (caddr_t)amp->info_mapdata, 
        amp->info_nentries = args.nentries;
        amp->info_gnentries = args.gnentries;
        error = copyin(args.mapdata, (caddr_t)amp->info_mapdata, 
-           8*args.nentries);
+           2*sizeof(int)*args.nentries);
        if (error) return (error);
        if (error) return (error);
+
+#ifdef UMAP_DIAGNOSTIC
        printf("umap_mount:nentries %d\n",args.nentries);
        printf("umap_mount:nentries %d\n",args.nentries);
-       for (i=0; i<args.nentries;i++)
+       for (i = 0; i < args.nentries; i++)
                printf("   %d maps to %d\n", amp->info_mapdata[i][0],
                    amp->info_mapdata[i][1]);
                printf("   %d maps to %d\n", amp->info_mapdata[i][0],
                    amp->info_mapdata[i][1]);
+#endif
 
        error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata, 
 
        error = copyin(args.gmapdata, (caddr_t)amp->info_gmapdata, 
-           8*args.nentries);
+           2*sizeof(int)*args.nentries);
        if (error) return (error);
        if (error) return (error);
+
+#ifdef UMAP_DIAGNOSTIC
        printf("umap_mount:gnentries %d\n",args.gnentries);
        printf("umap_mount:gnentries %d\n",args.gnentries);
-       for (i=0; i<args.gnentries;i++)
+       for (i = 0; i < args.gnentries; i++)
                printf("        group %d maps to %d\n", 
                    amp->info_gmapdata[i][0],
                    amp->info_gmapdata[i][1]);
                printf("        group %d maps to %d\n", 
                    amp->info_gmapdata[i][0],
                    amp->info_gmapdata[i][1]);
+#endif
 
 
        /*
 
 
        /*
@@ -135,7 +135,7 @@ umapfs_mount(mp, path, data, ndp, p)
         */
        error = umap_node_create(mp, lowerrootvp, &vp);
        /*
         */
        error = umap_node_create(mp, lowerrootvp, &vp);
        /*
-        * Unlock the node (either the target or the alias)
+        * Unlock the node (either the lower or the alias)
         */
        VOP_UNLOCK(vp);
        /*
         */
        VOP_UNLOCK(vp);
        /*
@@ -165,7 +165,7 @@ umapfs_mount(mp, path, data, ndp, p)
            &size);
        bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
 #ifdef UMAPFS_DIAGNOSTIC
            &size);
        bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
 #ifdef UMAPFS_DIAGNOSTIC
-       printf("umapfs_mount: target %s, alias at %s\n",
+       printf("umapfs_mount: lower %s, alias at %s\n",
                mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
 #endif
        return (0);
                mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname);
 #endif
        return (0);
@@ -227,14 +227,7 @@ umapfs_unmount(mp, mntflags, p)
                return (error);
 
 #ifdef UMAPFS_DIAGNOSTIC
                return (error);
 
 #ifdef UMAPFS_DIAGNOSTIC
-       /*
-        * Flush any remaining vnode references
-        */
-       umap_node_flushmp (mp);
-#endif
-
-#ifdef UMAPFS_DIAGNOSTIC
-       vprint("alias root of target", umapm_rootvp);
+       vprint("alias root of lower", umapm_rootvp);
 #endif  
        /*
         * Release reference on underlying root vnode
 #endif  
        /*
         * Release reference on underlying root vnode
index f03b2d9..cb81ee1 100644 (file)
@@ -2,61 +2,22 @@
  * Copyright (c) 1992 The Regents of the University of California
  * All rights reserved.
  *
  * Copyright (c) 1992 The Regents of the University of California
  * All rights reserved.
  *
- * This code is derived from the null layer of
- * John Heidemann from the UCLA Ficus project and
- * Jan-Simon Pendry's loopback file system.
+ * This code is derived from software donated to Berkeley by
+ * the UCLA Ficus project.
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)umap_vnops.c        1.1 (Berkeley) %G%
+ *     @(#)umap_vnops.c        1.2 (Berkeley) %G%
  *
  *
- * Ancestors:
- *     @(#)lofs_vnops.c        1.2 (Berkeley) 6/18/92
- *     $Id: lofs_vnops.c,v 1.11 1992/05/30 10:05:43 jsp Exp jsp $
- *     ...and...
- *     @(#)umap_vnodeops.c 1.20 92/07/07 UCLA Ficus project
+ * @(#)umap_vnops.c       1.5 (Berkeley) 7/10/92
  */
 
 /*
  * Umap Layer
  */
 
 /*
  * Umap Layer
- *
- * The umap layer duplicates a portion of the file system
- * name space under a new name.  In this respect, it is
- * similar to the loopback file system.  It differs from
- * the loopback fs in two respects:  it is implemented using
- * a bypass operation, and it's "umap-node"s stack above
- * all lower-layer vnodes, not just over directory vnodes.
- *
- * The umap layer is the minimum file system layer,
- * simply bypassing all possible operations to the lower layer
- * for processing there.  All but vop_getattr, _inactive, _reclaim,
- * and _print are bypassed.
- *
- * Vop_getattr is not bypassed so that we can change the fsid being
- * returned.  Vop_{inactive,reclaim} are bypassed so that
- * they can handle freeing umap-layer specific data.
- * Vop_print is not bypassed for debugging.
- *
- *
- * INVOKING OPERATIONS ON LOWER LAYERS
- *
- * NEEDSWORK: Describe methods to invoke operations on the lower layer
- * (bypass vs. VOP).
- *
- *
- * CREATING NEW FILESYSTEM LAYERS
- *
- * One of the easiest ways to construct new file system layers is to make
- * a copy of the umap layer, rename all files and variables, and
- * then begin modifing the copy.  Sed can be used to easily rename
- * all variables.
- *
  */
 
 #include <sys/param.h>
 #include <sys/systm.h>
  */
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/user.h>
-#include <sys/proc.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/vnode.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/vnode.h>
@@ -71,28 +32,7 @@ int umap_bug_bypass = 0;   /* for debugging: enables bypass printf'ing */
 
 /*
  * This is the 10-Apr-92 bypass routine.
 
 /*
  * This is the 10-Apr-92 bypass routine.
- *    This version has been optimized for speed, throwing away some
- * safety checks.  It should still always work, but it's not as
- * robust to programmer errors.
- *    Define SAFETY to include some error checking code.
- *
- * In general, we map all vnodes going down and unmap them on the way back.
- * As an exception to this, vnodes can be marked "unmapped" by setting
- * the Nth bit in operation's vdesc_flags.
- *
- * Also, some BSD vnode operations have the side effect of vrele'ing
- * their arguments.  With stacking, the reference counts are held
- * by the upper node, not the lower one, so we must handle these
- * side-effects here.  This is not of concern in Sun-derived systems
- * since there are no such side-effects.
- *
- * This makes the following assumptions:
- * - only one returned vpp
- * - no INOUT vpp's (Sun's vop_open has one of these)
- * - the vnode operation vector of the first vnode should be used
- *   to determine what implementation of the op should be invoked
- * - all mapped vnodes are of our vnode-type (NEEDSWORK:
- *   problems on rmdir'ing mount points and renaming?)
+ * See null_vnops.c:null_bypass for more details.
  */ 
 int
 umap_bypass(ap)
  */ 
 int
 umap_bypass(ap)
@@ -101,14 +41,16 @@ umap_bypass(ap)
        extern int (**umap_vnodeop_p)();  /* not extern, really "forward" */
        int *mapdata, nentries ;
        int *gmapdata, gnentries ;
        extern int (**umap_vnodeop_p)();  /* not extern, really "forward" */
        int *mapdata, nentries ;
        int *gmapdata, gnentries ;
-       struct ucred **credpp,*credp, *savecredp, *saveucredp ;
+       struct ucred **credpp,*credp, *savecredp, *saveucredp, *savecompcredp ;
+       struct ucred *compcredp;
        register struct vnode **this_vp_p;
        int error;
        register struct vnode **this_vp_p;
        int error;
-       struct vnode *old_vps[VDESC_MAX_VPS];
+       struct vnode *old_vps[VDESC_MAX_VPS], *vp1;
        struct vnode **vps_p[VDESC_MAX_VPS];
        struct vnode ***vppp;
        struct vnodeop_desc *descp = ap->a_desc;
        int reles, i;
        struct vnode **vps_p[VDESC_MAX_VPS];
        struct vnode ***vppp;
        struct vnodeop_desc *descp = ap->a_desc;
        int reles, i;
+       struct componentname **compnamepp;
 
        if (umap_bug_bypass)
                printf ("umap_bypass: %s\n", descp->vdesc_name);
 
        if (umap_bug_bypass)
                printf ("umap_bypass: %s\n", descp->vdesc_name);
@@ -117,8 +59,8 @@ umap_bypass(ap)
        /*
         * We require at least one vp.
         */
        /*
         * We require at least one vp.
         */
-       if (descp->vdesc_vp_offsets==UMAP ||
-           descp->vdesc_vp_offsets[0]==VDESC_NO_OFFSET)
+       if (descp->vdesc_vp_offsets == NULL ||
+           descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET)
                panic ("umap_bypass: no vp's in map.\n");
 #endif
 
                panic ("umap_bypass: no vp's in map.\n");
 #endif
 
@@ -128,8 +70,8 @@ umap_bypass(ap)
         * the first mapped vnode's operation vector.
         */
        reles = descp->vdesc_flags;
         * 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)
+       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] = this_vp_p = 
                        VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[i],ap);
                        break;   /* bail out at end of list */
                vps_p[i] = this_vp_p = 
                        VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[i],ap);
@@ -142,21 +84,23 @@ umap_bypass(ap)
                /*
                 * We're not guaranteed that any but the first vnode
                 * are of our type.  Check for and don't map any
                /*
                 * We're not guaranteed that any but the first vnode
                 * are of our type.  Check for and don't map any
-                * that aren't.
+                * that aren't.  (Must map first vp or vclean fails.)
                 */
 
                 */
 
-               if ((*this_vp_p)->v_op != umap_vnodeop_p) {
-                       old_vps[i] = UMAP;
+               if (i && (*this_vp_p)->v_op != umap_vnodeop_p) {
+                       old_vps[i] = NULL;
                } else {
                        old_vps[i] = *this_vp_p;
                        *(vps_p[i]) = UMAPVPTOLOWERVP(*this_vp_p);
                        if (reles & 1)
                                VREF(*this_vp_p);
                } else {
                        old_vps[i] = *this_vp_p;
                        *(vps_p[i]) = UMAPVPTOLOWERVP(*this_vp_p);
                        if (reles & 1)
                                VREF(*this_vp_p);
-               };
+               }
                        
                        
-       };
+       }
 
 
-       /* Doctor the credentials.  (That's the purpose of this layer.) */
+       /*
+        * Fix the credentials.  (That's the purpose of this layer.)
+        */
 
        if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
 
 
        if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {
 
@@ -166,32 +110,48 @@ umap_bypass(ap)
                /* Save old values */
 
                savecredp = (*credpp);
                /* Save old values */
 
                savecredp = (*credpp);
-               saveucredp = u.u_cred;
-               (*credpp) = u.u_cred = crdup(savecredp);
+               (*credpp) = crdup(savecredp);
                credp = *credpp;
 
                if (umap_bug_bypass && credp->cr_uid != 0 )
                        printf("umap_bypass: user was %d, group %d\n", 
                            credp->cr_uid,credp->cr_gid);
 
                credp = *credpp;
 
                if (umap_bug_bypass && credp->cr_uid != 0 )
                        printf("umap_bypass: user was %d, group %d\n", 
                            credp->cr_uid,credp->cr_gid);
 
-               nentries =  MOUNTTOUMAPMOUNT(vp1->v_vfsp)->info_nentries;
-               mapdata =  &(MOUNTTOUMAPMOUNT(vp1->v_vfsp)->info_mapdata[0][0]);
-               gnentries =  MOUNTTOUMAPMOUNT(vp1->v_vfsp)->info_gnentries;
-               gmapdata =  &(MOUNTTOUMAPMOUNT(vp1->v_vfsp)->info_gmapdata[0][0]);
-
-               if (umap_bug_bypass && credp->cr_uid != 0 )
-                       printf("nentries = %d, gnentries = %d\n", nentries, 
-                           gnentries);
-
                /* Map all ids in the credential structure. */
 
                /* Map all ids in the credential structure. */
 
-               umap_mapids(credp,mapdata,nentries,gmapdata,gnentries);
+               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);
        }
 
 
                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.
        /*
         * Call the operation on the lower layer
         * with the modified argument structure.
@@ -204,8 +164,8 @@ umap_bypass(ap)
         * to their original value.
         */
        reles = descp->vdesc_flags;
         * 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)
+       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]) {
                        *(vps_p[i]) = old_vps[i];
                        break;   /* bail out at end of list */
                if (old_vps[i]) {
                        *(vps_p[i]) = old_vps[i];
@@ -222,23 +182,14 @@ umap_bypass(ap)
        if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET &&
            !(descp->vdesc_flags & VDESC_NOMAP_VPP) &&
            !error) {
        if (descp->vdesc_vpp_offset != VDESC_NO_OFFSET &&
            !(descp->vdesc_flags & VDESC_NOMAP_VPP) &&
            !error) {
-               /*
-                * XXX - even though symlink has a vpp arg,
-                * it doesn't return a VREF'ed vpp in that
-                * field.  The vpp arg should become a vp
-                * arg.
-                */
-               if (descp == VDESC(vop_symlink)) {
-#ifdef UMAPFS_DIAGNOSTIC
-                       printf("umap_bypass (symlink), lowervp->usecount = %d\n", (**vppp)->v_usecount);
-#endif
-                       return (error);
-               };
-               vppp=VOPARG_OFFSETTO(struct vnode***,
+               if (descp->vdesc_flags & VDESC_VPP_WILLRELE)
+                       goto out;
+               vppp = VOPARG_OFFSETTO(struct vnode***,
                                 descp->vdesc_vpp_offset,ap);
                error = umap_node_create(old_vps[0]->v_mount, **vppp, *vppp);
        };
 
                                 descp->vdesc_vpp_offset,ap);
                error = umap_node_create(old_vps[0]->v_mount, **vppp, *vppp);
        };
 
+ out:
        /* 
         * Free duplicate cred structure and restore old one.
         */
        /* 
         * Free duplicate cred structure and restore old one.
         */
@@ -248,12 +199,23 @@ umap_bypass(ap)
 
                crfree(credp);
                (*credpp) = savecredp;
 
                crfree(credp);
                (*credpp) = savecredp;
-               u.u_cred = saveucredp;
                if (umap_bug_bypass && (*credpp)->cr_uid != 0 )
                        printf("umap_bypass: returning-user now %d\n\n", 
                            (*credpp)->cr_uid);
        }
 
                if (umap_bug_bypass && (*credpp)->cr_uid != 0 )
                        printf("umap_bypass: returning-user now %d\n\n", 
                            (*credpp)->cr_uid);
        }
 
+       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", 
+                   compcredp->cr_uid);
+
+               crfree(compcredp);
+               (*compnamepp)->cn_cred = savecompcredp;
+               if (umap_bug_bypass && (*credpp)->cr_uid != 0 )
+                       printf("umap_bypass: returning-component-user now %d\n\n", 
+                           compcredp->cr_uid);
+       }
+
        return (error);
 }
 
        return (error);
 }
 
@@ -267,20 +229,24 @@ umap_getattr(ap)
 {
        short uid, gid;
        int error, tmpid, *mapdata, nentries, *gmapdata, gnentries;
 {
        short uid, gid;
        int error, tmpid, *mapdata, nentries, *gmapdata, gnentries;
+       struct vnode **vp1p;
+       struct vnodeop_desc *descp = ap->a_desc;
 
 
-       if (error=umap_bypass(ap))
+       if (error = umap_bypass(ap))
                return error;
        /* Requires that arguments be restored. */
        ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
 
                return error;
        /* 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. */
+       /*
+        * 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.
+        */
 
        /* Find entry in map */
 
 
        /* Find entry in map */
 
@@ -291,10 +257,10 @@ umap_getattr(ap)
                    gid);
 
        vp1p = VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[0],ap);
                    gid);
 
        vp1p = VOPARG_OFFSETTO(struct vnode**,descp->vdesc_vp_offsets[0],ap);
-       nentries =  MOUNTTOUMAPMOUNT((*vp1p)->v_vfsp)->info_nentries;
-       mapdata =  &(MOUNTTOUMAPMOUNT((*vp1p)->v_vfsp)->info_mapdata[0][0]);
-       gnentries =  MOUNTTOUMAPMOUNT((*vp1p)->v_vfsp)->info_gnentries;
-       gmapdata =  &(MOUNTTOUMAPMOUNT((*vp1p)->v_vfsp)->info_gmapdata[0][0]);
+       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. */
 
        /* Reverse map the uid for the vnode.  Since it's a reverse
                map, we can't use umap_mapids() to do it. */
@@ -328,19 +294,12 @@ int
 umap_inactive (ap)
        struct vop_inactive_args *ap;
 {
 umap_inactive (ap)
        struct vop_inactive_args *ap;
 {
-#ifdef UMAPFS_DIAGNOSTIC
-       printf("umap_inactive(ap->a_vp = %x->%x)\n", ap->a_vp, UMAPVPTOLOWERVP(ap->a_vp));
-#endif
        /*
         * 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.
         *
        /*
         * 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.
         *
-        * NEEDSWORK: Someday, consider inactive'ing
-        * the lowervp and then trying to reactivate it
-        * like they do in the name lookup cache code.
-        * That's too much work for now.
         */
        return 0;
 }
         */
        return 0;
 }
@@ -349,48 +308,51 @@ int
 umap_reclaim (ap)
        struct vop_reclaim_args *ap;
 {
 umap_reclaim (ap)
        struct vop_reclaim_args *ap;
 {
-       struct vnode *targetvp;
-
-       /*
-        * Note: at this point, ap->a_vp->v_op == dead_vnodeop_p.
-        */
-#ifdef UMAPFS_DIAGNOSTIC
-       printf("umap_reclaim(ap->a_vp = %x->%x)\n", ap->a_vp, UMAPVPTOLOWERVP(ap->a_vp));
-#endif
-       remque(VTOUMAP(ap->a_vp));           /* NEEDSWORK: What? */
-       vrele (UMAPVPTOLOWERVP(ap->a_vp));   /* release lower layer */
-       FREE(ap->a_vp->v_data, M_TEMP);
-       ap->a_vp->v_data = 0;
-       return (0);
+       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;
+       remque(xp);
+       FREE(vp->v_data, M_TEMP);
+       vp->v_data = NULL;
+       vrele (lowervp);
+       return 0;
 }
 
 int
 }
 
 int
-umap_bmap (ap)
-       struct vop_bmap_args *ap;
+umap_strategy (ap)
+       struct vop_strategy_args *ap;
 {
 {
-#ifdef UMAPFS_DIAGNOSTIC
-       printf("umap_bmap(ap->a_vp = %x->%x)\n", ap->a_vp, UMAPVPTOLOWERVP(ap->a_vp));
-#endif
+       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 VOP_BMAP(UMAPVPTOLOWERVP(ap->a_vp), ap->a_bn, ap->a_vpp, ap->a_bnp);
+       return error;
 }
 
 int
 }
 
 int
-umap_strategy (ap)
-       struct vop_strategy_args *ap;
+umap_bwrite (ap)
+       struct vop_bwrite_args *ap;
 {
 {
+       struct buf *bp = ap->a_bp;
        int error;
        struct vnode *savedvp;
 
        int error;
        struct vnode *savedvp;
 
-#ifdef UMAPFS_DIAGNOSTIC
-       printf("umap_strategy(vp = %x->%x)\n", ap->a_bp->b_vp, UMAPVPTOLOWERVP(ap->a_bp->b_vp));
-#endif
-
-       savedvp = ap->a_bp->b_vp;
+       savedvp = bp->b_vp;
+       bp->b_vp = UMAPVPTOLOWERVP(bp->b_vp);
 
 
-       error = VOP_STRATEGY(ap->a_bp);
+       error = VOP_BWRITE(ap->a_bp);
 
 
-       ap->a_bp->b_vp = savedvp;
+       bp->b_vp = savedvp;
 
        return error;
 }
 
        return error;
 }
@@ -405,12 +367,53 @@ umap_print (ap)
        return 0;
 }
 
        return 0;
 }
 
+int
+umap_rename(ap)
+       struct vop_rename_args *ap;
+{
+       int error;
+       struct componentname *compnamep;
+       struct ucred *compcredp, *savecompcredp;
+       struct vnode *vp;
+
+       /* Now map the second componentname structure kept in this vop's
+        * arguments. 
+        */
+
+       vp = ap->a_fdvp;
+       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 %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))
+               return error;
+       
+       /* Restore the additional mapped componentname cred structure. */
+
+       crfree(compcredp);
+       compnamep->cn_cred = savecompcredp;
+       
+}
 
 /*
  * Global vfs data structures
  */
 /*
 
 /*
  * Global vfs data structures
  */
 /*
- * NEEDSWORK: strategy,bmap are hand coded currently.  They should
+ * XXX - strategy,bwrite are hand coded currently.  They should
  * go away with a merged buffer/block cache.
  *
  */
  * go away with a merged buffer/block cache.
  *
  */
@@ -423,10 +426,10 @@ struct vnodeopv_entry_desc umap_vnodeop_entries[] = {
        { &vop_reclaim_desc, umap_reclaim },
        { &vop_print_desc, umap_print },
 
        { &vop_reclaim_desc, umap_reclaim },
        { &vop_print_desc, umap_print },
 
-       { &vop_bmap_desc, umap_bmap },
        { &vop_strategy_desc, umap_strategy },
        { &vop_strategy_desc, umap_strategy },
+       { &vop_bwrite_desc, umap_bwrite },
 
 
-       { (struct vnodeop_desc*)UMAP, (int(*)())UMAP }
+       { (struct vnodeop_desc*)NULL, (int(*)())NULL }
 };
 struct vnodeopv_desc umap_vnodeop_opv_desc =
        { &umap_vnodeop_p, umap_vnodeop_entries };
 };
 struct vnodeopv_desc umap_vnodeop_opv_desc =
        { &umap_vnodeop_p, umap_vnodeop_entries };