checkpoint
[unix-history] / usr / src / sys / miscfs / union / union_subr.c
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);