diff options
author | Haik Aftandilian <Haik.Aftandilian@Sun.COM> | 2010-03-26 14:31:08 -0700 |
---|---|---|
committer | Haik Aftandilian <Haik.Aftandilian@Sun.COM> | 2010-03-26 14:31:08 -0700 |
commit | 273a517f474549f42a8e8b9af219c177c300c49e (patch) | |
tree | 53808cf5ad7134956547d85cbf67678e8bc2eac8 /usr/src | |
parent | 183ef8a1713ca188e24d970f22c6f9cc333007fd (diff) | |
download | illumos-joyent-273a517f474549f42a8e8b9af219c177c300c49e.tar.gz |
6929496 deadlock with mdeg_notify_clients and mdeg_unregister hit with DEBUG, causes login hang
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/sun4v/io/mdeg.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/usr/src/uts/sun4v/io/mdeg.c b/usr/src/uts/sun4v/io/mdeg.c index 93c3545939..18441c2e3c 100644 --- a/usr/src/uts/sun4v/io/mdeg.c +++ b/usr/src/uts/sun4v/io/mdeg.c @@ -553,6 +553,10 @@ mdeg_notify_clients(void) (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 @@ mdeg_notify_client(void *arg) 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_notify_client(void *arg) MDEG_DBG("MDEG client callback done\n"); cleanup: - rw_exit(&mdeg.rwlock); - if (mdd != MD_INVAL_DIFF_COOKIE) (void) md_diff_fini(mdd); } |