Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/fs/union Make union_newlower() ans union_newupper() loca...



details:   https://anonhg.NetBSD.org/src/rev/b97c73cbc9ea
branches:  trunk
changeset: 825481:b97c73cbc9ea
user:      hannken <hannken%NetBSD.org@localhost>
date:      Mon Jul 17 09:22:36 2017 +0000

description:
Make union_newlower() ans union_newupper() local to union_subr.c,
expand and remove union_updatevp() and take care to transfer the
vnode lock from the union vnode to its new upper vnode without
breaking the fstrans state.

Add assertions that un_lowervp and un_uppervp never change from
non-NULL to non-NULL.

diffstat:

 sys/fs/union/union.h      |    4 +-
 sys/fs/union/union_subr.c |  136 ++++++++++++++++++++++-----------------------
 2 files changed, 68 insertions(+), 72 deletions(-)

diffs (214 lines):

diff -r 974d95b3dd58 -r b97c73cbc9ea sys/fs/union/union.h
--- a/sys/fs/union/union.h      Sun Jul 16 21:40:28 2017 +0000
+++ b/sys/fs/union/union.h      Mon Jul 17 09:22:36 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: union.h,v 1.28 2015/02/16 10:22:00 hannken Exp $       */
+/*     $NetBSD: union.h,v 1.29 2017/07/17 09:22:36 hannken Exp $       */
 
 /*
  * Copyright (c) 1994 The Regents of the University of California.
@@ -158,8 +158,6 @@
     struct lwp *);
 extern void union_removed_upper(struct union_node *un);
 extern struct vnode *union_lowervp(struct vnode *);
-extern void union_newlower(struct union_node *, struct vnode *);
-extern void union_newupper(struct union_node *, struct vnode *);
 extern void union_newsize(struct vnode *, off_t, off_t);
 int union_readdirhook(struct vnode **, struct file *, struct lwp *);
 
diff -r 974d95b3dd58 -r b97c73cbc9ea sys/fs/union/union_subr.c
--- a/sys/fs/union/union_subr.c Sun Jul 16 21:40:28 2017 +0000
+++ b/sys/fs/union/union_subr.c Mon Jul 17 09:22:36 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: union_subr.c,v 1.75 2017/06/01 02:45:13 chs Exp $      */
+/*     $NetBSD: union_subr.c,v 1.76 2017/07/17 09:22:36 hannken Exp $  */
 
 /*
  * Copyright (c) 1994
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.75 2017/06/01 02:45:13 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.76 2017/07/17 09:22:36 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -104,7 +104,8 @@
 
 static kmutex_t uhash_lock;
 
-void union_updatevp(struct union_node *, struct vnode *, struct vnode *);
+static void union_newupper(struct union_node *, struct vnode *);
+static void union_newlower(struct union_node *, struct vnode *);
 static void union_ref(struct union_node *);
 static void union_rele(struct union_node *);
 static int union_do_lookup(struct vnode *, struct componentname *, kauth_cred_t,    const char *);
@@ -160,71 +161,28 @@
 }
 
 void
-union_updatevp(struct union_node *un, struct vnode *uppervp,
-       struct vnode *lowervp)
+union_newlower(struct union_node *un, struct vnode *lowervp)
 {
        int ohash = UNION_HASH(un->un_uppervp, un->un_lowervp);
-       int nhash = UNION_HASH(uppervp, lowervp);
-       int docache = (lowervp != NULLVP || uppervp != NULLVP);
-       bool un_unlock;
+       int nhash = UNION_HASH(un->un_uppervp, lowervp);
+
+       if (un->un_lowervp == lowervp)
+               return;
 
        KASSERT(VOP_ISLOCKED(UNIONTOV(un)) == LK_EXCLUSIVE);
+       KASSERT(un->un_lowervp == NULL);
 
        mutex_enter(&uhash_lock);
 
-       if (!docache || ohash != nhash) {
-               if (un->un_cflags & UN_CACHED) {
-                       un->un_cflags &= ~UN_CACHED;
-                       LIST_REMOVE(un, un_cache);
-               }
-       }
-
-       if (un->un_lowervp != lowervp) {
-               if (un->un_lowervp) {
-                       vrele(un->un_lowervp);
-                       if (un->un_path) {
-                               free(un->un_path, M_TEMP);
-                               un->un_path = 0;
-                       }
-                       if (un->un_dirvp) {
-                               vrele(un->un_dirvp);
-                               un->un_dirvp = NULLVP;
-                       }
-               }
-               un->un_lowervp = lowervp;
-               mutex_enter(&un->un_lock);
-               un->un_lowersz = VNOVAL;
-               mutex_exit(&un->un_lock);
+       if (ohash != nhash && (un->un_cflags & UN_CACHED)) {
+               un->un_cflags &= ~UN_CACHED;
+               LIST_REMOVE(un, un_cache);
        }
-
-       if (un->un_uppervp != uppervp) {
-               if (un->un_uppervp) {
-                       un_unlock = false;
-                       vrele(un->un_uppervp);
-               } else
-                       un_unlock = true;
-
-               mutex_enter(&un->un_lock);
-               un->un_uppervp = uppervp;
-               mutex_exit(&un->un_lock);
-               if (un_unlock) {
-                       struct vop_unlock_args ap;
-
-                       ap.a_vp = UNIONTOV(un);
-                       genfs_unlock(&ap);
-               }
-               mutex_enter(&un->un_lock);
-               un->un_uppersz = VNOVAL;
-               mutex_exit(&un->un_lock);
-               /* Update union vnode interlock. */
-               if (uppervp != NULL) {
-                       mutex_obj_hold(uppervp->v_interlock);
-                       uvm_obj_setlock(&UNIONTOV(un)->v_uobj,
-                           uppervp->v_interlock);
-               }
-       }
-
-       if (docache && (ohash != nhash)) {
+       mutex_enter(&un->un_lock);
+       un->un_lowervp = lowervp;
+       un->un_lowersz = VNOVAL;
+       mutex_exit(&un->un_lock);
+       if (ohash != nhash) {
                LIST_INSERT_HEAD(&uhashtbl[nhash], un, un_cache);
                un->un_cflags |= UN_CACHED;
        }
@@ -233,17 +191,57 @@
 }
 
 void
