checkpoint
authorJan-Simon Pendry <pendry@ucbvax.Berkeley.EDU>
Wed, 2 Feb 1994 12:45:36 +0000 (04:45 -0800)
committerJan-Simon Pendry <pendry@ucbvax.Berkeley.EDU>
Wed, 2 Feb 1994 12:45:36 +0000 (04:45 -0800)
SCCS-vsn: sys/miscfs/union/union.h 1.3
SCCS-vsn: sys/miscfs/union/union_subr.c 1.3
SCCS-vsn: sys/miscfs/union/union_vnops.c 1.3
SCCS-vsn: sys/miscfs/union/union_vfsops.c 1.3

usr/src/sys/miscfs/union/union.h
usr/src/sys/miscfs/union/union_subr.c
usr/src/sys/miscfs/union/union_vfsops.c
usr/src/sys/miscfs/union/union_vnops.c

index b082a8e..74522c1 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union.h     1.2 (Berkeley) %G%
+ *     @(#)union.h     1.3 (Berkeley) %G%
  */
 
 struct union_args {
  */
 
 struct union_args {
@@ -59,7 +59,7 @@ extern int union_node_create __P((struct mount *mp, struct vnode *target, struct
 #define        VTOUNION(vp) ((struct union_node *)(vp)->v_data)
 #define        UNIONTOV(un) ((un)->un_vnode)
 #define        LOWERVP(vp) (VTOUNION(vp)->un_lowervp)
 #define        VTOUNION(vp) ((struct union_node *)(vp)->v_data)
 #define        UNIONTOV(un) ((un)->un_vnode)
 #define        LOWERVP(vp) (VTOUNION(vp)->un_lowervp)
-#define        UPPERVP(vp) (VTOUNION(vp)->un_lowervp)
+#define        UPPERVP(vp) (VTOUNION(vp)->un_uppervp)
 #define OTHERVP(vp) (UPPERVP(vp) ? UPPERVP(vp) : LOWERVP(vp))
 
 extern int (**union_vnodeop_p)();
 #define OTHERVP(vp) (UPPERVP(vp) ? UPPERVP(vp) : LOWERVP(vp))
 
 extern int (**union_vnodeop_p)();
index 3b77769..71c7f13 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union_subr.c        1.2 (Berkeley) %G%
+ *     @(#)union_subr.c        1.3 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -33,7 +33,14 @@ union_init()
 
 /*
  * allocate a union_node/vnode pair.  the vnode is
 
 /*
  * allocate a union_node/vnode pair.  the vnode is
- * referenced and locked.
+ * referenced and locked.  the new vnode is returned
+ * via (vpp).  (mp) is the mountpoint of the union filesystem,
+ * (dvp) is the parent directory where the upper layer object
+ * should exist (but doesn't) and (cnp) is the componentname
+ * information which is partially copied to allow the upper
+ * layer object to be created at a later time.  (uppervp)
+ * and (lowervp) reference the upper and lower layer objects
+ * being mapped.  either, but not both, can be nil.
  *
  * all union_nodes are maintained on a singly-linked
  * list.  new nodes are only allocated when they cannot
  *
  * all union_nodes are maintained on a singly-linked
  * list.  new nodes are only allocated when they cannot
@@ -64,6 +71,15 @@ union_allocvp(vpp, mp, dvp, cnp, uppervp, lowervp)
        int error;
        struct union_node *un;
        struct union_node **pp;
        int error;
        struct union_node *un;
        struct union_node **pp;
+       struct vnode *xlowervp = 0;
+
+       if (uppervp == 0 && lowervp == 0)
+               panic("union: unidentifiable allocation");
+
+       if (uppervp && lowervp && (uppervp->v_type != lowervp->v_type)) {
+               xlowervp = lowervp;
+               lowervp = 0;
+       }
 
 loop:
        for (un = unhead; un != 0; un = un->un_next) {
 
 loop:
        for (un = unhead; un != 0; un = un->un_next) {
@@ -74,8 +90,10 @@ loop:
                    (UNIONTOV(un)->v_mount == mp)) {
                        if (vget(un->un_vnode, 1))
                                goto loop;
                    (UNIONTOV(un)->v_mount == mp)) {
                        if (vget(un->un_vnode, 1))
                                goto loop;
-                       un->un_lowervp = lowervp;
                        un->un_uppervp = uppervp;
                        un->un_uppervp = uppervp;
+                       if ((lowervp == 0) && un->un_lowervp)
+                               vrele(un->un_lowervp);
+                       un->un_lowervp = lowervp;
                        *vpp = un->un_vnode;
                        return (0);
                }
                        *vpp = un->un_vnode;
                        return (0);
                }
@@ -99,19 +117,25 @@ loop:
        MALLOC((*vpp)->v_data, void *, sizeof(struct union_node),
                M_TEMP, M_WAITOK);
 
        MALLOC((*vpp)->v_data, void *, sizeof(struct union_node),
                M_TEMP, M_WAITOK);
 
+       if (uppervp)
+               (*vpp)->v_type = uppervp->v_type;
+       else
+               (*vpp)->v_type = lowervp->v_type;
        un = VTOUNION(*vpp);
        un->un_next = 0;
        un = VTOUNION(*vpp);
        un->un_next = 0;
-       un->un_dirvp = dvp;
        un->un_uppervp = uppervp;
        un->un_lowervp = lowervp;
        un->un_vnode = *vpp;
        un->un_flags = 0;
        un->un_uppervp = uppervp;
        un->un_lowervp = lowervp;
        un->un_vnode = *vpp;
        un->un_flags = 0;
-       if (cnp) {
+       if (uppervp == 0 && cnp) {
                un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
                bcopy(cnp->cn_nameptr, un->un_path, cnp->cn_namelen);
                un->un_path[cnp->cn_namelen] = '\0';
                un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
                bcopy(cnp->cn_nameptr, un->un_path, cnp->cn_namelen);
                un->un_path[cnp->cn_namelen] = '\0';
+               VREF(dvp);
+               un->un_dirvp = dvp;
        } else {
                un->un_path = 0;
        } else {
                un->un_path = 0;
+               un->un_dirvp = 0;
        }
 
 #ifdef DIAGNOSTIC
        }
 
 #ifdef DIAGNOSTIC
@@ -123,6 +147,12 @@ loop:
                continue;
        *pp = un;
 
                continue;
        *pp = un;
 
+       if (un)
+               un->un_flags |= UN_LOCKED;
+
+       if (xlowervp)
+               vrele(xlowervp);
+
 out:
        unvplock &= ~UN_LOCKED;
 
 out:
        unvplock &= ~UN_LOCKED;
 
@@ -131,9 +161,6 @@ out:
                wakeup((caddr_t) &unvplock);
        }
 
                wakeup((caddr_t) &unvplock);
        }
 
-       if (un)
-               VOP_LOCK(UNIONTOV(un));
-
        return (error);
 }
 
        return (error);
 }
 
index cc52f9e..2a5d97e 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union_vfsops.c      1.2 (Berkeley) %G%
+ *     @(#)union_vfsops.c      1.3 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -161,10 +161,14 @@ union_unmount(mp, mntflags, p)
 
        if (error = union_root(mp, &um_rootvp))
                return (error);
 
        if (error = union_root(mp, &um_rootvp))
                return (error);
-       if (um_rootvp->v_usecount > 1)
+       if (um_rootvp->v_usecount > 1) {
+               vput(um_rootvp);
                return (EBUSY);
                return (EBUSY);
-       if (error = vflush(mp, um_rootvp, flags))
+       }
+       if (error = vflush(mp, um_rootvp, flags)) {
+               vput(um_rootvp);
                return (error);
                return (error);
+       }
 
 #ifdef UNION_DIAGNOSTIC
        vprint("alias root of lower", um_rootvp);
 
 #ifdef UNION_DIAGNOSTIC
        vprint("alias root of lower", um_rootvp);
@@ -178,7 +182,7 @@ union_unmount(mp, mntflags, p)
        /*
         * Release reference on underlying root vnode
         */
        /*
         * Release reference on underlying root vnode
         */
-       vrele(um_rootvp);
+       vput(um_rootvp);
        /*
         * And blow it away for future re-use
         */
        /*
         * And blow it away for future re-use
         */
@@ -208,12 +212,19 @@ union_root(mp, vpp)
        /*
         * Return locked reference to root.
         */
        /*
         * Return locked reference to root.
         */
+       VREF(um->um_uppervp);
+       VREF(um->um_lowervp);
        error = union_allocvp(vpp, mp, (struct vnode *) 0,
                              (struct componentname *) 0,
                              um->um_uppervp,
                              um->um_lowervp);
        error = union_allocvp(vpp, mp, (struct vnode *) 0,
                              (struct componentname *) 0,
                              um->um_uppervp,
                              um->um_lowervp);
-       if (error == 0)
+
+       if (error) {
+               vrele(um->um_uppervp);
+               vrele(um->um_lowervp);
+       } else {
                (*vpp)->v_flag |= VROOT;
                (*vpp)->v_flag |= VROOT;
+       }
 
        return (error);
 }
 
        return (error);
 }
index acde16c..413e3be 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union_vnops.c       1.2 (Berkeley) %G%
+ *     @(#)union_vnops.c       1.3 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
 #include <sys/buf.h>
 #include "union.h"
 
 #include <sys/buf.h>
 #include "union.h"
 
+/*
+ * Create a shadow directory in the upper layer.
+ * The new vnode is returned locked.
+ */
 static int
 union_mkshadow(dvp, cnp, vpp)
        struct vnode *dvp;
 static int
 union_mkshadow(dvp, cnp, vpp)
        struct vnode *dvp;
@@ -34,7 +38,6 @@ union_mkshadow(dvp, cnp, vpp)
        int error;
        struct vattr va;
        struct proc *p = cnp->cn_proc;
        int error;
        struct vattr va;
        struct proc *p = cnp->cn_proc;
-       int lockparent = (cnp->cn_flags & LOCKPARENT);
 
        /*
         * policy: when creating the shadow directory in the
 
        /*
         * policy: when creating the shadow directory in the
@@ -49,13 +52,12 @@ union_mkshadow(dvp, cnp, vpp)
        VATTR_NULL(&va);
        va.va_type = VDIR;
        va.va_mode = UN_DIRMODE &~ p->p_fd->fd_cmask;
        VATTR_NULL(&va);
        va.va_type = VDIR;
        va.va_mode = UN_DIRMODE &~ p->p_fd->fd_cmask;
-       if (lockparent)
-               VOP_UNLOCK(dvp);
+       VOP_UNLOCK(dvp);
        LEASE_CHECK(dvp, p, p->p_ucred, LEASE_WRITE);
        LEASE_CHECK(dvp, p, p->p_ucred, LEASE_WRITE);
+       VREF(dvp);
        VOP_LOCK(dvp);
        error = VOP_MKDIR(dvp, vpp, cnp, &va);
        VOP_LOCK(dvp);
        error = VOP_MKDIR(dvp, vpp, cnp, &va);
-       if (lockparent)
-               VOP_LOCK(dvp);
+       VOP_LOCK(dvp);
        return (error);
 }
 
        return (error);
 }
 
@@ -102,7 +104,7 @@ union_lookup1(dvp, vpp, cnp)
                        return (error);
                }
 
                        return (error);
                }
 
-               vput(tdvp);
+               vput(dvp);
                dvp = tdvp;
        }
 
                dvp = tdvp;
        }
 
@@ -119,6 +121,7 @@ union_lookup(ap)
                struct componentname *a_cnp;
        } */ *ap;
 {
                struct componentname *a_cnp;
        } */ *ap;
 {
+       int error;
        int uerror, lerror;
        struct vnode *uppervp, *lowervp;
        struct vnode *upperdvp, *lowerdvp;
        int uerror, lerror;
        struct vnode *uppervp, *lowervp;
        struct vnode *upperdvp, *lowerdvp;
@@ -127,8 +130,12 @@ union_lookup(ap)
        struct componentname *cnp = ap->a_cnp;
        int lockparent = cnp->cn_flags & LOCKPARENT;
 
        struct componentname *cnp = ap->a_cnp;
        int lockparent = cnp->cn_flags & LOCKPARENT;
 
+       cnp->cn_flags |= LOCKPARENT;
+
        upperdvp = dun->un_uppervp;
        lowerdvp = dun->un_lowervp;
        upperdvp = dun->un_uppervp;
        lowerdvp = dun->un_lowervp;
+       uppervp = 0;
+       lowervp = 0;
 
        /*
         * do the lookup in the upper level.
 
        /*
         * do the lookup in the upper level.
@@ -138,13 +145,16 @@ union_lookup(ap)
         */
        uppervp = 0;
        if (upperdvp) {
         */
        uppervp = 0;
        if (upperdvp) {
+               VOP_LOCK(upperdvp);
                uerror = union_lookup1(upperdvp, &uppervp, cnp);
                uerror = union_lookup1(upperdvp, &uppervp, cnp);
+               VOP_UNLOCK(upperdvp);
+
                if (cnp->cn_consume != 0) {
                        *ap->a_vpp = uppervp;
                if (cnp->cn_consume != 0) {
                        *ap->a_vpp = uppervp;
+                       if (!lockparent)
+                               cnp->cn_flags &= ~LOCKPARENT;
                        return (uerror);
                }
                        return (uerror);
                }
-               if (!lockparent)
-                       VOP_LOCK(upperdvp);
        } else {
                uerror = ENOENT;
        }
        } else {
                uerror = ENOENT;
        }
@@ -158,21 +168,27 @@ union_lookup(ap)
         */
        lowervp = 0;
        if (lowerdvp) {
         */
        lowervp = 0;
        if (lowerdvp) {
+               VOP_LOCK(lowerdvp);
                lerror = union_lookup1(lowerdvp, &lowervp, cnp);
                lerror = union_lookup1(lowerdvp, &lowervp, cnp);
+               VOP_UNLOCK(lowerdvp);
+
                if (cnp->cn_consume != 0) {
                        if (uppervp) {
                                vput(uppervp);
                                uppervp = 0;
                        }
                        *ap->a_vpp = lowervp;
                if (cnp->cn_consume != 0) {
                        if (uppervp) {
                                vput(uppervp);
                                uppervp = 0;
                        }
                        *ap->a_vpp = lowervp;
+                       if (!lockparent)
+                               cnp->cn_flags &= ~LOCKPARENT;
                        return (lerror);
                }
                        return (lerror);
                }
-               if (!lockparent)
-                       VOP_LOCK(lowerdvp);
        } else {
                lerror = ENOENT;
        }
 
        } else {
                lerror = ENOENT;
        }
 
+       if (!lockparent)
+               cnp->cn_flags &= ~LOCKPARENT;
+
        /*
         * at this point, we have uerror and lerror indicating
         * possible errors with the lookups in the upper and lower
        /*
         * at this point, we have uerror and lerror indicating
         * possible errors with the lookups in the upper and lower
@@ -206,7 +222,9 @@ union_lookup(ap)
        /* case 2. */
        if (uerror != 0 /* && (lerror == 0) */ ) {
                if (lowervp->v_type == VDIR) { /* case 2b. */
        /* case 2. */
        if (uerror != 0 /* && (lerror == 0) */ ) {
                if (lowervp->v_type == VDIR) { /* case 2b. */
+                       VOP_LOCK(upperdvp);
                        uerror = union_mkshadow(upperdvp, cnp, &uppervp);
                        uerror = union_mkshadow(upperdvp, cnp, &uppervp);
+                       VOP_UNLOCK(upperdvp);
                        if (uerror) {
                                if (lowervp) {
                                        vput(lowervp);
                        if (uerror) {
                                if (lowervp) {
                                        vput(lowervp);
@@ -217,8 +235,25 @@ union_lookup(ap)
                }
        }
 
                }
        }
 
-       return (union_allocvp(ap->a_vpp, dvp->v_mount, dvp, cnp,
-                             uppervp, lowervp));
+       error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, cnp,
+                             uppervp, lowervp);
+
+       if (uppervp)
+               VOP_UNLOCK(uppervp);
+       if (lowervp)
+               VOP_UNLOCK(lowervp);
+
+       if (error) {
+               if (uppervp)
+                       vrele(uppervp);
+               if (lowervp)
+                       vrele(lowervp);
+       } else {
+               if (!lockparent)
+                       VOP_UNLOCK(*ap->a_vpp);
+       }
+
+       return (error);
 }
 
 int
 }
 
 int
@@ -248,10 +283,13 @@ union_create(ap)
                error = union_allocvp(
                                ap->a_vpp,
                                mp,
                error = union_allocvp(
                                ap->a_vpp,
                                mp,
-                               un->un_uppervp,
+                               NULLVP,
                                ap->a_cnp,
                                vp,
                                NULLVP);
                                ap->a_cnp,
                                vp,
                                NULLVP);
+               VOP_UNLOCK(vp);
+               if (error)
+                       vrele(vp);
                return (error);
        }
 
                return (error);
        }
 
@@ -283,13 +321,18 @@ union_mknod(ap)
                if (error)
                        return (error);
 
                if (error)
                        return (error);
 
-               error = union_allocvp(
-                               ap->a_vpp,
-                               mp,
-                               un->un_uppervp,
-                               ap->a_cnp,
-                               vp,
-                               NULLVP);
+               if (vp) {
+                       error = union_allocvp(
+                                       ap->a_vpp,
+                                       mp,
+                                       NULLVP,
+                                       ap->a_cnp,
+                                       vp,
+                                       NULLVP);
+                       VOP_UNLOCK(vp);
+                       if (error)
+                               vrele(vp);
+               }
                return (error);
        }
 
                return (error);
        }
 
@@ -377,81 +420,86 @@ union_open(ap)
        } */ *ap;
 {
        struct union_node *un = VTOUNION(ap->a_vp);
        } */ *ap;
 {
        struct union_node *un = VTOUNION(ap->a_vp);
+       struct vnode *tvp;
        int mode = ap->a_mode;
        struct ucred *cred = ap->a_cred;
        struct proc *p = ap->a_p;
        int mode = ap->a_mode;
        struct ucred *cred = ap->a_cred;
        struct proc *p = ap->a_p;
+       int error;
 
        /*
         * If there is an existing upper vp then simply open that.
         */
 
        /*
         * If there is an existing upper vp then simply open that.
         */
-       if (un->un_uppervp) {
-               int error;
-
-               VOP_LOCK(un->un_uppervp);
-               error = VOP_OPEN(un->un_uppervp, mode, cred, p);
-               VOP_UNLOCK(un->un_lowervp);
-
-               return (error);
-       }
-
-       /*
-        * If the lower vnode is being opened for writing, then
-        * copy the file contents to the upper vnode and open that,
-        * otherwise can simply open the lower vnode.
-        */
-       if ((ap->a_mode & FWRITE) && (un->un_lowervp->v_type == VREG)) {
-               int error;
-               struct nameidata nd;
-               struct filedesc *fdp = p->p_fd;
-               int fmode;
-               int cmode;
-
-               /*
-                * Open the named file in the upper layer.  Note that
-                * the file may have come into existence *since* the lookup
-                * was done, since the upper layer may really be a
-                * loopback mount of some other filesystem... so open
-                * the file with exclusive create and barf if it already
-                * exists.
-                * XXX - perhaps shoudl re-lookup the node (once more with
-                * feeling) and simply open that.  Who knows.
-                */
-               NDINIT(&nd, CREATE, 0, UIO_SYSSPACE, un->un_path, p);
-               fmode = (O_CREAT|O_TRUNC|O_EXCL);
-               cmode = UN_FILEMODE & ~fdp->fd_cmask;
-               error = vn_open(&nd, fmode, cmode);
-               if (error)
-                       return (error);
-               un->un_uppervp = nd.ni_vp;      /* XXX */
-               /* at this point, uppervp is locked */
-
+       tvp = un->un_uppervp;
+       if (tvp == NULLVP) {
                /*
                /*
-                * Now, if the file is being opened with truncation, then
-                * the (new) upper vnode is ready to fly, otherwise the
-                * data from the lower vnode must be copied to the upper
-                * layer first.  This only works for regular files (check
-                * is made above).
+                * If the lower vnode is being opened for writing, then
+                * copy the file contents to the upper vnode and open that,
+                * otherwise can simply open the lower vnode.
                 */
                 */
-               if ((mode & O_TRUNC) == 0) {
-                       /* XXX - should not ignore errors from VOP_CLOSE */
-                       VOP_LOCK(un->un_lowervp);
-                       error = VOP_OPEN(un->un_lowervp, FREAD, cred, p);
-                       if (error == 0) {
-                               error = union_copyfile(p, cred,
-                                              un->un_lowervp, un->un_uppervp);
-                               (void) VOP_CLOSE(un->un_lowervp, FREAD);
+               tvp = un->un_lowervp;
+               if ((ap->a_mode & FWRITE) && (tvp->v_type == VREG)) {
+                       struct nameidata nd;
+                       struct filedesc *fdp = p->p_fd;
+                       int fmode;
+                       int cmode;
+
+                       /*
+                        * Open the named file in the upper layer.  Note that
+                        * the file may have come into existence *since* the
+                        * lookup was done, since the upper layer may really
+                        * be a loopback mount of some other filesystem...
+                        * so open the file with exclusive create and barf if
+                        * it already exists.
+                        * XXX - perhaps shoudl re-lookup the node (once more
+                        * with feeling) and simply open that.  Who knows.
+                        */
+                       NDINIT(&nd, CREATE, 0, UIO_SYSSPACE, un->un_path, p);
+                       fmode = (O_CREAT|O_TRUNC|O_EXCL);
+                       cmode = UN_FILEMODE & ~fdp->fd_cmask;
+                       error = vn_open(&nd, fmode, cmode);
+                       if (error)
+                               return (error);
+                       un->un_uppervp = nd.ni_vp;      /* XXX */
+                       /* at this point, uppervp is locked */
+
+                       /*
+                        * Now, if the file is being opened with truncation,
+                        * then the (new) upper vnode is ready to fly,
+                        * otherwise the data from the lower vnode must be
+                        * copied to the upper layer first.  This only works
+                        * for regular files (check is made above).
+                        */
+                       if ((mode & O_TRUNC) == 0) {
+                               /*
+                                * XXX - should not ignore errors
+                                * from VOP_CLOSE
+                                */
+                               VOP_LOCK(un->un_lowervp);
+                               error = VOP_OPEN(tvp, FREAD, cred, p);
+                               if (error == 0) {
+                                       error = union_copyfile(p, cred,
+                                                      tvp, un->un_uppervp);
+                                       VOP_UNLOCK(tvp);
+                                       (void) VOP_CLOSE(tvp, FREAD);
+                               } else {
+                                       VOP_UNLOCK(tvp);
+                               }
+                               VOP_UNLOCK(un->un_uppervp);
+                               (void) VOP_CLOSE(un->un_uppervp, FWRITE);
+                               VOP_LOCK(un->un_uppervp);
                        }
                        }
-                       VOP_UNLOCK(un->un_lowervp);
+                       if (error == 0)
+                               error = VOP_OPEN(un->un_uppervp, mode, cred, p);
                        VOP_UNLOCK(un->un_uppervp);
                        VOP_UNLOCK(un->un_uppervp);
-                       (void) VOP_CLOSE(un->un_uppervp, FWRITE);
-                       VOP_LOCK(un->un_uppervp);
+                       return (error);
                }
                }
-               if (error == 0)
-                       error = VOP_OPEN(un->un_uppervp, FREAD, cred, p);
-               return (error);
        }
 
        }
 
-       return (VOP_OPEN(un->un_lowervp, mode, cred, p));
+       VOP_LOCK(tvp);
+       error = VOP_OPEN(tvp, mode, cred, p);
+       VOP_UNLOCK(tvp);
+
+       return (error);
 }
 
 int
 }
 
 int
@@ -486,20 +534,24 @@ union_access(ap)
        } */ *ap;
 {
        struct union_node *un = VTOUNION(ap->a_vp);
        } */ *ap;
 {
        struct union_node *un = VTOUNION(ap->a_vp);
+       int error = 0;
        struct vnode *vp;
 
        if (vp = un->un_lowervp) {
        struct vnode *vp;
 
        if (vp = un->un_lowervp) {
-               int error;
-
+               VOP_LOCK(vp);
                error = VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p);
                error = VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p);
+               VOP_UNLOCK(vp);
                if (error)
                        return (error);
        }
 
                if (error)
                        return (error);
        }
 
