From c26dc0e6aaefedc55ed5c35a5744b5c01ba39ea1 Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Fri, 9 May 2008 19:50:39 +0000 Subject: [PATCH] server-meltdown-avoidance-20080509 LICENSE IPL10 if the server is melting down or otherwise unable to reply with data, it will cut itself off. --- src/rx/rx.c | 14 +++++++++++++- src/rx/rx.h | 7 +++++++ src/viced/viced.c | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/rx/rx.c b/src/rx/rx.c index e1024adda..3341cb15d 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -1324,6 +1324,7 @@ rx_NewServiceHost(afs_uint32 host, u_short port, u_short serviceId, service->minProcs = 0; service->maxProcs = 1; service->idleDeadTime = 60; + service->idleDeadErr = 0; service->connDeadTime = rx_connDeadTime; service->executeRequestProc = serviceProc; service->checkReach = 0; @@ -2385,6 +2386,7 @@ rxi_FindConnection(osi_socket socket, register afs_int32 host, conn->specific = NULL; rx_SetConnDeadTime(conn, service->connDeadTime); rx_SetConnIdleDeadTime(conn, service->idleDeadTime); + rx_SetServerConnIdleDeadErr(conn, service->idleDeadErr); for (i = 0; i < RX_MAXCALLS; i++) { conn->twind[i] = rx_initSendWindow; conn->rwind[i] = rx_initReceiveWindow; @@ -4918,7 +4920,7 @@ rxi_SendList(struct rx_call *call, struct rx_packet **list, int len, /* Update last send time for this call (for keep-alive * processing), and for the connection (so that we can discover * idle connections) */ - conn->lastSendTime = call->lastSendTime = clock_Sec(); + call->lastSendData = conn->lastSendTime = call->lastSendTime = clock_Sec(); } /* When sending packets we need to follow these rules: @@ -5382,6 +5384,9 @@ rxi_Send(register struct rx_call *call, register struct rx_packet *p, * processing), and for the connection (so that we can discover * idle connections) */ conn->lastSendTime = call->lastSendTime = clock_Sec(); + /* Don't count keepalives here, so idleness can be tracked. */ + if (p->header.type != RX_PACKET_TYPE_ACK) + call->lastSendData = call->lastSendTime; } @@ -5455,6 +5460,13 @@ rxi_CheckCall(register struct rx_call *call) return -1; } } + if (call->lastSendData && conn->idleDeadTime && (conn->idleDeadErr != 0) + && ((call->lastSendData + conn->idleDeadTime) < 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))) { diff --git a/src/rx/rx.h b/src/rx/rx.h index d40669bc0..ebe0047e1 100644 --- a/src/rx/rx.h +++ b/src/rx/rx.h @@ -147,6 +147,9 @@ int ntoh_syserr_conv(int error); /* Define procedure to set service dead time */ #define rx_SetIdleDeadTime(service,time) ((service)->idleDeadTime = (time)) +/* Define error to return in server connections when failing to answer */ +#define rx_SetServerIdleDeadErr(service,err) ((service)->idleDeadErr = (err)) + /* Define procedures for getting and setting before and after execute-request procs */ #define rx_SetAfterProc(service,proc) ((service)->afterProc = (proc)) #define rx_SetBeforeProc(service,proc) ((service)->beforeProc = (proc)) @@ -167,6 +170,7 @@ int ntoh_syserr_conv(int error); /* 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)) /* Set the overload threshold and the overload error */ #define rx_SetBusyThreshold(threshold, code) (rx_BusyThreshold=(threshold),rx_BusyError=(code)) @@ -267,6 +271,7 @@ struct rx_connection { u_short idleDeadTime; /* max time a call can be idle (no data) */ u_char ackRate; /* how many packets between ack requests */ u_char makeCallWaiters; /* how many rx_NewCalls are waiting */ + afs_int32 idleDeadErr; int nSpecific; /* number entries in specific data */ void **specific; /* pointer to connection specific data */ }; @@ -311,6 +316,7 @@ struct rx_service { u_short connDeadTime; /* Seconds until a client of this service will be declared dead, if it is not responding */ u_short idleDeadTime; /* Time a server will wait for I/O to start up again */ u_char checkReach; /* Check for asymmetric clients? */ + afs_int32 idleDeadErr; }; #endif /* KDUMP_RX_LOCK */ @@ -507,6 +513,7 @@ struct rx_call { int abortCount; /* number of times last error was sent */ u_int lastSendTime; /* Last time a packet was sent on this call */ u_int lastReceiveTime; /* Last time a packet was received for this call */ + u_int lastSendData; /* Last time a nonping was sent on this call */ void (*arrivalProc) (register struct rx_call * call, register void * mh, register int index); /* Procedure to call when reply is received */ void *arrivalProcHandle; /* Handle to pass to replyFunc */ int arrivalProcArg; /* Additional arg to pass to reply Proc */ diff --git a/src/viced/viced.c b/src/viced/viced.c index 15378928b..d3fd3c022 100644 --- a/src/viced/viced.c +++ b/src/viced/viced.c @@ -2101,6 +2101,7 @@ main(int argc, char *argv[]) rx_SetMinProcs(tservice, 3); rx_SetMaxProcs(tservice, lwps); rx_SetCheckReach(tservice, 1); + rx_SetServerIdleDeadErr(tservice, VNOSERVICE); tservice = rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats", sc, 4, -- 2.39.5