Module Name:    src
Committed By:   hannken
Date:           Sat Aug 13 10:48:14 UTC 2011

Modified Files:
        src/sys/fs/union: union_subr.c

Log Message:
Use mutexes to protect the hash lists instead of tsleep/wakeup.


To generate a diff of this commit:
cvs rdiff -u -r1.48 -r1.49 src/sys/fs/union/union_subr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/union/union_subr.c
diff -u src/sys/fs/union/union_subr.c:1.48 src/sys/fs/union/union_subr.c:1.49
--- src/sys/fs/union/union_subr.c:1.48	Fri Aug 12 17:41:17 2011
+++ src/sys/fs/union/union_subr.c	Sat Aug 13 10:48:14 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: union_subr.c,v 1.48 2011/08/12 17:41:17 hannken Exp $	*/
+/*	$NetBSD: union_subr.c,v 1.49 2011/08/13 10:48:14 hannken Exp $	*/
 
 /*
  * Copyright (c) 1994
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.48 2011/08/12 17:41:17 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.49 2011/08/13 10:48:14 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -103,10 +103,8 @@
 	(((((unsigned long) (u)) + ((unsigned long) l)) >> 8) & (NHASH-1))
 
 static LIST_HEAD(unhead, union_node) unhead[NHASH];
-static int unvplock[NHASH];
+static kmutex_t unheadlock[NHASH];
 
-static int union_list_lock(int);
-static void union_list_unlock(int);
 void union_updatevp(struct union_node *, struct vnode *, struct vnode *);
 static int union_relookup(struct union_mount *, struct vnode *,
 			       struct vnode **, struct componentname *,
@@ -121,9 +119,10 @@
 {
 	int i;
 
-	for (i = 0; i < NHASH; i++)
+	for (i = 0; i < NHASH; i++) {
 		LIST_INIT(&unhead[i]);
-	memset(unvplock, 0, sizeof(unvplock));
+		mutex_init(&unheadlock[i], MUTEX_DEFAULT, IPL_NONE);
+	}
 }
 
 /*
@@ -132,38 +131,15 @@
 void
 union_done(void)
 {
+	int i;
+
+	for (i = 0; i < NHASH; i++)
+		mutex_destroy(&unheadlock[i]);
 
 	/* Make sure to unset the readdir hook. */
 	vn_union_readdir_hook = NULL;
 }
 
-static int
-union_list_lock(int ix)
-{
-
-	if (unvplock[ix] & UN_LOCKED) {
-		unvplock[ix] |= UN_WANTED;
-		(void) tsleep(&unvplock[ix], PINOD, "unionlk", 0);
-		return (1);
-	}
-
-	unvplock[ix] |= UN_LOCKED;
-
-	return (0);
-}
-
-static void
-union_list_unlock(int ix)
-{
-
-	unvplock[ix] &= ~UN_LOCKED;
-
-	if (unvplock[ix] & UN_WANTED) {
-		unvplock[ix] &= ~UN_WANTED;
-		wakeup(&unvplock[ix]);
-	}
-}
-
 void
 union_updatevp(struct union_node *un, struct vnode *uppervp,
 	struct vnode *lowervp)
@@ -186,11 +162,9 @@
 	}
 
 	if (lhash != uhash)
-		while (union_list_lock(lhash))
-			continue;
+		mutex_enter(&unheadlock[lhash]);
 
-	while (union_list_lock(uhash))
-		continue;
+	mutex_enter(&unheadlock[uhash]);
 
 	if (ohash != nhash || !docache) {
 		if (un->un_flags & UN_CACHED) {
@@ -200,7 +174,7 @@
 	}
 
 	if (ohash != nhash)
-		union_list_unlock(ohash);
+		mutex_exit(&unheadlock[ohash]);
 
 	if (un->un_lowervp != lowervp) {
 		if (un->un_lowervp) {
@@ -237,7 +211,7 @@
 		un->un_flags |= UN_CACHED;
 	}
 
-	union_list_unlock(nhash);
+	mutex_exit(&unheadlock[nhash]);
 }
 
 void
@@ -394,8 +368,7 @@
 			break;
 		}
 
-		while (union_list_lock(hash))
-			continue;
+		mutex_enter(&unheadlock[hash]);
 
 		for (un = unhead[hash].lh_first; un != 0;
 					un = un->un_cache.le_next) {
@@ -407,14 +380,14 @@
 				vp = UNIONTOV(un);
 				mutex_enter(vp->v_interlock);
 				if (vget(vp, 0)) {
-					union_list_unlock(hash);
+					mutex_exit(&unheadlock[hash]);
 					goto loop;
 				}
 				break;
 			}
 		}
 
-		union_list_unlock(hash);
+		mutex_exit(&unheadlock[hash]);
 
 		if (un)
 			break;
@@ -528,8 +501,7 @@
 	}
 
 	if (docache) {
-		while (union_list_lock(hash))
-			continue;
+		mutex_enter(&unheadlock[hash]);
 		LIST_FOREACH(un1, &unhead[hash], un_cache) {
 			if (un1->un_lowervp == lowervp &&
 			    un1->un_uppervp == uppervp &&
@@ -538,7 +510,7 @@
 				 * Another thread beat us, push back freshly
 				 * allocated vnode and retry.
 				 */
-				union_list_unlock(hash);
+				mutex_exit(&unheadlock[hash]);
 				ungetnewvnode(*vpp);
 				goto loop;
 			}
@@ -603,7 +575,7 @@
 
 out:
 	if (docache)
-		union_list_unlock(hash);
+		mutex_exit(&unheadlock[hash]);
 
 	return (error);
 }
@@ -616,13 +588,12 @@
 
 	hash = UNION_HASH(un->un_uppervp, un->un_lowervp);
 
-	while (union_list_lock(hash))
-		continue;
+	mutex_enter(&unheadlock[hash]);
 	if (un->un_flags & UN_CACHED) {
 		un->un_flags &= ~UN_CACHED;
 		LIST_REMOVE(un, un_cache);
 	}
-	union_list_unlock(hash);
+	mutex_exit(&unheadlock[hash]);
 
 	if (un->un_pvp != NULLVP)
 		vrele(un->un_pvp);
@@ -1060,13 +1031,12 @@
 
 	hash = UNION_HASH(un->un_uppervp, un->un_lowervp);
 
-	while (union_list_lock(hash))
-		continue;
+	mutex_enter(&unheadlock[hash]);
 	if (un->un_flags & UN_CACHED) {
 		un->un_flags &= ~UN_CACHED;
 		LIST_REMOVE(un, un_cache);
 	}
-	union_list_unlock(hash);
+	mutex_exit(&unheadlock[hash]);
 
 	if (un->un_flags & UN_ULOCK) {
 		un->un_flags &= ~UN_ULOCK;

Reply via email to