-       if (vp = un->un_uppervp)
-               return (VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p));
-       
-       return (0);
+       if (vp = un->un_uppervp) {
+               VOP_LOCK(vp);
+               error = VOP_ACCESS(vp, ap->a_mode, ap->a_cred, ap->a_p);
+               VOP_UNLOCK(vp);
+       }
+
+       return (error);
 }
 
 /*
 }
 
 /*
@@ -515,16 +567,19 @@ union_getattr(ap)
        } */ *ap;
 {
        int error;
        } */ *ap;
 {
        int error;
+       struct vnode *vp = OTHERVP(ap->a_vp);
+
+       VOP_LOCK(vp);
+       error = VOP_GETATTR(vp, ap->a_vap, ap->a_cred, ap->a_p);
+       VOP_UNLOCK(vp);
 
 
-       if (error = union_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 (0);
 }
 
 int
        /* Requires that arguments be restored. */
        ap->a_vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0];
        return (0);
 }
 
 int
-lofs_setattr(ap)
+union_setattr(ap)
        struct vop_setattr_args /* {
                struct vnode *a_vp;
                struct vattr *a_vap;
        struct vop_setattr_args /* {
                struct vnode *a_vp;
                struct vattr *a_vap;
@@ -564,9 +619,9 @@ union_read(ap)
        int error;
        struct vnode *vp = OTHERVP(ap->a_vp);
 
        int error;
        struct vnode *vp = OTHERVP(ap->a_vp);
 
-       VOP_LOCKvp);
+       VOP_LOCK(vp);
        error = VOP_READ(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
        error = VOP_READ(vp, ap->a_uio, ap->a_ioflag, ap->a_cred);
-       VOP_UNLOCKvp);
+       VOP_UNLOCK(vp);
 
        return (error);
 }
 
        return (error);
 }
@@ -849,10 +904,13 @@ union_mkdir(ap)
                error = union_allocvp(
                                ap->a_vpp,
                                mp,
                error = union_allocvp(
                                ap->a_vpp,
                                mp,
-                               un->un_uppervp,
+                               NULLVP,
                                ap->a_cnp,
                                vp,
                                NULLVP);
                                ap->a_cnp,
                                vp,
                                NULLVP);
+               VOP_UNLOCK(vp);
+               if (error)
+                       vrele(vp);
                return (error);
        }
 
                return (error);
        }
 
@@ -919,17 +977,7 @@ union_symlink(ap)
                vput(ap->a_dvp);
                error = VOP_SYMLINK(dvp, &vp, ap->a_cnp,
                                        ap->a_vap, ap->a_target);
                vput(ap->a_dvp);
                error = VOP_SYMLINK(dvp, &vp, ap->a_cnp,
                                        ap->a_vap, ap->a_target);
-               if (error)
-                       return (error);
-
-               error = union_allocvp(
-                               ap->a_vpp,
-                               mp,
-                               un->un_uppervp,
-                               ap->a_cnp,
-                               vp,
-                               NULLVP);
-               vput(*ap->a_vpp);
+               *ap->a_vpp = 0;
                return (error);
        }
 
                return (error);
        }
 
@@ -993,7 +1041,7 @@ union_abortop(ap)
        } */ *ap;
 {
        int error;
        } */ *ap;
 {
        int error;
-       struct vnode *vp = OTHERVP(a->a_dvp);
+       struct vnode *vp = OTHERVP(ap->a_dvp);
        struct union_node *un = VTOUNION(ap->a_dvp);
        int islocked = un->un_flags & UN_LOCKED;
 
        struct union_node *un = VTOUNION(ap->a_dvp);
        int islocked = un->un_flags & UN_LOCKED;
 
@@ -1068,11 +1116,11 @@ union_lock(ap)
 {
        struct union_node *un = VTOUNION(ap->a_vp);
 
 {
        struct union_node *un = VTOUNION(ap->a_vp);
 
+       while (un->un_flags & UN_LOCKED) {
 #ifdef DIAGNOSTIC
 #ifdef DIAGNOSTIC
-       if (un->un_pid == curproc->p_pid)
-               panic("union: locking agsinst myself");
+               if (un->un_pid == curproc->p_pid)
+                       panic("union: locking agsinst myself");
 #endif
 #endif
-       while (un->un_flags & UN_LOCKED) {
                un->un_flags |= UN_WANT;
                sleep((caddr_t) &un->un_flags, PINOD);
        }
                un->un_flags |= UN_WANT;
                sleep((caddr_t) &un->un_flags, PINOD);
        }
@@ -1089,10 +1137,10 @@ union_unlock(ap)
        struct union_node *un = VTOUNION(ap->a_vp);
 
 #ifdef DIAGNOSTIC
        struct union_node *un = VTOUNION(ap->a_vp);
 
 #ifdef DIAGNOSTIC
-       if (un->un_pid != curproc->p_pid)
-               panic("union: unlocking other process's union node");
        if ((un->un_flags & UN_LOCKED) == 0)
                panic("union: unlock unlocked node");
        if ((un->un_flags & UN_LOCKED) == 0)
                panic("union: unlock unlocked node");
+       if (un->un_pid != curproc->p_pid)
+               panic("union: unlocking other process's union node");
 #endif
 
        un->un_flags &= ~UN_LOCKED;
 #endif
 
        un->un_flags &= ~UN_LOCKED;
@@ -1219,7 +1267,7 @@ union_strategy(ap)
  * Global vfs data structures
  */
 int (**union_vnodeop_p)();
  * Global vfs data structures
  */
 int (**union_vnodeop_p)();
-struct vnodeopv_entry_desc lofs_vnodeop_entries[] = {
+struct vnodeopv_entry_desc union_vnodeop_entries[] = {
        { &vop_default_desc, vn_default_error },
        { &vop_lookup_desc, union_lookup },             /* lookup */
        { &vop_create_desc, union_create },             /* create */
        { &vop_default_desc, vn_default_error },
        { &vop_lookup_desc, union_lookup },             /* lookup */
        { &vop_create_desc, union_create },             /* create */