checkpoint
authorJan-Simon Pendry <pendry@ucbvax.Berkeley.EDU>
Tue, 8 Feb 1994 08:13:18 +0000 (00:13 -0800)
committerJan-Simon Pendry <pendry@ucbvax.Berkeley.EDU>
Tue, 8 Feb 1994 08:13:18 +0000 (00:13 -0800)
SCCS-vsn: sys/miscfs/union/union.h 1.7
SCCS-vsn: sys/miscfs/union/union_subr.c 1.7
SCCS-vsn: sys/miscfs/union/union_vnops.c 1.7
SCCS-vsn: sys/miscfs/union/union_vfsops.c 1.7

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 42ba138..f989af6 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union.h     1.6 (Berkeley) %G%
+ *     @(#)union.h     1.7 (Berkeley) %G%
  */
 
 struct union_args {
  */
 
 struct union_args {
@@ -42,9 +42,12 @@ struct union_node {
        struct vnode            *un_lowervp;    /* underlying object */
        struct vnode            *un_dirvp;      /* Parent dir of uppervp */
        char                    *un_path;       /* saved component name */
        struct vnode            *un_lowervp;    /* underlying object */
        struct vnode            *un_dirvp;      /* Parent dir of uppervp */
        char                    *un_path;       /* saved component name */
-       int                     un_open;        /* # of opens on lowervp */
+       int                     un_hash;        /* saved un_path hash value */
+       int                     un_openl;       /* # of opens on lowervp */
        int                     un_flags;
        int                     un_flags;
+#ifdef DIAGNOSTIC
        pid_t                   un_pid;
        pid_t                   un_pid;
+#endif
 };
 
 #define UN_WANT 0x01
 };
 
 #define UN_WANT 0x01
@@ -60,6 +63,7 @@ extern int union_mkshadow __P((struct union_mount *, struct vnode *,
                                struct componentname *, struct vnode **));
 extern int union_vn_create __P((struct vnode **, struct union_node *,
                                struct proc *));
                                struct componentname *, struct vnode **));
 extern int union_vn_create __P((struct vnode **, struct union_node *,
                                struct proc *));
+extern void union_removed_upper __P((struct union_node *un));
 
 #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 4532682..d34f594 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union_subr.c        1.6 (Berkeley) %G%
