server-meltdown-avoidance-20080509
authorDerrick Brashear <shadow@dementia.org>
Fri, 9 May 2008 19:50:39 +0000 (19:50 +0000)
committerDerrick Brashear <shadow@dementia.org>
Fri, 9 May 2008 19:50:39 +0000 (19:50 +0000)
LICENSE IPL10

if the server is melting down or otherwise unable to reply with data, it will
cut itself off.

src/rx/rx.c
src/rx/rx.h
src/viced/viced.c

index e1024ad..3341cb1 100644 (file)
@@ -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))) {
index d40669b..ebe0047 100644 (file)
@@ -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 */
index 1537892..d3fd3c0 100644 (file)
@@ -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,