handle weird cases of stepping back across mount points
[unix-history] / usr / src / sys / miscfs / union / union_vnops.c
index 7766a4a..d6115ce 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union_vnops.c       8.6 (Berkeley) %G%
+ *     @(#)union_vnops.c       8.7 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -41,16 +41,19 @@ union_fixup(un)
 }
 
 static int
 }
 
 static int
-union_lookup1(udvp, dvp, vpp, cnp)
+union_lookup1(udvp, dvpp, vpp, cnp)
        struct vnode *udvp;
        struct vnode *udvp;
-       struct vnode *dvp;
+       struct vnode **dvpp;
        struct vnode **vpp;
        struct componentname *cnp;
 {
        int error;
        struct vnode *tdvp;
        struct vnode **vpp;
        struct componentname *cnp;
 {
        int error;
        struct vnode *tdvp;
+       struct vnode *dvp;
        struct mount *mp;
 
        struct mount *mp;
 
+       dvp = *dvpp;
+
        /*
         * If stepping up the directory tree, check for going
         * back across the mount point, in which case do what
        /*
         * If stepping up the directory tree, check for going
         * back across the mount point, in which case do what
@@ -58,18 +61,15 @@ union_lookup1(udvp, dvp, vpp, cnp)
         * hierarchy.
         */
        if (cnp->cn_flags & ISDOTDOT) {
         * hierarchy.
         */
        if (cnp->cn_flags & ISDOTDOT) {
-               for (;;) {
+               while ((dvp != udvp) && (dvp->v_flag & VROOT)) {
                        /*
                         * Don't do the NOCROSSMOUNT check
                         * at this level.  By definition,
                         * union fs deals with namespaces, not
                         * filesystems.
                         */
                        /*
                         * Don't do the NOCROSSMOUNT check
                         * at this level.  By definition,
                         * union fs deals with namespaces, not
                         * filesystems.
                         */
-                       if ((dvp->v_flag & VROOT) == 0)
-                               break;
-
                        tdvp = dvp;
                        tdvp = dvp;
-                       dvp = dvp->v_mount->mnt_vnodecovered;
+                       *dvpp = dvp = dvp->v_mount->mnt_vnodecovered;
                        vput(tdvp);
                        VREF(dvp);
                        VOP_LOCK(dvp);
                        vput(tdvp);
                        VREF(dvp);
                        VOP_LOCK(dvp);
@@ -153,7 +153,7 @@ union_lookup(ap)
         */
        if (upperdvp) {
                FIXUP(dun);
         */
        if (upperdvp) {
                FIXUP(dun);
-               uerror = union_lookup1(um->um_uppervp, upperdvp,
+               uerror = union_lookup1(um->um_uppervp, &upperdvp,
                                        &uppervp, cnp);
                /*if (uppervp == upperdvp)
                        dun->un_flags |= UN_KLOCK;*/
                                        &uppervp, cnp);
                /*if (uppervp == upperdvp)
                        dun->un_flags |= UN_KLOCK;*/
@@ -190,7 +190,7 @@ union_lookup(ap)
                        saved_cred = cnp->cn_cred;
                        cnp->cn_cred = um->um_cred;
                }
                        saved_cred = cnp->cn_cred;
                        cnp->cn_cred = um->um_cred;
                }
-               lerror = union_lookup1(um->um_lowervp, lowerdvp,
+               lerror = union_lookup1(um->um_lowervp, &lowerdvp,
                                &lowervp, cnp);
                if (um->um_op == UNMNT_BELOW)
                        cnp->cn_cred = saved_cred;
                                &lowervp, cnp);
                if (um->um_op == UNMNT_BELOW)
                        cnp->cn_cred = saved_cred;