changeset 11712:3b88ce606c90

6615402 recursive mutex enter on the hash lock in arc_evict_ghost
author William Gorrell <william.gorrell@sun.com>
date Fri, 19 Feb 2010 10:41:19 -0700
parents d0efae043e26
children 03615b084875
files usr/src/uts/common/fs/zfs/arc.c
diffstat 1 files changed, 7 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fs/zfs/arc.c	Fri Feb 19 08:06:02 2010 -0800
+++ b/usr/src/uts/common/fs/zfs/arc.c	Fri Feb 19 10:41:19 2010 -0700
@@ -1722,6 +1722,7 @@
 	kmutex_t *hash_lock;
 	uint64_t bytes_deleted = 0;
 	uint64_t bufs_skipped = 0;
+	boolean_t have_lock;
 
 	ASSERT(GHOST_STATE(state));
 top:
@@ -1731,7 +1732,8 @@
 		if (spa && ab->b_spa != spa)
 			continue;
 		hash_lock = HDR_LOCK(ab);
-		if (mutex_tryenter(hash_lock)) {
+		have_lock = MUTEX_HELD(hash_lock);
+		if (have_lock || mutex_tryenter(hash_lock)) {
 			ASSERT(!HDR_IO_IN_PROGRESS(ab));
 			ASSERT(ab->b_buf == NULL);
 			ARCSTAT_BUMP(arcstat_deleted);
@@ -1743,10 +1745,12 @@
 				 * don't destroy the header.
 				 */
 				arc_change_state(arc_l2c_only, ab, hash_lock);
-				mutex_exit(hash_lock);
+				if (!have_lock)
+					mutex_exit(hash_lock);
 			} else {
 				arc_change_state(arc_anon, ab, hash_lock);
-				mutex_exit(hash_lock);
+				if (!have_lock)
+					mutex_exit(hash_lock);
 				arc_hdr_destroy(ab);
 			}