checkpoint
authorJan-Simon Pendry <pendry@ucbvax.Berkeley.EDU>
Fri, 4 Feb 1994 04:25:30 +0000 (20:25 -0800)
committerJan-Simon Pendry <pendry@ucbvax.Berkeley.EDU>
Fri, 4 Feb 1994 04:25:30 +0000 (20:25 -0800)
SCCS-vsn: sys/miscfs/union/union_vnops.c 1.4
SCCS-vsn: sys/miscfs/union/union_vfsops.c 1.4
SCCS-vsn: sys/miscfs/union/union.h 1.4
SCCS-vsn: sys/miscfs/union/union_subr.c 1.4

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 74522c1..5c82d1d 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union.h     1.3 (Berkeley) %G%
+ *     @(#)union.h     1.4 (Berkeley) %G%
  */
 
 struct union_args {
  */
 
 struct union_args {
@@ -41,10 +41,10 @@ struct union_mount {
  */
 struct union_node {
        struct union_node       *un_next;       /* Hash chain */
  */
 struct union_node {
        struct union_node       *un_next;       /* Hash chain */
+       struct vnode            *un_vnode;      /* Back pointer */
        struct vnode            *un_uppervp;    /* overlaying object */
        struct vnode            *un_lowervp;    /* underlying object */
        struct vnode            *un_dirvp;      /* Parent dir of uppervp */
        struct vnode            *un_uppervp;    /* overlaying object */
        struct vnode            *un_lowervp;    /* underlying object */
        struct vnode            *un_dirvp;      /* Parent dir of uppervp */
-       struct vnode            *un_vnode;      /* Back pointer */
        char                    *un_path;       /* saved component name */
        int                     un_flags;
        pid_t                   un_pid;
        char                    *un_path;       /* saved component name */
        int                     un_flags;
        pid_t                   un_pid;
@@ -53,7 +53,7 @@ struct union_node {
 #define UN_WANT 0x01
 #define UN_LOCKED 0x02
 
 #define UN_WANT 0x01
 #define UN_LOCKED 0x02
 
-extern int union_node_create __P((struct mount *mp, struct vnode *target, struct vnode **vpp));
+extern int union_allocvp __P((struct vnode **, struct mount *, struct vnode *, struct vnode *, struct componentname *, struct vnode *, struct vnode *));
 
 #define        MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
 #define        VTOUNION(vp) ((struct union_node *)(vp)->v_data)
 
 #define        MOUNTTOUNIONMOUNT(mp) ((struct union_mount *)((mp)->mnt_data))
 #define        VTOUNION(vp) ((struct union_node *)(vp)->v_data)
index 71c7f13..a963d7d 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union_subr.c        1.3 (Berkeley) %G%
+ *     @(#)union_subr.c        1.4 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
 #include <sys/malloc.h>
 #include "union.h" /*<miscfs/union/union.h>*/
 
 #include <sys/malloc.h>
 #include "union.h" /*<miscfs/union/union.h>*/
 
+#ifdef DIAGNOSTIC
+#include <sys/proc.h>
+#endif
+
 static struct union_node *unhead;
 static int unvplock;
 
 static struct union_node *unhead;
 static int unvplock;
 
@@ -60,9 +64,10 @@ union_init()
  * the vnode free list.
  */
 int
  * the vnode free list.
  */
 int
-union_allocvp(vpp, mp, dvp, cnp, uppervp, lowervp)
+union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp)
        struct vnode **vpp;
        struct mount *mp;
        struct vnode **vpp;
        struct mount *mp;
+       struct vnode *undvp;
        struct vnode *dvp;              /* may be null */
        struct componentname *cnp;      /* may be null */
        struct vnode *uppervp;          /* may be null */
        struct vnode *dvp;              /* may be null */
        struct componentname *cnp;      /* may be null */
        struct vnode *uppervp;          /* may be null */
@@ -88,13 +93,21 @@ loop:
                    (un->un_uppervp == uppervp ||
                     un->un_uppervp == 0) &&
                    (UNIONTOV(un)->v_mount == mp)) {
                    (un->un_uppervp == uppervp ||
                     un->un_uppervp == 0) &&
                    (UNIONTOV(un)->v_mount == mp)) {
-                       if (vget(un->un_vnode, 1))
+                       if (vget(UNIONTOV(un), 0))
                                goto loop;
                                goto loop;
-                       un->un_uppervp = uppervp;
-                       if ((lowervp == 0) && un->un_lowervp)
-                               vrele(un->un_lowervp);
-                       un->un_lowervp = lowervp;
-                       *vpp = un->un_vnode;
+                       if (UNIONTOV(un) != undvp)
+                               VOP_LOCK(UNIONTOV(un));
+                       if (uppervp != un->un_uppervp) {
+                               if (un->un_uppervp)
+                                       vrele(un->un_uppervp);
+                               un->un_uppervp = uppervp;
+                       }
+                       if (lowervp != un->un_lowervp) {
+                               if (un->un_lowervp)
+                                       vrele(un->un_lowervp);
+                               un->un_lowervp = lowervp;
+                       }
+                       *vpp = UNIONTOV(un);
                        return (0);
                }
        }
                        return (0);
                }
        }
@@ -122,10 +135,10 @@ loop:
        else
                (*vpp)->v_type = lowervp->v_type;
        un = VTOUNION(*vpp);
        else
                (*vpp)->v_type = lowervp->v_type;
        un = VTOUNION(*vpp);
+       un->un_vnode = *vpp;
        un->un_next = 0;
        un->un_uppervp = uppervp;
        un->un_lowervp = lowervp;
        un->un_next = 0;
        un->un_uppervp = uppervp;
        un->un_lowervp = lowervp;
-       un->un_vnode = *vpp;
        un->un_flags = 0;
        if (uppervp == 0 && cnp) {
                un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
        un->un_flags = 0;
        if (uppervp == 0 && cnp) {
                un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
@@ -138,17 +151,16 @@ loop:
                un->un_dirvp = 0;
        }
 
                un->un_dirvp = 0;
        }
 
-#ifdef DIAGNOSTIC
-       un->un_pid = 0;
-#endif
-
        /* add to union vnode list */
        for (pp = &unhead; *pp; pp = &(*pp)->un_next)
                continue;
        *pp = un;
 
        /* add to union vnode list */
        for (pp = &unhead; *pp; pp = &(*pp)->un_next)
                continue;
        *pp = un;
 
-       if (un)
-               un->un_flags |= UN_LOCKED;
+       un->un_flags |= UN_LOCKED;
+
+#ifdef DIAGNOSTIC
+       un->un_pid = curproc->p_pid;
+#endif
 
        if (xlowervp)
                vrele(xlowervp);
 
        if (xlowervp)
                vrele(xlowervp);
index 2a5d97e..85d1957 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union_vfsops.c      1.3 (Berkeley) %G%
+ *     @(#)union_vfsops.c      1.4 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -214,7 +214,9 @@ union_root(mp, vpp)
         */
        VREF(um->um_uppervp);
        VREF(um->um_lowervp);
         */
        VREF(um->um_uppervp);
        VREF(um->um_lowervp);
-       error = union_allocvp(vpp, mp, (struct vnode *) 0,
+       error = union_allocvp(vpp, mp,
+                             (struct vnode *) 0,
+                             (struct vnode *) 0,
                              (struct componentname *) 0,
                              um->um_uppervp,
                              um->um_lowervp);
                              (struct componentname *) 0,
                              um->um_uppervp,
                              um->um_lowervp);
index 413e3be..1cb2e3d 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union_vnops.c       1.3 (Berkeley) %G%
+ *     @(#)union_vnops.c       1.4 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -62,7 +62,8 @@ union_mkshadow(dvp, cnp, vpp)
 }
 
 static int
 }
 
 static int
-union_lookup1(dvp, vpp, cnp)
+union_lookup1(udvp, dvp, vpp, cnp)
+       struct vnode *udvp;
        struct vnode *dvp;
        struct vnode **vpp;
        struct componentname *cnp;
        struct vnode *dvp;
        struct vnode **vpp;
        struct componentname *cnp;
@@ -90,7 +91,8 @@ union_lookup1(dvp, vpp, cnp)
                return (error);
 
        dvp = tdvp;
                return (error);
 
        dvp = tdvp;
-       while ((dvp->v_type == VDIR) && (mp = dvp->v_mountedhere) &&
+       while (dvp != udvp && (dvp->v_type == VDIR) &&
+              (mp = dvp->v_mountedhere) &&
               (cnp->cn_flags & NOCROSSMOUNT) == 0) {
 
                if (mp->mnt_flag & MNT_MLOCK) {
               (cnp->cn_flags & NOCROSSMOUNT) == 0) {
 
                if (mp->mnt_flag & MNT_MLOCK) {
@@ -126,7 +128,7 @@ union_lookup(ap)
        struct vnode *uppervp, *lowervp;
        struct vnode *upperdvp, *lowerdvp;
        struct vnode *dvp = ap->a_dvp;
        struct vnode *uppervp, *lowervp;
        struct vnode *upperdvp, *lowerdvp;
        struct vnode *dvp = ap->a_dvp;
-       struct union_node *dun = VTOUNION(ap->a_dvp);
+       struct union_node *dun = VTOUNION(dvp);
        struct componentname *cnp = ap->a_cnp;
        int lockparent = cnp->cn_flags & LOCKPARENT;
 
        struct componentname *cnp = ap->a_cnp;
        int lockparent = cnp->cn_flags & LOCKPARENT;
 
@@ -143,11 +145,13 @@ union_lookup(ap)
         * then assume that something special is going
         * on and just return that vnode.
         */
         * then assume that something special is going
         * on and just return that vnode.
         */
-       uppervp = 0;
        if (upperdvp) {
                VOP_LOCK(upperdvp);
        if (upperdvp) {
                VOP_LOCK(upperdvp);
-               uerror = union_lookup1(upperdvp, &uppervp, cnp);
-               VOP_UNLOCK(upperdvp);
+               uerror = union_lookup1(
+                       MOUNTTOUNIONMOUNT(dvp->v_mount)->um_uppervp,
+                       upperdvp, &uppervp, cnp);
+               if (uppervp != upperdvp)
+                       VOP_UNLOCK(upperdvp);
 
                if (cnp->cn_consume != 0) {
                        *ap->a_vpp = uppervp;
 
                if (cnp->cn_consume != 0) {
                        *ap->a_vpp = uppervp;
@@ -166,11 +170,13 @@ union_lookup(ap)
         * back from the upper layer and return the lower vnode
         * instead.
         */
         * back from the upper layer and return the lower vnode
         * instead.
         */
-       lowervp = 0;
        if (lowerdvp) {
                VOP_LOCK(lowerdvp);
        if (lowerdvp) {
                VOP_LOCK(lowerdvp);
-               lerror = union_lookup1(lowerdvp, &lowervp, cnp);
-               VOP_UNLOCK(lowerdvp);
+               lerror = union_lookup1(
+                       MOUNTTOUNIONMOUNT(dvp->v_mount)->um_lowervp,
+                       lowerdvp, &lowervp, cnp);
+               if (lowervp != lowerdvp)
+                       VOP_UNLOCK(lowerdvp);
 
                if (cnp->cn_consume != 0) {
                        if (uppervp) {
 
                if (cnp->cn_consume != 0) {
                        if (uppervp) {
@@ -222,9 +228,11 @@ 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);
+                       if (uppervp != upperdvp)
+                               VOP_LOCK(upperdvp);
                        uerror = union_mkshadow(upperdvp, cnp, &uppervp);
                        uerror = union_mkshadow(upperdvp, cnp, &uppervp);
-                       VOP_UNLOCK(upperdvp);
+                       if (uppervp != upperdvp)
+                               VOP_UNLOCK(upperdvp);
                        if (uerror) {
                                if (lowervp) {
                                        vput(lowervp);
                        if (uerror) {
                                if (lowervp) {
                                        vput(lowervp);
@@ -235,7 +243,7 @@ union_lookup(ap)
                }
        }
 
                }
        }
 
-       error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, cnp,
+       error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp,
                              uppervp, lowervp);
 
        if (uppervp)
                              uppervp, lowervp);
 
        if (uppervp)
@@ -249,8 +257,8 @@ union_lookup(ap)
                if (lowervp)
                        vrele(lowervp);
        } else {
                if (lowervp)
                        vrele(lowervp);
        } else {
-               if (!lockparent)
-                       VOP_UNLOCK(*ap->a_vpp);
+               if (!lockparent && (*ap->a_vpp != dvp))
+                       VOP_UNLOCK(dvp);
        }
 
        return (error);
        }
 
        return (error);
@@ -271,7 +279,6 @@ union_create(ap)
        if (dvp) {
                int error;
                struct vnode *vp;
        if (dvp) {
                int error;
                struct vnode *vp;
-               struct mount *mp = ap->a_dvp->v_mount;
 
                VREF(dvp);
                VOP_LOCK(dvp);
 
                VREF(dvp);
                VOP_LOCK(dvp);
@@ -282,7 +289,8 @@ union_create(ap)
 
                error = union_allocvp(
                                ap->a_vpp,
 
                error = union_allocvp(
                                ap->a_vpp,
-                               mp,
+                               ap->a_dvp->v_mount,
+                               ap->a_dvp,
                                NULLVP,
                                ap->a_cnp,
                                vp,
                                NULLVP,
                                ap->a_cnp,
                                vp,
@@ -312,7 +320,6 @@ union_mknod(ap)
        if (dvp) {
                int error;
                struct vnode *vp;
        if (dvp) {
                int error;
                struct vnode *vp;
-               struct mount *mp = ap->a_dvp->v_mount;
 
                VREF(dvp);
                VOP_LOCK(dvp);
 
                VREF(dvp);
                VOP_LOCK(dvp);
@@ -324,7 +331,8 @@ union_mknod(ap)
                if (vp) {
                        error = union_allocvp(
                                        ap->a_vpp,
                if (vp) {
                        error = union_allocvp(
                                        ap->a_vpp,
-                                       mp,
+                                       ap->a_dvp->v_mount,
+                                       ap->a_dvp,
                                        NULLVP,
                                        ap->a_cnp,
                                        vp,
                                        NULLVP,
                                        ap->a_cnp,
                                        vp,
@@ -892,7 +900,6 @@ union_mkdir(ap)
        if (dvp) {
                int error;
                struct vnode *vp;
        if (dvp) {
                int error;
                struct vnode *vp;
-               struct mount *mp = ap->a_dvp->v_mount;
 
                VREF(dvp);
                VOP_LOCK(dvp);
 
                VREF(dvp);
                VOP_LOCK(dvp);
@@ -903,7 +910,8 @@ union_mkdir(ap)
 
                error = union_allocvp(
                                ap->a_vpp,
 
                error = union_allocvp(
                                ap->a_vpp,
-                               mp,
+                               ap->a_dvp->v_mount,
+                               ap->a_dvp,
                                NULLVP,
                                ap->a_cnp,
                                vp,
                                NULLVP,
                                ap->a_cnp,
                                vp,
@@ -1073,6 +1081,14 @@ union_inactive(ap)
         * like they do in the name lookup cache code.
         * That's too much work for now.
         */
         * like they do in the name lookup cache code.
         * That's too much work for now.
         */
+
+#ifdef DIAGNOSTIC
+       struct union_node *un = VTOUNION(ap->a_vp);
+
+       if (un->un_flags & UN_LOCKED)
+               panic("union: inactivating locked node");
+#endif
+
        return (0);
 }
 
        return (0);
 }
 
@@ -1118,15 +1134,20 @@ union_lock(ap)
 
        while (un->un_flags & UN_LOCKED) {
 #ifdef DIAGNOSTIC
 
        while (un->un_flags & UN_LOCKED) {
 #ifdef DIAGNOSTIC
-               if (un->un_pid == curproc->p_pid)
-                       panic("union: locking agsinst myself");
+               if (curproc && un->un_pid == curproc->p_pid &&
+                           un->un_pid > -1 && curproc->p_pid > -1)
+                       panic("union: locking against myself");
 #endif
                un->un_flags |= UN_WANT;
                sleep((caddr_t) &un->un_flags, PINOD);
        }
        un->un_flags |= UN_LOCKED;
 #endif
                un->un_flags |= UN_WANT;
                sleep((caddr_t) &un->un_flags, PINOD);
        }
        un->un_flags |= UN_LOCKED;
+
 #ifdef DIAGNOSTIC
 #ifdef DIAGNOSTIC
-       un->un_pid = curproc->p_pid;
+       if (curproc)
+               un->un_pid = curproc->p_pid;
+       else
+               un->un_pid = -1;
 #endif
 }
 
 #endif
 }
 
@@ -1139,7 +1160,8 @@ union_unlock(ap)
 #ifdef DIAGNOSTIC
        if ((un->un_flags & UN_LOCKED) == 0)
                panic("union: unlock unlocked node");
 #ifdef DIAGNOSTIC
        if ((un->un_flags & UN_LOCKED) == 0)
                panic("union: unlock unlocked node");
-       if (un->un_pid != curproc->p_pid)
+       if (curproc && un->un_pid != curproc->p_pid &&
+                       curproc->p_pid > -1 && un->un_pid > -1)
                panic("union: unlocking other process's union node");
 #endif
 
                panic("union: unlocking other process's union node");
 #endif