+ *     @(#)union_subr.c        1.7 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -101,6 +101,10 @@ loop:
                                goto loop;
                        if (UNIONTOV(un) != undvp)
                                VOP_LOCK(UNIONTOV(un));
                                goto loop;
                        if (UNIONTOV(un) != undvp)
                                VOP_LOCK(UNIONTOV(un));
+
+                       /*
+                        * Save information about the upper layer.
+                        */
                        if (uppervp != un->un_uppervp) {
                                if (un->un_uppervp)
                                        vrele(un->un_uppervp);
                        if (uppervp != un->un_uppervp) {
                                if (un->un_uppervp)
                                        vrele(un->un_uppervp);
@@ -108,10 +112,31 @@ loop:
                        } else if (uppervp) {
                                vrele(uppervp);
                        }
                        } else if (uppervp) {
                                vrele(uppervp);
                        }
+
+                       /*
+                        * Save information about the lower layer.
+                        * This needs to keep track of pathname
+                        * and directory information which union_vn_create
+                        * might need.
+                        */
                        if (lowervp != un->un_lowervp) {
                        if (lowervp != un->un_lowervp) {
-                               if (un->un_lowervp)
+                               if (un->un_lowervp) {
                                        vrele(un->un_lowervp);
                                        vrele(un->un_lowervp);
+                                       free(un->un_path, M_TEMP);
+                                       vrele(un->un_dirvp);
+                               }
                                un->un_lowervp = lowervp;
                                un->un_lowervp = lowervp;
+                               if (cnp && (lowervp != NULLVP) &&
+                                   (lowervp->v_type == VREG)) {
+                                       un->un_hash = cnp->cn_hash;
+                                       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 if (lowervp) {
                                vrele(lowervp);
                        }
                        } else if (lowervp) {
                                vrele(lowervp);
                        }
@@ -149,13 +174,15 @@ loop:
        un->un_lowervp = lowervp;
        un->un_open = 0;
        un->un_flags = 0;
        un->un_lowervp = lowervp;
        un->un_open = 0;
        un->un_flags = 0;
-       if (uppervp == 0 && cnp) {
+       if (cnp && (lowervp != NULLVP) && (lowervp->v_type == VREG)) {
+               un->un_hash = cnp->cn_hash;
                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 = 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_hash = 0;
                un->un_path = 0;
                un->un_dirvp = 0;
        }
                un->un_path = 0;
                un->un_dirvp = 0;
        }
@@ -323,7 +350,8 @@ union_mkshadow(um, dvp, cnp, vpp)
         * The pathname buffer will be FREEed by VOP_MKDIR.
         */
        cn.cn_pnbuf = malloc(cnp->cn_namelen+1, M_NAMEI, M_WAITOK);
         * The pathname buffer will be FREEed by VOP_MKDIR.
         */
        cn.cn_pnbuf = malloc(cnp->cn_namelen+1, M_NAMEI, M_WAITOK);
-       bcopy(cnp->cn_nameptr, cn.cn_pnbuf, cnp->cn_namelen+1);
+       bcopy(cnp->cn_nameptr, cn.cn_pnbuf, cnp->cn_namelen);
+       cn.cn_pnbuf[cnp->cn_namelen] = '\0';
 
        cn.cn_nameiop = CREATE;
        cn.cn_flags = (LOCKPARENT|HASBUF|SAVENAME|ISLASTCN);
 
        cn.cn_nameiop = CREATE;
        cn.cn_flags = (LOCKPARENT|HASBUF|SAVENAME|ISLASTCN);
@@ -334,8 +362,10 @@ union_mkshadow(um, dvp, cnp, vpp)
        cn.cn_hash = cnp->cn_hash;
        cn.cn_consume = cnp->cn_consume;
 
        cn.cn_hash = cnp->cn_hash;
        cn.cn_consume = cnp->cn_consume;
 
+       VREF(dvp);
        if (error = relookup(dvp, vpp, &cn))
                return (error);
        if (error = relookup(dvp, vpp, &cn))
                return (error);
+       vrele(dvp);
 
        if (*vpp) {
                VOP_ABORTOP(dvp, &cn);
 
        if (*vpp) {
                VOP_ABORTOP(dvp, &cn);
@@ -347,7 +377,7 @@ union_mkshadow(um, dvp, cnp, vpp)
 
        VATTR_NULL(&va);
        va.va_type = VDIR;
 
        VATTR_NULL(&va);
        va.va_type = VDIR;
-       va.va_mode = UN_DIRMODE &p->p_fd->fd_cmask;
+       va.va_mode = UN_DIRMODE & ~p->p_fd->fd_cmask;
 
        /* LEASE_CHECK: dvp is locked */
        LEASE_CHECK(dvp, p, p->p_ucred, LEASE_WRITE);
 
        /* LEASE_CHECK: dvp is locked */
        LEASE_CHECK(dvp, p, p->p_ucred, LEASE_WRITE);
@@ -377,8 +407,7 @@ union_vn_create(vpp, un, p)
        struct vattr *vap = &vat;
        int fmode = FFLAGS(O_WRONLY|O_CREAT|O_TRUNC|O_EXCL);
        int error;
        struct vattr *vap = &vat;
        int fmode = FFLAGS(O_WRONLY|O_CREAT|O_TRUNC|O_EXCL);
        int error;
-       int hash;
-       int cmode = UN_FILEMODE &~ p->p_fd->fd_cmask;
+       int cmode = UN_FILEMODE & ~p->p_fd->fd_cmask;
        char *cp;
        struct componentname cn;
 
        char *cp;
        struct componentname cn;
 
@@ -392,13 +421,14 @@ union_vn_create(vpp, un, p)
        cn.cn_proc = p;
        cn.cn_cred = p->p_ucred;
        cn.cn_nameptr = cn.cn_pnbuf;
        cn.cn_proc = p;
        cn.cn_cred = p->p_ucred;
        cn.cn_nameptr = cn.cn_pnbuf;
-       for (hash = 0, cp = cn.cn_nameptr; *cp != 0 && *cp != '/'; cp++)
-               hash += (unsigned char)*cp;
-       cn.cn_hash = hash;
+       cn.cn_hash = un->un_hash;
        cn.cn_consume = 0;
 
        cn.cn_consume = 0;
 
+       VREF(un->un_dirvp);
        if (error = relookup(un->un_dirvp, &vp, &cn))
                return (error);
        if (error = relookup(un->un_dirvp, &vp, &cn))
                return (error);
+       vrele(un->un_dirvp);
+
        if (vp == NULLVP) {
                VATTR_NULL(vap);
                vap->va_type = VREG;
        if (vp == NULLVP) {
                VATTR_NULL(vap);
                vap->va_type = VREG;
@@ -440,3 +470,21 @@ bad:
        vput(vp);
        return (error);
 }
        vput(vp);
        return (error);
 }
+
+int
+union_vn_close(vp, fmode)
+       struct vnode *vp;
+       int fmode;
+{
+       if (fmode & FWRITE)
+               --vp->v_writecount;
+       return (VOP_CLOSE(vp, fmode));
+}
+
+void
+union_removed_upper(un)
+       struct union_node *un;
+{
+       vrele(un->un_uppervp);
+       un->un_uppervp = NULLVP;
+}
index fb93df3..49466ee 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union_vfsops.c      1.6 (Berkeley) %G%
+ *     @(#)union_vfsops.c      1.7 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
index 2b1be68..65976d3 100644 (file)
@@ -8,7 +8,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)union_vnops.c       1.6 (Berkeley) %G%
+ *     @(#)union_vnops.c       1.7 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -54,18 +54,17 @@ union_lookup1(udvp, dvp, vpp, cnp)
                        VOP_LOCK(dvp);
                }
        }
                        VOP_LOCK(dvp);
                }
        }
-       
+
         error = VOP_LOOKUP(dvp, &tdvp, cnp);
        if (error)
                return (error);
 
        /*
         error = VOP_LOOKUP(dvp, &tdvp, cnp);
        if (error)
                return (error);
 
        /*
-        * If going back up the directory tree, then the parent directory
-        * will have been unlocked, unless lookup found the last
-        * component.  In which case, re-lock the node here to allow
-        * it to be unlocked again (phew) in union_lookup.
+        * The parent directory will have been unlocked, unless lookup
+        * found the last component.  In which case, re-lock the node
+        * here to allow it to be unlocked again (phew) in union_lookup.
         */
         */
-       if ((cnp->cn_flags & ISDOTDOT) && !(cnp->cn_flags & ISLASTCN))
+       if (dvp != tdvp && !(cnp->cn_flags & ISLASTCN))
                VOP_LOCK(dvp);
 
        dvp = tdvp;
                VOP_LOCK(dvp);
 
        dvp = tdvp;
@@ -203,9 +202,10 @@ union_lookup(ap)
         *    whatever the bottom layer returned.
         */
 
         *    whatever the bottom layer returned.
         */
 
+       *ap->a_vpp = NULLVP;
+
        /* case 1. */
        if ((uerror != 0) && (lerror != 0)) {
        /* case 1. */
        if ((uerror != 0) && (lerror != 0)) {
-               *ap->a_vpp = NULLVP;
                return (uerror);
        }
 
                return (uerror);
        }
 
@@ -370,7 +370,7 @@ union_open(ap)
                         * be a loopback mount of some other filesystem...
                         * so open the file with exclusive create and barf if
                         * it already exists.
                         * 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
+                        * XXX - perhaps should re-lookup the node (once more
                         * with feeling) and simply open that.  Who knows.
                         */
                        error = union_vn_create(&vp, un, p);
                         * with feeling) and simply open that.  Who knows.
                         */
                        error = union_vn_create(&vp, un, p);
@@ -402,10 +402,10 @@ union_open(ap)
                                        VOP_UNLOCK(tvp);
                                }
                                VOP_UNLOCK(un->un_uppervp);
                                        VOP_UNLOCK(tvp);
                                }
                                VOP_UNLOCK(un->un_uppervp);
