diff --git a/src/rx/rx.c b/src/rx/rx.c index 505ba00123..cbbf317a23 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -1328,6 +1328,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; @@ -2389,6 +2390,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; @@ -4922,7 +4924,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: @@ -5386,6 +5388,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; } @@ -5459,6 +5464,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 1d6c35d3c3..6a83900d0a 100644 --- a/src/rx/rx.h +++ b/src/rx/rx.h @@ -145,6 +145,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)) @@ -165,6 +168,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)) @@ -265,6 +269,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 */ }; @@ -309,6 +314,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 */ @@ -505,6 +511,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 baa32e6a67..6d597003ff 100644 --- a/src/viced/viced.c +++ b/src/viced/viced.c @@ -2097,6 +2097,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,