rx mutex inversion fix
authorDerrick Brashear <shadow@dementia.org>
Tue, 2 Nov 2010 18:47:35 +0000 (14:47 -0400)
committerJeffrey Altman <jaltman@openafs.org>
Wed, 3 Nov 2010 03:23:42 +0000 (20:23 -0700)
as discovered by Benjamin Kaduk, we were usually holding rx_refcnt_mutex
but briefly, and here we held it longer, and thus around acquiring freepktQ
mutex. undo it by simply setting STATE_RESET sooner as newcall does.

Change-Id: I3ae6fce1832d79c7cf17e93831cf8f30aebeb82b
Reviewed-on: http://gerrit.openafs.org/3219
Tested-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>

src/rx/rx.c

index 8f9438d..5a189a2 100644 (file)
@@ -2474,9 +2474,18 @@ rxi_FreeCall(struct rx_call *call, int haveCTLock)
 
     if (call->state == RX_STATE_DALLY || call->state == RX_STATE_HOLD)
        (*call->callNumber)++;
+    /*
+     * We are setting the state to RX_STATE_RESET to
+     * ensure that no one else will attempt to use this
+     * call once we drop the refcnt lock. We must drop
+     * the refcnt lock before calling rxi_ResetCall
+     * because it cannot be held across acquiring the
+     * freepktQ lock. NewCall does the same.
+     */
+    call->state = RX_STATE_RESET;
+    MUTEX_EXIT(&rx_refcnt_mutex);
     rxi_ResetCall(call, 0);
     call->conn->call[channel] = (struct rx_call *)0;
-    MUTEX_EXIT(&rx_refcnt_mutex);
 
     MUTEX_ENTER(&rx_freeCallQueue_lock);
     SET_CALL_QUEUE_LOCK(call, &rx_freeCallQueue_lock);