rx: conn->callNumber protected by conn_call_lock
authorJeffrey Altman <jaltman@your-file-system.com>
Sun, 29 Jan 2012 18:52:17 +0000 (13:52 -0500)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Tue, 3 Apr 2012 13:21:33 +0000 (06:21 -0700)
The conn->callNumber array should be protected by the conn_call_lock
since the conn_call_lock is what protects the binding of calls to
connection channels.

Change-Id: I9f9b4e8f90d1e4ebbc4429af286358807784d84f
Reviewed-on: http://gerrit.openafs.org/6629
Tested-by: Jeffrey Altman <jaltman@secure-endpoints.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Alistair Ferguson <alistair.ferguson@mac.com>
Reviewed-by: Jeffrey Altman <jaltman@secure-endpoints.com>

src/rx/rx.c

index f4037af..a832c21 100644 (file)
@@ -1495,10 +1495,11 @@ rx_NewCall(struct rx_connection *conn)
                          * effect on overall system performance.
                          */
                         call->state = RX_STATE_RESET;
+                        CALL_HOLD(call, RX_CALL_REFCOUNT_BEGIN);
+                        (*call->callNumber)++;
                         MUTEX_EXIT(&conn->conn_call_lock);
                         CALL_HOLD(call, RX_CALL_REFCOUNT_BEGIN);
                         rxi_ResetCall(call, 0);
-                        (*call->callNumber)++;
                         if (MUTEX_TRYENTER(&conn->conn_call_lock))
                             break;
 
@@ -1661,12 +1662,14 @@ rxi_GetCallNumberVector(struct rx_connection *aconn,
     SPLVAR;
 
     NETPRI;
+    MUTEX_ENTER(&aconn->conn_call_lock);
     for (i = 0; i < RX_MAXCALLS; i++) {
        if ((tcall = aconn->call[i]) && (tcall->state == RX_STATE_DALLY))
            aint32s[i] = aconn->callNumber[i] + 1;
        else
            aint32s[i] = aconn->callNumber[i];
     }
+    MUTEX_EXIT(&aconn->conn_call_lock);
     USERPRI;
     return 0;
 }
@@ -1680,12 +1683,14 @@ rxi_SetCallNumberVector(struct rx_connection *aconn,
     SPLVAR;
 
     NETPRI;
+    MUTEX_ENTER(&aconn->conn_call_lock);
     for (i = 0; i < RX_MAXCALLS; i++) {
        if ((tcall = aconn->call[i]) && (tcall->state == RX_STATE_DALLY))
            aconn->callNumber[i] = aint32s[i] - 1;
        else
            aconn->callNumber[i] = aint32s[i];
     }
+    MUTEX_EXIT(&aconn->conn_call_lock);
     USERPRI;
     return 0;
 }
@@ -3041,11 +3046,12 @@ rxi_CheckBusy(struct rx_call *call)
     int channel = call->channel;
     int freechannel = 0;
     int i;
-    afs_uint32 callNumber = *call->callNumber;
+    afs_uint32 callNumber;
 
     MUTEX_EXIT(&call->lock);
 
     MUTEX_ENTER(&conn->conn_call_lock);
+    callNumber = *call->callNumber;
 
     /* Are there any other call slots on this conn that we should try? Look for
      * slots that are empty and are either non-busy, or were marked as busy
@@ -3079,8 +3085,6 @@ rxi_CheckBusy(struct rx_call *call)
        }
     }
 
-    MUTEX_EXIT(&conn->conn_call_lock);
-
     MUTEX_ENTER(&call->lock);
 
     /* Since the call->lock and conn->conn_call_lock have been released it is
@@ -3100,6 +3104,7 @@ rxi_CheckBusy(struct rx_call *call)
 
        rxi_CallError(call, RX_CALL_BUSY);
     }
+    MUTEX_EXIT(&conn->conn_call_lock);
 }
 
 /* There are two packet tracing routines available for testing and monitoring
@@ -3245,22 +3250,23 @@ rxi_ReceivePacket(struct rx_packet *np, osi_socket socket,
     }
 
     channel = np->header.cid & RX_CHANNELMASK;
+    MUTEX_ENTER(&conn->conn_call_lock);
     call = conn->call[channel];
 
     if (call) {
        MUTEX_ENTER(&call->lock);
         currentCallNumber = conn->callNumber[channel];
+        MUTEX_EXIT(&conn->conn_call_lock);
     } else if (type == RX_SERVER_CONNECTION) {  /* No call allocated */
-        MUTEX_ENTER(&conn->conn_call_lock);
         call = conn->call[channel];
         if (call) {
             MUTEX_ENTER(&call->lock);
-            MUTEX_EXIT(&conn->conn_call_lock);
             currentCallNumber = conn->callNumber[channel];
+            MUTEX_EXIT(&conn->conn_call_lock);
         } else {
             call = rxi_NewCall(conn, channel);  /* returns locked call */
-            MUTEX_EXIT(&conn->conn_call_lock);
             *call->callNumber = currentCallNumber = np->header.callNumber;
+            MUTEX_EXIT(&conn->conn_call_lock);
 #ifdef RXDEBUG
             if (np->header.callNumber == 0)
                 dpf(("RecPacket call 0 %d %s: %x.%u.%u.%u.%u.%u.%u flags %d, packet %"AFS_PTR_FMT" len %d\n",
@@ -3346,6 +3352,11 @@ rxi_ReceivePacket(struct rx_packet *np, osi_socket socket,
                return tp;
            }
            rxi_ResetCall(call, 0);
+            /*
+             * The conn_call_lock is not held but no one else should be
+             * using this call channel while we are processing this incoming
+             * packet.  This assignment should be safe.
+             */
            *call->callNumber = np->header.callNumber;
 #ifdef RXDEBUG
            if (np->header.callNumber == 0)