-                               (void) VOP_CLOSE(un->un_uppervp, FWRITE);
+                               union_vn_close(un->un_uppervp, FWRITE);
                                VOP_LOCK(un->un_uppervp);
                                if (!error)
                                VOP_LOCK(un->un_uppervp);
                                if (!error)
-                                       uprintf("union: copied up\n",
+                                       uprintf("union: copied up %s\n",
                                                                un->un_path);
                        }
 
                                                                un->un_path);
                        }
 
@@ -417,18 +417,18 @@ union_open(ap)
                         * the right thing with (cred) and (FREAD) though.
                         * Ignoring error returns is not righ, either.
                         */
                         * the right thing with (cred) and (FREAD) though.
                         * Ignoring error returns is not righ, either.
                         */
-                       for (i = 0; i < un->un_open; i++) {
+                       for (i = 0; i < un->un_openl; i++) {
                                (void) VOP_CLOSE(tvp, FREAD);
                                (void) VOP_OPEN(un->un_uppervp, FREAD, cred, p);
                        }
                                (void) VOP_CLOSE(tvp, FREAD);
                                (void) VOP_OPEN(un->un_uppervp, FREAD, cred, p);
                        }
-                       un->un_open = 0;
+                       un->un_openl = 0;
 
                        if (error == 0)
                                error = VOP_OPEN(un->un_uppervp, mode, cred, p);
                        VOP_UNLOCK(un->un_uppervp);
                        return (error);
                }
 
                        if (error == 0)
                                error = VOP_OPEN(un->un_uppervp, mode, cred, p);
                        VOP_UNLOCK(un->un_uppervp);
                        return (error);
                }
