6929496 deadlock with mdeg_notify_clients and mdeg_unregister hit with DEBUG, causes login hang
authorHaik Aftandilian <Haik.Aftandilian@Sun.COM>
Fri, 26 Mar 2010 14:31:08 -0700
changeset 12014 abaacd7b1365
parent 12013 a41a3263e845
child 12015 63716a810520
6929496 deadlock with mdeg_notify_clients and mdeg_unregister hit with DEBUG, causes login hang
usr/src/uts/sun4v/io/mdeg.c
--- a/usr/src/uts/sun4v/io/mdeg.c	Fri Mar 26 14:31:07 2010 -0700
+++ b/usr/src/uts/sun4v/io/mdeg.c	Fri Mar 26 14:31:08 2010 -0700
@@ -553,6 +553,10 @@
 		    (void *)clnt, TQ_SLEEP);
 	}
 
+	/*
+	 * Wait for all mdeg_notify_client notifications to
+	 * finish while we are still holding mdeg.rwlock.
+	 */
 	taskq_wait(mdeg.taskq);
 
 done:
@@ -569,7 +573,21 @@
 	mde_cookie_t		md_prev_start;
 	mde_cookie_t		md_curr_start;
 
-	rw_enter(&mdeg.rwlock, RW_READER);
+	/*
+	 * mdeg.rwlock must be held as a reader while this function
+	 * executes. However, we do not need to acquire the lock as a
+	 * reader here because it is held as a reader by the thread
+	 * executing mdeg_notify_clients which triggers the execution
+	 * of this function from a taskq. Since mdeg_notify_clients
+	 * holds the lock as a reader until the taskq callbacks have
+	 * completed, it will be held for the life of this function call.
+	 * Furthermore, we must not attempt to acquire the lock as a
+	 * reader with rw_enter because if there is a pending writer,
+	 * we will block, creating a circular deadlock with this function,
+	 * the writer, and mdeg_notify_clients. Since we do not need
+	 * to acquire the lock, just assert that it is held.
+	 */
+	ASSERT(RW_READ_HELD(&mdeg.rwlock));
 
 	if (!mdeg.enabled) {
 		/* trying to shutdown */
@@ -621,8 +639,6 @@
 	MDEG_DBG("MDEG client callback done\n");
 
 cleanup:
-	rw_exit(&mdeg.rwlock);
-
 	if (mdd != MD_INVAL_DIFF_COOKIE)
 		(void) md_diff_fini(mdd);
 }