-union_newlower(struct union_node *un, struct vnode *lowervp)
-{
-
-       union_updatevp(un, un->un_uppervp, lowervp);
-}
-
-void
 union_newupper(struct union_node *un, struct vnode *uppervp)
 {
+       int ohash = UNION_HASH(un->un_uppervp, un->un_lowervp);
+       int nhash = UNION_HASH(uppervp, un->un_lowervp);
+       struct vop_lock_args lock_ap;
+       struct vop_unlock_args unlock_ap;
+       int error __diagused;
 
-       union_updatevp(un, uppervp, un->un_lowervp);
+       if (un->un_uppervp == uppervp)
+               return;
+
+       KASSERT(VOP_ISLOCKED(UNIONTOV(un)) == LK_EXCLUSIVE);
+       KASSERT(un->un_uppervp == NULL);
+
+       /*
+        * We have to transfer the vnode lock from the union vnode to
+        * the upper vnode.  Lock the upper vnode first.  We cannot use
+        * VOP_LOCK() here as it would break the fstrans state.
+        */
+       lock_ap.a_desc = VDESC(vop_lock);
+       lock_ap.a_vp = uppervp;
+       lock_ap.a_flags = LK_EXCLUSIVE;
+       error = VCALL(lock_ap.a_vp,  VOFFSET(vop_lock), &lock_ap);
+       KASSERT(error == 0);
+
+       mutex_enter(&uhash_lock);
+
+       if (ohash != nhash && (un->un_cflags & UN_CACHED)) {
+               un->un_cflags &= ~UN_CACHED;
+               LIST_REMOVE(un, un_cache);
+       }
+       mutex_enter(&un->un_lock);
+       un->un_uppervp = uppervp;
+       un->un_uppersz = VNOVAL;
+       /*
+        * With the upper vnode in place unlock the union vnode to
+        * finalize the lock transfer.
+        */
+       unlock_ap.a_desc = VDESC(vop_unlock);
+       unlock_ap.a_vp = UNIONTOV(un);
+       genfs_unlock(&unlock_ap);
+       /* Update union vnode interlock. */
+       mutex_obj_hold(uppervp->v_interlock);
+       uvm_obj_setlock(&UNIONTOV(un)->v_uobj, uppervp->v_interlock);
+       mutex_exit(&un->un_lock);
+       if (ohash != nhash) {
+               LIST_INSERT_HEAD(&uhashtbl[nhash], un, un_cache);
+               un->un_cflags |= UN_CACHED;
+       }
+
+       mutex_exit(&uhash_lock);
 }
 
 /*
@@ -694,7 +692,6 @@
        if (error)
                return (error);
 
-       KASSERT(VOP_ISLOCKED(uvp) == LK_EXCLUSIVE);
        union_newupper(un, uvp);
 
        lvp = un->un_lowervp;
@@ -934,6 +931,7 @@
        }
 
        vp->v_writecount++;
+       VOP_UNLOCK(vp);
        *vpp = vp;
        return 0;
 }



Home | Main Index | Thread Index | Old Index