clones-take-two-20081120
authorJeffrey Altman <jaltman@your-file-system.com>
Thu, 20 Nov 2008 22:56:12 +0000 (22:56 +0000)
committerDerrick Brashear <shadow@dementia.org>
Thu, 20 Nov 2008 22:56:12 +0000 (22:56 +0000)
LICENSE IPL10
FIXES 89557

commit jeff's revised version of the patch

src/rx/rx.c
src/rx/rx.h
src/rx/rx_globals.c
src/rx/rx_globals.h
src/rxdebug/rxdebug.c

index 27e31c9..77ea8ca 100644 (file)
@@ -773,97 +773,103 @@ rx_StartServer(int donateMe)
  * specified security object to implement the security model for this
  * connection. */
 struct rx_connection *
-rx_NewConnection(register afs_uint32 shost, u_short sport, u_short sservice,
-                register struct rx_securityClass *securityObject,
+rx_NewConnection(afs_uint32 shost, u_short sport, u_short sservice,
+                struct rx_securityClass *securityObject,
                 int serviceSecurityIndex)
 {
     int hashindex, i;
-    afs_int32 cid, cix, nclones;
-    register struct rx_connection *conn, *tconn, *ptconn;
+    afs_int32 cix, nclones;
+    struct rx_connection *conn, *tconn, *ptconn;
 
     SPLVAR;
 
     clock_NewTime();
     dpf(("rx_NewConnection(host %x, port %u, service %u, securityObject %x, serviceSecurityIndex %d)\n", ntohl(shost), ntohs(sport), sservice, securityObject, serviceSecurityIndex));
 
-       conn = tconn = 0;
-       nclones = rx_max_clones_per_connection;
-
-    /* Vasilsi said: "NETPRI protects Cid and Alloc", but can this be true in
-     * the case of kmem_alloc? */
-
     NETPRI;
     RWLOCK_WRLOCK(&rx_connHashTable_lock);
 
-    /* send in the clones */
-    for(cix = 0; cix <= nclones; ++cix) {
-         ptconn = tconn;
-         tconn = rxi_AllocConnection();
-         tconn->type = RX_CLIENT_CONNECTION;
-         tconn->epoch = rx_epoch;
-         tconn->peer = rxi_FindPeer(shost, sport, 0, 1);
-         tconn->serviceId = sservice;
-         tconn->securityObject = securityObject;
-         tconn->securityData = (void *) 0;
-         tconn->securityIndex = serviceSecurityIndex;
-         tconn->ackRate = RX_FAST_ACK_RATE;
-         tconn->nSpecific = 0;
-         tconn->specific = NULL;
-         tconn->challengeEvent = NULL;
-         tconn->delayedAbortEvent = NULL;
-         tconn->abortCount = 0;
-         tconn->error = 0;
-         for (i = 0; i < RX_MAXCALLS; i++) {
-             tconn->twind[i] = rx_initSendWindow;
-             tconn->rwind[i] = rx_initReceiveWindow;
-         }
-         tconn->parent = 0;
-         tconn->next_clone = 0;
-         tconn->nclones = nclones;
-         rx_SetConnDeadTime(tconn, rx_connDeadTime);
-               
-         if(cix == 0) {
-               conn = tconn;
-         } else {
-               tconn->flags |= RX_CLONED_CONNECTION;
-               tconn->parent = conn;
-               ptconn->next_clone = tconn;
-         }
-
-         /* generic connection setup */
-#ifdef RX_ENABLE_LOCKS
-         MUTEX_INIT(&tconn->conn_call_lock, "conn call lock", MUTEX_DEFAULT, 0);
-         MUTEX_INIT(&tconn->conn_data_lock, "conn data lock", MUTEX_DEFAULT, 0);
-         CV_INIT(&tconn->conn_call_cv, "conn call cv", CV_DEFAULT, 0);
+    /* 
+     * allocate the connection and all of its clones.
+     * clones are flagged as such and have their 
+     * parent set to the 0th connection object.
+     */
+    for (nclones = rx_max_clones_per_connection, 
+            conn = tconn = 0, 
+            cix = 0; 
+        cix <= nclones; 
+        ++cix, ptconn = tconn) {
+       
+       tconn = rxi_AllocConnection();
+       tconn->cid = (rx_nextCid += RX_MAXCALLS);
+       tconn->type = RX_CLIENT_CONNECTION;
+       tconn->epoch = rx_epoch;
+       tconn->peer = rxi_FindPeer(shost, sport, 0, 1);
+       tconn->serviceId = sservice;
+       tconn->securityObject = securityObject;
+       tconn->securityData = (void *) 0;
+       tconn->securityIndex = serviceSecurityIndex;
+       tconn->ackRate = RX_FAST_ACK_RATE;
+       tconn->nSpecific = 0;
+       tconn->specific = NULL;
+       tconn->challengeEvent = NULL;
+       tconn->delayedAbortEvent = NULL;
+       tconn->abortCount = 0;
+       tconn->error = 0;
+       
+       for (i = 0; i < RX_MAXCALLS; i++) {
+           tconn->twind[i] = rx_initSendWindow;
+           tconn->rwind[i] = rx_initReceiveWindow;
+       }
+       
+       if (cix == 0) {
+           conn = tconn;
+           conn->nclones = nclones;
+           conn->parent = 0;
+           conn->next_clone = 0;
+           rx_SetConnDeadTime(conn, rx_connDeadTime);
+       } else {
+           tconn->nclones = 0;
+           tconn->flags |= RX_CLONED_CONNECTION;
+           tconn->parent = conn;
+           ptconn->next_clone = tconn;
+           tconn->secondsUntilDead = 0;
+           tconn->secondsUntilPing = 0;
+       }
+       /* generic connection setup */ 
+#ifdef        RX_ENABLE_LOCKS
+       MUTEX_INIT(&tconn->conn_call_lock, "conn call lock", MUTEX_DEFAULT,
+                  0);
+        MUTEX_INIT(&tconn->conn_data_lock, "conn data lock", MUTEX_DEFAULT,
+                  0);
+       CV_INIT(&tconn->conn_call_cv, "conn call cv", CV_DEFAULT, 0);
 #endif
-         cid = (rx_nextCid += RX_MAXCALLS);
-         tconn->cid = cid;
-         RXS_NewConnection(securityObject, tconn);
-         hashindex =
-               CONN_HASH(shost, sport, tconn->cid, tconn->epoch, 
-                                 RX_CLIENT_CONNECTION);
-         tconn->refCount++; /* no lock required since only this thread knows */
-         tconn->next = rx_connHashTable[hashindex];
-         rx_connHashTable[hashindex] = tconn;
-         rx_MutexIncrement(rx_stats.nClientConns, rx_stats_mutex);     
+       RXS_NewConnection(securityObject, tconn);
+       hashindex =
+           CONN_HASH(shost, sport, tconn->cid, tconn->epoch,
+                     RX_CLIENT_CONNECTION);
+        tconn->refCount++;    /* no lock required since only this thread knows */
+       tconn->next = rx_connHashTable[hashindex];
+       rx_connHashTable[hashindex] = tconn;
+       rx_MutexIncrement(rx_stats.nClientConns, rx_stats_mutex);
     }
-    
+       
     RWLOCK_UNLOCK(&rx_connHashTable_lock);
     USERPRI;
     return conn;
 }
 
 void
-rx_SetConnDeadTime(register struct rx_connection *conn, register int seconds)
+rx_SetConnDeadTime(struct rx_connection *conn, int seconds)
 {
-  /* The idea is to set the dead time to a value that allows several
-   * keepalives to be dropped without timing out the connection. */
-  struct rx_connection *tconn;
-  tconn = conn;
-  do {
-       tconn->secondsUntilDead = MAX(seconds, 6);
-       tconn->secondsUntilPing = tconn->secondsUntilDead / 6;
-  } while(tconn->next_clone && (tconn = tconn->next_clone));
+    /* The idea is to set the dead time to a value that allows several
+     * keepalives to be dropped without timing out the connection. */
+    struct rx_connection *tconn =
+        (rx_IsClonedConn(conn)) ? conn->parent : conn;
+    
+    tconn->secondsUntilDead = MAX(seconds, 6);
+    tconn->secondsUntilPing = rx_ConnSecondsUntilDead(tconn) / 6;
 }
 
 int rxi_lowPeerRefCount = 0;
@@ -928,42 +934,47 @@ rxi_CleanupConnection(struct rx_connection *conn)
 void
 rxi_DestroyConnection(register struct rx_connection *conn)
 {
-  register struct rx_connection *tconn, *dtconn;
-  
-  RWLOCK_WRLOCK(&rx_connHashTable_lock);
-  
-  if(!(conn->flags & RX_CLONED_CONNECTION)) {
+    register struct rx_connection *tconn, *dtconn;
+    
+    RWLOCK_WRLOCK(&rx_connHashTable_lock);
+    
+    /* destroy any clones that might exist */
+    if (!rx_IsClonedConn(conn)) {
        tconn = conn->next_clone;
-       conn->next_clone = 0; /* once */
-       do {
-         if(tconn) {
-               dtconn = tconn;
-               tconn = tconn->next_clone;
-               rxi_DestroyConnectionNoLock(dtconn);
-               /* destroyed? */
-               if (dtconn == rx_connCleanup_list) {
-                 rx_connCleanup_list = rx_connCleanup_list->next;
-                 RWLOCK_UNLOCK(&rx_connHashTable_lock);
-                 /* rxi_CleanupConnection will free tconn */   
-                 rxi_CleanupConnection(dtconn);
-                 RWLOCK_WRLOCK(&rx_connHashTable_lock);
-                 (conn->nclones)--;
-               }
-         }
-       } while(tconn);
-  }
-
-  rxi_DestroyConnectionNoLock(conn);
-  /* conn should be at the head of the cleanup list */
-  if (conn == rx_connCleanup_list) {
+       conn->next_clone = 0;   /* once */
+       
+       while (tconn) {
+           dtconn = tconn;
+           tconn = tconn->next_clone;
+           rxi_DestroyConnectionNoLock(dtconn);
+           /*
+            * if destroyed dtconn will be the head of
+            * rx_connCleanup_list.  Remove it and clean 
+            * it up now as no one else is holding a 
+            * reference to it.
+            */
+           if (dtconn == rx_connCleanup_list) {
+               rx_connCleanup_list = rx_connCleanup_list->next;
+               MUTEX_EXIT(&rx_connHashTable_lock);
+               /* rxi_CleanupConnection will free dtconn */
+               rxi_CleanupConnection(dtconn);
+               MUTEX_ENTER(&rx_connHashTable_lock);
+               (conn->nclones)--;
+           }
+       }                       /* while(tconn) */
+    }
+    /* !rx_IsCloned */
+    rxi_DestroyConnectionNoLock(conn);
+    /* conn should be at the head of the cleanup list */
+    if (conn == rx_connCleanup_list) {
        rx_connCleanup_list = rx_connCleanup_list->next;
        RWLOCK_UNLOCK(&rx_connHashTable_lock);
        rxi_CleanupConnection(conn);
-  }
+    }
 #ifdef RX_ENABLE_LOCKS
-  else {
+    else {
        RWLOCK_UNLOCK(&rx_connHashTable_lock);
-  }
+    }
 #endif /* RX_ENABLE_LOCKS */
 }
 
@@ -1189,49 +1200,48 @@ rx_NewCall(register struct rx_connection *conn)
        MUTEX_EXIT(&conn->conn_data_lock);
     }
 
-       /* search for next free call on this connection or 
-        * its clones, if any */
+    /* search for next free call on this connection or 
+     * its clones, if any */
     for (;;) {
-               tconn = conn;
-               do {
-                       for (i = 0; i < RX_MAXCALLS; i++) {
-                               call = tconn->call[i];
-                               if (call) {
-                                       MUTEX_ENTER(&call->lock);
-                                       if (call->state == RX_STATE_DALLY) {
-                                               rxi_ResetCall(call, 0);
-                                               (*call->callNumber)++;
-                                               goto f_call;
-                                       }
-                                       MUTEX_EXIT(&call->lock);
-                               } else {
-                                       call = rxi_NewCall(tconn, i);
-                                       goto f_call;
-                               }
-                       } /* for i < RX_MAXCALLS */
-               } while (tconn->next_clone && (tconn = tconn->next_clone));
-
-       f_call:
-
-               if (i < RX_MAXCALLS) {
-                       break;
-               }
-
-               /* to be here, all available calls for this connection (and all
-                * its clones) must be in use */
-
-               MUTEX_ENTER(&conn->conn_data_lock);
-               conn->flags |= RX_CONN_MAKECALL_WAITING;
-               conn->makeCallWaiters++;
-               MUTEX_EXIT(&conn->conn_data_lock);
-
+       register struct rx_connection *tconn;
+       
+       for (tconn = conn; tconn; tconn = tconn->next_clone) {
+           for (i = 0; i < RX_MAXCALLS; i++) {
+               call = tconn->call[i];
+               if (call) {
+                   MUTEX_ENTER(&call->lock);
+                   if (call->state == RX_STATE_DALLY) {
+                       rxi_ResetCall(call, 0);
+                       (*call->callNumber)++;
+                       goto have_call;
+                   }
+                   MUTEX_EXIT(&call->lock);
+               } else {
+                   call = rxi_NewCall(tconn, i);
+                   goto have_call;
+              }
+           }                   /* for i < RX_MAXCALLS */
+       }
+       
+       /* 
+        * to be here, all available calls for this connection (and all
+        * of its clones) must be in use 
+        */
+       
+       MUTEX_ENTER(&conn->conn_data_lock);
+       conn->flags |= RX_CONN_MAKECALL_WAITING;
+       conn->makeCallWaiters++;
+       MUTEX_EXIT(&conn->conn_data_lock);
+       
 #ifdef RX_ENABLE_LOCKS
-               CV_WAIT(&conn->conn_call_cv, &conn->conn_call_lock);
+       CV_WAIT(&conn->conn_call_cv, &conn->conn_call_lock);
 #else
-               osi_rxSleep(conn);
+       osi_rxSleep(conn);
 #endif
-               rx_MutexDecrement(conn->makeCallWaiters, conn->conn_data_lock);
+       rx_MutexDecrement(conn->makeCallWaiters, conn->conn_data_lock);
     } /* for ;; */
+
+ have_call:
     /*
      * Wake up anyone else who might be giving us a chance to
      * run (see code above that avoids resource starvation).
@@ -1246,7 +1256,7 @@ rx_NewCall(register struct rx_connection *conn)
 
     /* Client is initially in send mode */
     call->state = RX_STATE_ACTIVE;
-    call->error = conn->error;
+    call->error = rx_ConnError(conn);
     if (call->error)
        call->mode = RX_MODE_ERROR;
     else
@@ -1278,7 +1288,7 @@ rx_NewCall(register struct rx_connection *conn)
 
     dpf(("rx_NewCall(call %x)\n", call));
     return call;
-}
+}                              /* rx_NewCall */
 
 int
 rxi_HasActiveCalls(register struct rx_connection *aconn)
