From a4eb6e722de55fe6dd599ac74434105e674a2b4a Mon Sep 17 00:00:00 2001 From: Derek Atkins Date: Fri, 17 Jan 2003 05:42:34 +0000 Subject: [PATCH] STABLE12-linux-fast-netdown-20020107 notice the NETUNREACH quickly and mark a host down (cherry picked from commit b72c14c4cfdae85c469bcc1b88659e5bd6fb620c) --- src/rx/rx.c | 6 +++--- src/rx/rx_packet.c | 42 ++++++++++++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/rx/rx.c b/src/rx/rx.c index 56fd9579d..6b5f7b387 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -4741,9 +4741,9 @@ static void rxi_SendList(call, list, len, istack, moreFlag, now, retryTime, rese CALL_HOLD(call, RX_CALL_REFCOUNT_SEND); MUTEX_EXIT(&call->lock); if (len > 1) { - rxi_SendPacketList(conn, list, len, istack); + rxi_SendPacketList(call, conn, list, len, istack); } else { - rxi_SendPacket(conn, list[0], istack); + rxi_SendPacket(call, conn, list[0], istack); } MUTEX_ENTER(&call->lock); CALL_RELE(call, RX_CALL_REFCOUNT_SEND); @@ -5200,7 +5200,7 @@ void rxi_Send(call, p, istack) /* Actually send the packet, filling in more connection-specific fields */ CALL_HOLD(call, RX_CALL_REFCOUNT_SEND); MUTEX_EXIT(&call->lock); - rxi_SendPacket(conn, p, istack); + rxi_SendPacket(call, conn, p, istack); MUTEX_ENTER(&call->lock); CALL_RELE(call, RX_CALL_REFCOUNT_SEND); diff --git a/src/rx/rx_packet.c b/src/rx/rx_packet.c index 12e26443a..5485d954a 100644 --- a/src/rx/rx_packet.c +++ b/src/rx/rx_packet.c @@ -1471,14 +1471,15 @@ static void rxi_SendDebugPacket(struct rx_packet *apacket, osi_socket asocket, } /* Send the packet to appropriate destination for the specified - * connection. The header is first encoded and placed in the packet. + * call. The header is first encoded and placed in the packet. */ -void rxi_SendPacket(struct rx_connection * conn, struct rx_packet *p, - int istack) +void rxi_SendPacket(struct rx_call * call, struct rx_connection * conn, + struct rx_packet *p, int istack) { #if defined(KERNEL) int waslocked; #endif + int code; struct sockaddr_in addr; register struct rx_peer *peer = conn->peer; osi_socket socket; @@ -1550,14 +1551,24 @@ void rxi_SendPacket(struct rx_connection * conn, struct rx_packet *p, waslocked = ISAFS_GLOCK(); if (waslocked) AFS_GUNLOCK(); #endif - if (osi_NetSend(socket, &addr, p->wirevec, p->niovecs, - p->length+RX_HEADER_SIZE, istack)){ + if ((code = osi_NetSend(socket, &addr, p->wirevec, p->niovecs, + p->length+RX_HEADER_SIZE, istack)) != 0) { /* send failed, so let's hurry up the resend, eh? */ MUTEX_ENTER(&rx_stats_mutex); rx_stats.netSendFailures++; MUTEX_EXIT(&rx_stats_mutex); p->retryTime = p->timeSent; /* resend it very soon */ clock_Addmsec(&(p->retryTime), 10 + (((afs_uint32) p->backoff) << 8)); + +#if defined(KERNEL) && defined(AFS_LINUX20_ENV) + /* Linux is nice -- it can tell us right away that we cannot + * reach this recipient by returning an ENETUNREACH error + * code. So, when this happens let's "down" the host NOW so + * we don't sit around waiting for this host to timeout later. + */ + if (call && code == -ENETUNREACH) + call->lastReceiveTime = 0; +#endif } #ifdef KERNEL if (waslocked) AFS_GLOCK(); @@ -1582,10 +1593,8 @@ void rxi_SendPacket(struct rx_connection * conn, struct rx_packet *p, /* Send a list of packets to appropriate destination for the specified * connection. The headers are first encoded and placed in the packets. */ -void rxi_SendPacketList(struct rx_connection * conn, - struct rx_packet **list, - int len, - int istack) +void rxi_SendPacketList(struct rx_call * call, struct rx_connection * conn, + struct rx_packet **list, int len, int istack) { #if defined(AFS_SUN5_ENV) && defined(KERNEL) int waslocked; @@ -1595,7 +1604,7 @@ void rxi_SendPacketList(struct rx_connection * conn, osi_socket socket; struct rx_packet *p = NULL; struct iovec wirevec[RX_MAXIOVECS]; - int i, length; + int i, length, code; afs_uint32 serial; afs_uint32 temp; struct rx_jumboHeader *jp; @@ -1715,7 +1724,7 @@ void rxi_SendPacketList(struct rx_connection * conn, waslocked = ISAFS_GLOCK(); if (!istack && waslocked) AFS_GUNLOCK(); #endif - if (osi_NetSend(socket, &addr, &wirevec[0], len+1, length, istack)){ + if ((code = osi_NetSend(socket, &addr, &wirevec[0], len+1, length, istack)) != 0){ /* send failed, so let's hurry up the resend, eh? */ MUTEX_ENTER(&rx_stats_mutex); rx_stats.netSendFailures++; @@ -1725,6 +1734,15 @@ void rxi_SendPacketList(struct rx_connection * conn, p->retryTime = p->timeSent; /* resend it very soon */ clock_Addmsec(&(p->retryTime), 10 + (((afs_uint32) p->backoff) << 8)); } +#if defined(KERNEL) && defined(AFS_LINUX20_ENV) + /* Linux is nice -- it can tell us right away that we cannot + * reach this recipient by returning an ENETUNREACH error + * code. So, when this happens let's "down" the host NOW so + * we don't sit around waiting for this host to timeout later. + */ + if (call && code == -ENETUNREACH) + call->lastReceiveTime = 0; +#endif } #if defined(AFS_SUN5_ENV) && defined(KERNEL) if (!istack && waslocked) AFS_GLOCK(); @@ -1816,7 +1834,7 @@ rxi_SendSpecial(call, conn, optionalPacket, type, data, nbytes, istack) } if (call) rxi_Send(call, p, istack); - else rxi_SendPacket(conn, p, istack); + else rxi_SendPacket((struct rx_call *)0, conn, p, istack); if (saven) { /* means we truncated the packet above. We probably don't */ /* really need to do this, but it seems safer this way, given that */ /* sneaky optionalPacket... */ -- 2.39.5