From: Jeffrey Altman Date: Thu, 20 Nov 2008 22:56:12 +0000 (+0000) Subject: clones-take-two-20081120 X-Git-Tag: openafs-devel-1_5_61~685 X-Git-Url: http://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=ef92a3331f25375387a99fbb690c4473ee91d945 clones-take-two-20081120 LICENSE IPL10 FIXES 89557 commit jeff's revised version of the patch --- diff --git a/src/rx/rx.c b/src/rx/rx.c index 27e31c9..77ea8ca 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -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; } diff --git a/src/rx/rx.h b/src/rx/rx.h index d100ffe..f1635d2 100644 --- a/src/rx/rx.h +++ b/src/rx/rx.h @@ -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 { diff --git a/src/rx/rx_globals.c b/src/rx/rx_globals.c index 8f08ab1..d46564c 100644 --- a/src/rx/rx_globals.c +++ b/src/rx/rx_globals.c @@ -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 */ diff --git a/src/rx/rx_globals.h b/src/rx/rx_globals.h index 74c9e5f..90583e2 100644 --- a/src/rx/rx_globals.h +++ b/src/rx/rx_globals.h @@ -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); diff --git a/src/rxdebug/rxdebug.c b/src/rxdebug/rxdebug.c index e66db4a..5c48a57 100644 --- a/src/rxdebug/rxdebug.c +++ b/src/rxdebug/rxdebug.c @@ -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);