@@ -2640,7 +2650,7 @@ rxi_ReceivePacket(register struct rx_packet *np, osi_socket socket,
 
     /* If the connection is in an error state, send an abort packet and ignore
      * the incoming packet */
-    if (conn->error) {
+    if (rx_ConnError(conn)) {
        /* Don't respond to an abort packet--we don't want loops! */
        MUTEX_ENTER(&conn->conn_data_lock);
        if (np->header.type != RX_PACKET_TYPE_ABORT)
@@ -4436,7 +4446,7 @@ rxi_SendConnectionAbort(register struct rx_connection *conn,
     afs_int32 error;
     struct clock when, now;
 
-    if (!conn->error)
+    if (!rx_ConnError(conn))
        return packet;
 
     /* Clients should never delay abort messages */
@@ -4448,7 +4458,7 @@ rxi_SendConnectionAbort(register struct rx_connection *conn,
        if (conn->delayedAbortEvent) {
            rxevent_Cancel(conn->delayedAbortEvent, (struct rx_call *)0, 0);
        }
-       error = htonl(conn->error);
+       error = htonl(rx_ConnError(conn));
        conn->abortCount++;
        MUTEX_EXIT(&conn->conn_data_lock);
        packet =
@@ -4466,17 +4476,20 @@ rxi_SendConnectionAbort(register struct rx_connection *conn,
     return packet;
 }
 
-/* Associate an error all of the calls owned by a connection.  Called
+/* 
+ * Associate an error all of the calls owned by a connection.  Called
  * with error non-zero.  This is only for really fatal things, like
  * bad authentication responses.  The connection itself is set in
  * error at this point, so that future packets received will be
- * rejected. */
+ * rejected. 
+ */
 void
 rxi_ConnectionError(register struct rx_connection *conn,
                    register afs_int32 error)
 {
     if (error) {
        register int i;
+        struct rx_connection *tconn;
 
        dpf(("rxi_ConnectionError conn %x error %d", conn, error));
 
@@ -4490,15 +4503,20 @@ rxi_ConnectionError(register struct rx_connection *conn,
            conn->refCount--;
        }
        MUTEX_EXIT(&conn->conn_data_lock);
-       for (i = 0; i < RX_MAXCALLS; i++) {
-           struct rx_call *call = conn->call[i];
-           if (call) {
-               MUTEX_ENTER(&call->lock);
-               rxi_CallError(call, error);
-               MUTEX_EXIT(&call->lock);
-           }
+
+        for ( tconn = rx_IsClonedConn(conn) ? conn->parent : conn;
+              tconn; 
+              tconn = tconn->next_clone) {
+            for (i = 0; i < RX_MAXCALLS; i++) {
+                struct rx_call *call = tconn->call[i];
+                if (call) {
+                    MUTEX_ENTER(&call->lock);
+                    rxi_CallError(call, error);
+                    MUTEX_EXIT(&call->lock);
+                }
+            }
        }
-       conn->error = error;
+        rx_SetConnError(conn, error);
         rx_MutexIncrement(rx_stats.fatalErrors, rx_stats_mutex);
     }
 }
@@ -5540,7 +5558,7 @@ rxi_CheckCall(register struct rx_call *call)
 #endif
     /* dead time + RTT + 8*MDEV, rounded up to next second. */
     deadTime =
-       (((afs_uint32) conn->secondsUntilDead << 10) +
+       (((afs_uint32) rx_ConnSecondsUntilDead(conn) << 10) +
         ((afs_uint32) conn->peer->rtt >> 3) +
         ((afs_uint32) conn->peer->rtt_dev << 1) + 1023) >> 10;
     now = clock_Sec();
@@ -5600,23 +5618,24 @@ rxi_CheckCall(register struct rx_call *call)
         * attached process can die reasonably gracefully. */
     }
     /* see if we have a non-activity timeout */
-    if (call->startWait && conn->idleDeadTime
-       && ((call->startWait + conn->idleDeadTime) < now)) {
+    if (call->startWait && rx_ConnIdleDeadTime(conn)
+       && ((call->startWait + rx_ConnIdleDeadTime(conn)) < now)) {
        if (call->state == RX_STATE_ACTIVE) {
            rxi_CallError(call, RX_CALL_TIMEOUT);
            return -1;
        }
     }
-    if (call->lastSendData && conn->idleDeadTime && (conn->idleDeadErr != 0)
-        && ((call->lastSendData + conn->idleDeadTime) < now)) {
+    if (call->lastSendData && rx_ConnIdleDeadTime(conn) 
+        && (rx_ConnIdleDeadErr(conn) != 0)
+        && ((call->lastSendData + rx_ConnIdleDeadTime(conn)) < now)) {
        if (call->state == RX_STATE_ACTIVE) {
            rxi_CallError(call, conn->idleDeadErr);
            return -1;
        }
     }
     /* see if we have a hard timeout */
-    if (conn->hardDeadTime
-       && (now > (conn->hardDeadTime + call->startTime.sec))) {
+    if (rx_ConnHardDeadTime(conn)
+       && (now > (rx_ConnHardDeadTime(conn) + call->startTime.sec))) {
        if (call->state == RX_STATE_ACTIVE)
            rxi_CallError(call, RX_CALL_TIMEOUT);
        return -1;
@@ -5661,7 +5680,7 @@ rxi_KeepAliveEvent(struct rxevent *event, void *arg1, void *dummy)
     }
 
     conn = call->conn;
-    if ((now - call->lastSendTime) > conn->secondsUntilPing) {
+    if ((now - call->lastSendTime) > rx_ConnSecondsUntilPing(conn)) {
        /* Don't try to send keepalives if there is unacknowledged data */
        /* the rexmit code should be good enough, this little hack 
         * doesn't quite work XXX */
@@ -5679,7 +5698,7 @@ rxi_ScheduleKeepAliveEvent(register struct rx_call *call)
        struct clock when, now;
        clock_GetTime(&now);
        when = now;
-       when.sec += call->conn->secondsUntilPing;
+       when.sec += rx_ConnSecondsUntilPing(call->conn);
        CALL_HOLD(call, RX_CALL_REFCOUNT_ALIVE);
        call->keepAliveEvent =
            rxevent_PostNow(&when, &now, rxi_KeepAliveEvent, call, 0);
@@ -5712,7 +5731,7 @@ rxi_SendDelayedConnAbort(struct rxevent *event,
 
     MUTEX_ENTER(&conn->conn_data_lock);
     conn->delayedAbortEvent = NULL;
-    error = htonl(conn->error);
+    error = htonl(rx_ConnError(conn));
     conn->abortCount++;
     MUTEX_EXIT(&conn->conn_data_lock);
     packet = rxi_AllocPacket(RX_PACKET_CLASS_SPECIAL);
@@ -6732,7 +6751,7 @@ rx_GetServerConnections(osi_socket socket, afs_uint32 remoteAddr,
        for (i = 0; i < RX_MAXCALLS; i++) {
            conn->callNumber[i] = ntohl(conn->callNumber[i]);
        }
-       conn->error = ntohl(conn->error);
+        rx_SetConnError(conn, ntohl(rx_ConnError(conn)));
        conn->secStats.flags = ntohl(conn->secStats.flags);
        conn->secStats.expires = ntohl(conn->secStats.expires);
        conn->secStats.packetsReceived =
@@ -6972,38 +6991,44 @@ void
 rx_SetSpecific(struct rx_connection *conn, int key, void *ptr)
 {
     int i;
-    MUTEX_ENTER(&conn->conn_data_lock);
-    if (!conn->specific) {
-       conn->specific = (void **)malloc((key + 1) * sizeof(void *));
+    struct rx_connection *tconn =
+       (rx_IsClonedConn(conn)) ? conn->parent : conn;
+
+    MUTEX_ENTER(&tconn->conn_data_lock);
+    if (!tconn->specific) {
+       tconn->specific = (void **)malloc((key + 1) * sizeof(void *));
        for (i = 0; i < key; i++)
-           conn->specific[i] = NULL;
-       conn->nSpecific = key + 1;
-       conn->specific[key] = ptr;
-    } else if (key >= conn->nSpecific) {
-       conn->specific = (void **)
-           realloc(conn->specific, (key + 1) * sizeof(void *));
-       for (i = conn->nSpecific; i < key; i++)
-           conn->specific[i] = NULL;
-       conn->nSpecific = key + 1;
-       conn->specific[key] = ptr;
+           tconn->specific[i] = NULL;
+       tconn->nSpecific = key + 1;
+       tconn->specific[key] = ptr;
+    } else if (key >= tconn->nSpecific) {
+       tconn->specific = (void **)
+           realloc(tconn->specific, (key + 1) * sizeof(void *));
+       for (i = tconn->nSpecific; i < key; i++)
+           tconn->specific[i] = NULL;
+       tconn->nSpecific = key + 1;
+       tconn->specific[key] = ptr;
     } else {
-       if (conn->specific[key] && rxi_keyCreate_destructor[key])
+       if (tconn->specific[key] && rxi_keyCreate_destructor[key])
            (*rxi_keyCreate_destructor[key]) (conn->specific[key]);
-       conn->specific[key] = ptr;
+       tconn->specific[key] = ptr;
     }
-    MUTEX_EXIT(&conn->conn_data_lock);
+    MUTEX_EXIT(&tconn->conn_data_lock);
 }
 
 void *
 rx_GetSpecific(struct rx_connection *conn, int key)
 {
     void *ptr;
-    MUTEX_ENTER(&conn->conn_data_lock);
-    if (key >= conn->nSpecific)
+    struct rx_connection *tconn =
+       (rx_IsClonedConn(conn)) ? conn->parent : conn;
+
+    MUTEX_ENTER(&tconn->conn_data_lock);
+    if (key >= tconn->nSpecific)
        ptr = NULL;
     else
-       ptr = conn->specific[key];
-    MUTEX_EXIT(&conn->conn_data_lock);
+       ptr = tconn->specific[key];
+    MUTEX_EXIT(&tconn->conn_data_lock);
     return ptr;
 }
 
index d100ffe..f1635d2 100644 (file)
@@ -110,16 +110,24 @@ int ntoh_syserr_conv(int error);
 #define rx_GetLocalStatus(call, status) ((call)->localStatus)
 #define        rx_GetRemoteStatus(call)        ((call)->remoteStatus)
 #define        rx_Error(call)                  ((call)->error)
-#define        rx_ConnError(conn)              ((conn)->error)
 #define        rx_IsServerConn(conn)           ((conn)->type == RX_SERVER_CONNECTION)
 #define        rx_IsClientConn(conn)           ((conn)->type == RX_CLIENT_CONNECTION)
 /* Don't use these; use the IsServerConn style */
 #define        rx_ServerConn(conn)             ((conn)->type == RX_SERVER_CONNECTION)
 #define        rx_ClientConn(conn)             ((conn)->type == RX_CLIENT_CONNECTION)
 #define rx_IsUsingPktCksum(conn)       ((conn)->flags & RX_CONN_USING_PACKET_CKSUM)
+#define rx_IsClonedConn(conn)           ((conn)->flags & RX_CLONED_CONNECTION)
 #define rx_ServiceIdOf(conn)           ((conn)->serviceId)
 #define        rx_SecurityClassOf(conn)        ((conn)->securityIndex)
 #define rx_SecurityObjectOf(conn)      ((conn)->securityObject)
+#define rx_ConnError(conn)             (rx_IsClonedConn((conn)) ? (conn)->parent->error : (conn)->error)
+#define rx_SetConnError(conn, err)      (rx_IsClonedConn((conn)) ? ((conn)->parent->error = err): ((conn)->error = err))
+#define rx_ConnHardDeadTime(conn)      (rx_IsClonedConn((conn)) ? (conn)->parent->hardDeadTime : (conn)->hardDeadTime)
+#define rx_ConnIdleDeadTime(conn)      (rx_IsClonedConn((conn)) ? (conn)->parent->idleDeadTime : (conn)->idleDeadTime)
+#define rx_ConnIdleDeadErr(conn)       (rx_IsClonedConn((conn)) ? (conn)->parent->idleDeadErr : (conn)->idleDeadErr)
+#define rx_ConnSecondsUntilDead(conn)  (rx_IsClonedConn((conn)) ? (conn)->parent->secondsUntilDead : (conn)->secondsUntilDead)
+#define rx_ConnSecondsUntilPing(conn)  (rx_IsClonedConn((conn)) ? (conn)->parent->secondsUntilPing : (conn)->secondsUntilPing)
+
 
 /*******************
  * Macros callable by the user to further define attributes of a
@@ -167,9 +175,30 @@ int ntoh_syserr_conv(int error);
 #define rx_SetCheckReach(service, x) ((service)->checkReach = (x))
 
 /* Set connection hard and idle timeouts for a connection */
-#define rx_SetConnHardDeadTime(conn, seconds) ((conn)->hardDeadTime = (seconds))
-#define rx_SetConnIdleDeadTime(conn, seconds) ((conn)->idleDeadTime = (seconds))
-#define rx_SetServerConnIdleDeadErr(conn,err) ((conn)->idleDeadErr = (err))
+#define rx_SetConnHardDeadTime(conn, seconds)\
+    {\
+    if (rx_IsClonedConn(conn))                                         \
+       (conn)->parent->hardDeadTime = (seconds);                       \
+    else                                                               \
+       (conn)->hardDeadTime = (seconds);                               \
+    }
+
+#define rx_SetConnIdleDeadTime(conn, seconds)\
+    {\
+    if (rx_IsClonedConn(conn))                                         \
+       (conn)->parent->idleDeadTime = (seconds);                       \
+    else                                                               \
+       (conn)->idleDeadTime = (seconds);                               \
+    }
+
+#define rx_SetServerConnIdleDeadErr(conn, err)\
+    {\
+    if (rx_IsClonedConn(conn))                                         \
+       (conn)->parent->idleDeadErr = (err);                            \
+    else                                                               \
+       (conn)->idleDeadErr = (err);                                    \
+    }
+
 
 /* Set the overload threshold and the overload error */
 #define rx_SetBusyThreshold(threshold, code) (rx_BusyThreshold=(threshold),rx_BusyError=(code))
@@ -236,8 +265,6 @@ struct rx_connection_rx_lock {
 #else
 struct rx_connection {
     struct rx_connection *next;        /* on hash chain _or_ free list */
-    struct rx_connection *parent; /* primary connection, if this is a clone */
-    struct rx_connection *next_clone; /* next in list of clones */
     struct rx_peer *peer;
 #endif
 #ifdef RX_ENABLE_LOCKS
@@ -245,7 +272,6 @@ struct rx_connection {
     afs_kcondvar_t conn_call_cv;
     afs_kmutex_t conn_data_lock;       /* locks packet data */
 #endif
-    afs_uint32 nclones; /* count of clone connections (if not a clone) */
     afs_uint32 epoch;          /* Process start time of client side of connection */
     afs_uint32 cid;            /* Connection id (call channel is bottom bits) */
     afs_int32 error;           /* If this connection is in error, this is it */
@@ -291,6 +317,9 @@ struct rx_connection {
     afs_int32 idleDeadErr;
     int nSpecific;             /* number entries in specific data */
     void **specific;           /* pointer to connection specific data */
+    struct rx_connection *parent; /* primary connection, if this is a clone */
+    struct rx_connection *next_clone; /* next in list of clones */
+    afs_uint32 nclones; /* count of clone connections (if not a clone) */
 };
 
 
@@ -902,44 +931,46 @@ struct rx_debugStats {
 };
 
 struct rx_debugConn_vL {
-    afs_int32 host;
-    afs_int32 cid;
-    afs_int32 serial;
-    afs_int32 callNumber[RX_MAXCALLS];
-    afs_int32 error;
-    short port;
-    char flags;
-    char type;
-    char securityIndex;
-    char callState[RX_MAXCALLS];
-    char callMode[RX_MAXCALLS];
-    char callFlags[RX_MAXCALLS];
-    char callOther[RX_MAXCALLS];
+    afs_uint32 host;
+    afs_uint32 cid;
+    struct rx_debugConn_vL *parent;    /* primary connection, if this is a clone */
+    afs_uint32 serial;
+    afs_uint32 callNumber[RX_MAXCALLS];
+    afs_uint32 error;
+    u_short port;
+    u_char flags;
+    u_char type;
+    u_char securityIndex;
+    u_char callState[RX_MAXCALLS];
+    u_char callMode[RX_MAXCALLS];
+    u_char callFlags[RX_MAXCALLS];
+    u_char callOther[RX_MAXCALLS];
     /* old style getconn stops here */
     struct rx_securityObjectStats secStats;
-    afs_int32 sparel[10];
+    afs_uint32 sparel[10];
 };
 
 struct rx_debugConn {
-    afs_int32 host;
-    afs_int32 cid;
-    afs_int32 serial;
-    afs_int32 callNumber[RX_MAXCALLS];
-    afs_int32 error;
-    short port;
-    char flags;
-    char type;
-    char securityIndex;
-    char sparec[3];            /* force correct alignment */
-    char callState[RX_MAXCALLS];
-    char callMode[RX_MAXCALLS];
-    char callFlags[RX_MAXCALLS];
-    char callOther[RX_MAXCALLS];
+    afs_uint32 host;
+    afs_uint32 cid;
+    struct rx_debugConn *parent;       /* primary connection, if this is a clone */
+    afs_uint32 serial;
+    afs_uint32 callNumber[RX_MAXCALLS];
+    afs_uint32 error;
+    u_short port;
+    u_char flags;
+    u_char type;
+    u_char securityIndex;
+    u_char sparec[3];          /* force correct alignment */
+    u_char callState[RX_MAXCALLS];
+    u_char callMode[RX_MAXCALLS];
+    u_char callFlags[RX_MAXCALLS];
+    u_char callOther[RX_MAXCALLS];
     /* old style getconn stops here */
     struct rx_securityObjectStats secStats;
-    afs_int32 epoch;
-    afs_int32 natMTU;
-    afs_int32 sparel[9];
+    afs_uint32 epoch;
+    afs_uint32 natMTU;
+    afs_uint32 sparel[9];
 };
 
 struct rx_debugPeer {
index 8f08ab1..d46564c 100644 (file)
@@ -66,4 +66,9 @@ void rx_SetUdpBufSize(int x)
         rx_UdpBufSize = x;
 }
 
+void rx_SetMaxClonesPerConn(int x)
+{
+    rx_max_clones_per_connection = x;
+}
+
 #endif /* AFS_NT40_ENV */
index 74c9e5f..90583e2 100644 (file)
@@ -102,9 +102,11 @@ EXT int rx_UdpBufSize GLOBALSINIT(64 * 1024);
 #ifdef AFS_NT40_ENV
 int   rx_GetMinUdpBufSize(void);
 void  rx_SetUdpBufSize(int x);
+void rx_SetMaxClonesPerConn(int x);
 #else
 #define rx_GetMinUdpBufSize()   (64*1024)
 #define rx_SetUdpBufSize(x)     (((x)>rx_GetMinUdpBufSize()) ? (rx_UdpBufSize = (x)):0)
+#define rx_SetMaxClonesPerConn(x)  (rx_max_clones_per_connection = x)
 #endif
 /*
  * Variables to control RX overload management. When the number of calls
@@ -622,9 +624,7 @@ EXT int rx_enable_hot_thread GLOBALSINIT(0);
  * Set rx_max_clones_per_connection to a value > 0 to enable connection clone 
  * workaround to RX_MAXCALLS limit.
  */
 #define RX_HARD_MAX_CLONES 10
-
 EXT int rx_max_clones_per_connection GLOBALSINIT(2);
 
 EXT int RX_IPUDP_SIZE GLOBALSINIT(_RX_IPUDP_SIZE);
index e66db4a..5c48a57 100644 (file)
@@ -409,6 +409,16 @@ MainCommand(struct cmd_syndesc *as, void *arock)
                    printf(" DESTROYED");
                if (tconn.flags & RX_CONN_USING_PACKET_CKSUM)
                    printf(" pktCksum");
+                if (tconn.flags & RX_CONN_KNOW_WINDOW)
+                    printf(" knowWindow");
+                if (tconn.flags & RX_CONN_RESET)
+                    printf(" reset");
+                if (tconn.flags & RX_CONN_BUSY)
+                    printf(" busy");
+                if (tconn.flags & RX_CONN_ATTACHWAIT)
+                    printf(" attachWait");
+                if (tconn.flags & RX_CLONED_CONNECTION)
+                    printf(" clone");
                printf(", ");
            }
            printf("security index %d, ", tconn.securityIndex);