-               un->un_open++;
+               un->un_openl++;
        }
 
        VOP_LOCK(tvp);
        }
 
        VOP_LOCK(tvp);
@@ -453,14 +453,14 @@ union_close(ap)
        if (un->un_uppervp) {
                vp = un->un_uppervp;
        } else {
        if (un->un_uppervp) {
                vp = un->un_uppervp;
        } else {
-#ifdef DIAGNOSTIC
-               if (un->un_open <= 0)
-                       panic("union: un_open cnt");
+#ifdef UNION_DIAGNOSTIC
+               if (un->un_openl <= 0)
+                       panic("union: un_openl cnt");
 #endif
 #endif
-               --un->un_open;
+               --un->un_openl;
                vp = un->un_lowervp;
        }
                vp = un->un_lowervp;
        }
-       
+
        return (VOP_CLOSE(vp, ap->a_fflag, ap->a_cred, ap->a_p));
 }
 
        return (VOP_CLOSE(vp, ap->a_fflag, ap->a_cred, ap->a_p));
 }
 
@@ -698,6 +698,12 @@ union_remove(ap)
                vput(ap->a_vp);
 
                error = VOP_REMOVE(dvp, vp, ap->a_cnp);
                vput(ap->a_vp);
 
                error = VOP_REMOVE(dvp, vp, ap->a_cnp);
+               if (!error)
+                       union_removed_upper(un);
+
+               /*
+                * XXX: should create a whiteout here
+                */
        } else {
                /*
                 * XXX: should create a whiteout here
        } else {
                /*
                 * XXX: should create a whiteout here
@@ -891,6 +897,12 @@ union_rmdir(ap)
                vput(ap->a_vp);
 
                error = VOP_REMOVE(dvp, vp, ap->a_cnp);
                vput(ap->a_vp);
 
                error = VOP_REMOVE(dvp, vp, ap->a_cnp);
+               if (!error)
+                       union_removed_upper(un);
+
+               /*
+                * XXX: should create a whiteout here
+                */
        } else {
                /*
                 * XXX: should create a whiteout here
        } else {
                /*
                 * XXX: should create a whiteout here
@@ -1023,7 +1035,7 @@ union_inactive(ap)
         * That's too much work for now.
         */
 
         * That's too much work for now.
         */
 
-#ifdef DIAGNOSTIC
+#ifdef UNION_DIAGNOSTIC
        struct union_node *un = VTOUNION(ap->a_vp);
 
        if (un->un_flags & UN_LOCKED)
        struct union_node *un = VTOUNION(ap->a_vp);
 
        if (un->un_flags & UN_LOCKED)