rx: connection aborts send serial zero when no conn available
[openafs.git] / src / rx / rx.c
index 7043986..e84cf32 100644 (file)
@@ -660,6 +660,7 @@ rxi_rto_startTimer(struct rx_call *call, int lastPacket, int istack)
 {
     struct clock now, retryTime;
 
+    MUTEX_ASSERT(&call->lock);
     clock_GetTime(&now);
     retryTime = now;
 
@@ -690,6 +691,7 @@ rxi_rto_startTimer(struct rx_call *call, int lastPacket, int istack)
 static_inline void
 rxi_rto_cancel(struct rx_call *call)
 {
+    MUTEX_ASSERT(&call->lock);
     if (rxevent_Cancel(&call->resendEvent))
        CALL_RELE(call, RX_CALL_REFCOUNT_RESEND);
 }
@@ -775,6 +777,7 @@ rxi_PostDelayedAckEvent(struct rx_call *call, struct clock *offset)
 {
     struct clock now, when;
 
+    MUTEX_ASSERT(&call->lock);
     clock_GetTime(&now);
     when = now;
     clock_Add(&when, offset);
@@ -799,6 +802,7 @@ rxi_PostDelayedAckEvent(struct rx_call *call, struct clock *offset)
 void
 rxi_CancelDelayedAckEvent(struct rx_call *call)
 {
+    MUTEX_ASSERT(&call->lock);
     /* Only drop the ref if we cancelled it before it could run. */
     if (rxevent_Cancel(&call->delayedAckEvent))
        CALL_RELE(call, RX_CALL_REFCOUNT_DELAY);
@@ -1244,6 +1248,7 @@ rxi_DestroyConnectionNoLock(struct rx_connection *conn)
     if ((conn->type == RX_CLIENT_CONNECTION)
        && (conn->flags & (RX_CONN_MAKECALL_WAITING|RX_CONN_MAKECALL_ACTIVE))) {
        conn->flags |= RX_CONN_DESTROY_ME;
+       MUTEX_EXIT(&rx_refcnt_mutex);
        MUTEX_EXIT(&conn->conn_data_lock);
        USERPRI;
        return;
@@ -2503,9 +2508,7 @@ rx_Finalize(void)
            for (conn = *conn_ptr; conn; conn = next) {
                next = conn->next;
                if (conn->type == RX_CLIENT_CONNECTION) {
-                    MUTEX_ENTER(&rx_refcnt_mutex);
-                   conn->refCount++;
-                    MUTEX_EXIT(&rx_refcnt_mutex);
+                    rx_GetConnection(conn);
 #ifdef RX_ENABLE_LOCKS
                    rxi_DestroyConnectionNoLock(conn);
 #else /* RX_ENABLE_LOCKS */
@@ -2760,9 +2763,7 @@ rxi_FreeCall(struct rx_call *call, int haveCTLock)
      */
     MUTEX_ENTER(&conn->conn_data_lock);
     if (conn->flags & RX_CONN_DESTROY_ME && !(conn->flags & RX_CONN_MAKECALL_WAITING)) {
-        MUTEX_ENTER(&rx_refcnt_mutex);
-       conn->refCount++;
-        MUTEX_EXIT(&rx_refcnt_mutex);
+        rx_GetConnection(conn);
        MUTEX_EXIT(&conn->conn_data_lock);
 #ifdef RX_ENABLE_LOCKS
        if (haveCTLock)
@@ -3148,9 +3149,7 @@ rxi_FindConnection(osi_socket socket, afs_uint32 host,
             rx_atomic_inc(&rx_stats.nServerConns);
     }
 
-    MUTEX_ENTER(&rx_refcnt_mutex);
-    conn->refCount++;
-    MUTEX_EXIT(&rx_refcnt_mutex);
+    rx_GetConnection(conn);
 
     rxLastConn = conn;         /* store this connection as the last conn used */
     MUTEX_EXIT(&rx_connHashTable_lock);
@@ -3166,10 +3165,15 @@ static_inline int
 rxi_AbortIfServerBusy(osi_socket socket, struct rx_connection *conn,
                      struct rx_packet *np)
 {
+    afs_uint32 serial;
+
     if ((rx_BusyThreshold > 0) &&
        (rx_atomic_read(&rx_nWaiting) > rx_BusyThreshold)) {
+       MUTEX_ENTER(&conn->conn_data_lock);
+       serial = ++conn->serial;
+       MUTEX_EXIT(&conn->conn_data_lock);
        rxi_SendRawAbort(socket, conn->peer->host, conn->peer->port,
-                        rx_BusyError, np, 0);
+                        serial, rx_BusyError, np, 0);
        if (rx_stats_active)
            rx_atomic_inc(&rx_stats.nBusies);
        return 1;
@@ -3421,7 +3425,7 @@ rxi_ReceivePacket(struct rx_packet *np, osi_socket socket,
        don't abort an abort. */
     if (!conn) {
         if (unknownService && (np->header.type != RX_PACKET_TYPE_ABORT))
-            rxi_SendRawAbort(socket, host, port, RX_INVALID_OPERATION,
+           rxi_SendRawAbort(socket, host, port, 0, RX_INVALID_OPERATION,
                              np, 0);
         return np;
     }
@@ -3664,6 +3668,8 @@ rxi_CheckReachEvent(struct rxevent *event, void *arg1, void *arg2, int dummy)
 
     if (event != NULL)
        MUTEX_ENTER(&conn->conn_data_lock);
+    else
+       MUTEX_ASSERT(&conn->conn_data_lock);
 
     if (event != NULL && event == conn->checkReachEvent)
        rxevent_Put(&conn->checkReachEvent);
@@ -4426,12 +4432,20 @@ rxi_ReceiveAckPacket(struct rx_call *call, struct rx_packet *np,
        rx_packetread(np, rx_AckDataSize(ap->nAcks) + (int)sizeof(afs_int32),
                      (int)sizeof(afs_int32), &tSize);
        tSize = (afs_uint32) ntohl(tSize);
+       if (tSize > RX_MAX_PACKET_SIZE)
+           tSize = RX_MAX_PACKET_SIZE;
+       if (tSize < RX_MIN_PACKET_SIZE)
+           tSize = RX_MIN_PACKET_SIZE;
        peer->natMTU = rxi_AdjustIfMTU(MIN(tSize, peer->ifMTU));
 
        /* Get the maximum packet size to send to this peer */
        rx_packetread(np, rx_AckDataSize(ap->nAcks), (int)sizeof(afs_int32),
                      &tSize);
        tSize = (afs_uint32) ntohl(tSize);
+       if (tSize > RX_MAX_PACKET_SIZE)
+           tSize = RX_MAX_PACKET_SIZE;
+       if (tSize < RX_MIN_PACKET_SIZE)
+           tSize = RX_MIN_PACKET_SIZE;
        tSize = (afs_uint32) MIN(tSize, rx_MyMaxSendSize);
        tSize = rxi_AdjustMaxMTU(peer->natMTU, tSize);
 
@@ -4453,6 +4467,10 @@ rxi_ReceiveAckPacket(struct rx_call *call, struct rx_packet *np,
                          rx_AckDataSize(ap->nAcks) + 2 * (int)sizeof(afs_int32),
                          (int)sizeof(afs_int32), &tSize);
            tSize = (afs_uint32) ntohl(tSize);  /* peer's receive window, if it's */
+           if (tSize == 0)
+               tSize = 1;
+           if (tSize >= rx_maxSendWindow)
+               tSize = rx_maxSendWindow;
            if (tSize < call->twind) {  /* smaller than our send */
                call->twind = tSize;    /* window, we must send less... */
                call->ssthresh = MIN(call->twind, call->ssthresh);
@@ -4474,6 +4492,10 @@ rxi_ReceiveAckPacket(struct rx_call *call, struct rx_packet *np,
                          rx_AckDataSize(ap->nAcks) + 2 * (int)sizeof(afs_int32),
                          sizeof(afs_int32), &tSize);
            tSize = (afs_uint32) ntohl(tSize);
+           if (tSize == 0)
+               tSize = 1;
+           if (tSize >= rx_maxSendWindow)
+               tSize = rx_maxSendWindow;
            /*
             * As of AFS 3.5 we set the send window to match the receive window.
             */
@@ -4675,6 +4697,8 @@ static void
 rxi_SendConnectionAbortLater(struct rx_connection *conn, int msec)
 {
     struct clock when, now;
+
+    MUTEX_ASSERT(&conn->conn_data_lock);
     if (!conn->error) {
        return;
     }
@@ -5067,7 +5091,14 @@ rxi_SendCallAbort(struct rx_call *call, struct rx_packet *packet,
     if (rx_IsClientConn(call->conn))
        force = 1;
 
-    if (call->abortCode != call->error) {
+    /*
+     * An opcode that has been deprecated or has yet to be implemented is not
+     * a misbehavior of the client.  Do not punish the client by introducing
+     * delays.
+     */
+    if (call->error == RXGEN_OPCODE) {
+       force = 1;
+    } else if (call->abortCode != call->error) {
        call->abortCode = call->error;
        call->abortCount = 0;
     }
@@ -5076,7 +5107,8 @@ rxi_SendCallAbort(struct rx_call *call, struct rx_packet *packet,
        || call->abortCount < rxi_callAbortThreshhold) {
        rxi_CancelDelayedAbortEvent(call);
        error = htonl(call->error);
-       call->abortCount++;
+       if (!force)
+           call->abortCount++;
        packet =
            rxi_SendSpecial(call, call->conn, packet, RX_PACKET_TYPE_ABORT,
                            (char *)&error, sizeof(error), istack);
@@ -5094,6 +5126,7 @@ rxi_SendCallAbort(struct rx_call *call, struct rx_packet *packet,
 static void
 rxi_CancelDelayedAbortEvent(struct rx_call *call)
 {
+    MUTEX_ASSERT(&call->lock);
     if (rxevent_Cancel(&call->delayedAbortEvent))
        CALL_RELE(call, RX_CALL_REFCOUNT_ABORT);
 }
@@ -6410,6 +6443,7 @@ rxi_NatKeepAliveEvent(struct rxevent *event, void *arg1,
 static void
 rxi_ScheduleNatKeepAliveEvent(struct rx_connection *conn)
 {
+    MUTEX_ASSERT(&conn->conn_data_lock);
     if (!conn->natKeepAliveEvent && conn->secondsUntilNatPing) {
        struct clock when, now;
        clock_GetTime(&now);
@@ -6458,6 +6492,7 @@ rxi_KeepAliveEvent(struct rxevent *event, void *arg1, void *dummy,
 
     if (rxi_CheckCall(call, 0)) {
        MUTEX_EXIT(&call->lock);
+       CALL_RELE(call, RX_CALL_REFCOUNT_ALIVE);
        return;
     }
 
@@ -6518,6 +6553,7 @@ out:
 static void
 rxi_ScheduleKeepAliveEvent(struct rx_call *call)
 {
+    MUTEX_ASSERT(&call->lock);
     if (!call->keepAliveEvent) {
        struct clock when, now;
        clock_GetTime(&now);
@@ -6531,6 +6567,7 @@ rxi_ScheduleKeepAliveEvent(struct rx_call *call)
 
 static void
 rxi_CancelKeepAliveEvent(struct rx_call *call) {
+    MUTEX_ASSERT(&call->lock);
     if (rxevent_Cancel(&call->keepAliveEvent))
        CALL_RELE(call, RX_CALL_REFCOUNT_ALIVE);
 }
@@ -6538,6 +6575,7 @@ rxi_CancelKeepAliveEvent(struct rx_call *call) {
 static void
 rxi_ScheduleGrowMTUEvent(struct rx_call *call, int secs)
 {
+    MUTEX_ASSERT(&call->lock);
     if (!call->growMTUEvent) {
        struct clock when, now;
 
@@ -6561,6 +6599,7 @@ rxi_ScheduleGrowMTUEvent(struct rx_call *call, int secs)
 static void
 rxi_CancelGrowMTUEvent(struct rx_call *call)
 {
+    MUTEX_ASSERT(&call->lock);
     if (rxevent_Cancel(&call->growMTUEvent))
        CALL_RELE(call, RX_CALL_REFCOUNT_MTU);
 }