afsi_log("rx_SetUdpBufSize %d", rx_udpbufsize);
}
- rx_SetBusyChannelError(CM_RX_RETRY_BUSY_CALL);
+ rx_SetBusyChannelError(1); /* Activate busy call channel reporting */
/* initialize RX, and tell it to listen to the callbackport,
* which is used for callback RPC messages.
#define CM_FLAG_NOPROBE 0x100 /* For use with cm_GetCellxxx - do not probe server status */
#define CM_FLAG_DFS_REFERRAL 0x200 /* The request is a DFS Referral - the last char of the lookup name may be missing */
-/* Private RX Errors */
-#define CM_RX_RETRY_BUSY_CALL (-13)
-
/* Used by cm_FollowMountPoint and cm_FindVolumeByName */
/* And as an index in cm_volume_t */
#define RWVOL 0
retry = 1;
}
- else if (errorCode == CM_RX_RETRY_BUSY_CALL) {
+ else if (errorCode == RX_CALL_BUSY) {
/*
* RPC failed because the selected call channel
* is currently busy on the server. Unconditionally
/* If not allowed to retry, don't */
if (!forcing_new && (reqp->flags & CM_REQ_NORETRY) &&
- (errorCode != RX_MSGSIZE && errorCode != CM_RX_RETRY_BUSY_CALL))
+ (errorCode != RX_MSGSIZE && errorCode != RX_CALL_BUSY))
retry = 0;
else if (retry && dead_session)
retry = 0;
rx_SetConnDeadTime(tcp->rxconnp, ConnDeadtimeout);
rx_SetConnHardDeadTime(tcp->rxconnp, HardDeadtimeout);
- /* Disable Idle Dead Timeout processing as it can lead to data corruption. */
- rx_SetConnIdleDeadTime(tcp->rxconnp, IdleDeadtimeout);
-
/*
- * Register the error to be returned on an idle dead timeout
+ * Setting idle dead timeout to a non-zero value activates RX_CALL_IDLE errors
*/
- rx_SetServerConnIdleDeadErr(tcp->rxconnp, RX_CALL_DEAD);
+ rx_SetConnIdleDeadTime(tcp->rxconnp, IdleDeadtimeout);
/*
* Let the Rx library know that we can auto-retry if an
} /* got an unauthenticated connection to this server */
lock_ObtainMutex(&tsp->mx);
- if (code >= 0 || code == RXGEN_OPCODE || code == CM_RX_RETRY_BUSY_CALL) {
+ if (code >= 0 || code == RXGEN_OPCODE || code == RX_CALL_BUSY) {
/* mark server as up */
_InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN);
tsp->downTime = 0;
/* we currently handle 32-bits of capabilities */
- if (code != RXGEN_OPCODE && code != CM_RX_RETRY_BUSY_CALL &&
+ if (code != RXGEN_OPCODE && code != RX_CALL_BUSY &&
caps.Capabilities_len > 0) {
tsp->capabilities = caps.Capabilities_val[0];
xdr_free((xdrproc_t) xdr_Capabilities, &caps);
wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
if (results[i] >= 0 || results[i] == RXGEN_OPCODE ||
- results[i] == CM_RX_RETRY_BUSY_CALL) {
+ results[i] == RX_CALL_BUSY) {
/* mark server as up */
_InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN);
tsp->downTime = 0;
/* we currently handle 32-bits of capabilities */
- if (results[i] != RXGEN_OPCODE && results[i] != CM_RX_RETRY_BUSY_CALL &&
+ if (results[i] != RXGEN_OPCODE && results[i] != RX_CALL_BUSY &&
caps[i].Capabilities_len > 0) {
tsp->capabilities = caps[i].Capabilities_val[0];
xdr_free((xdrproc_t) xdr_Capabilities, &caps[i]);
lock_ObtainMutex(&tsp->mx);
wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
- if (results[i] >= 0 || results[i] == CM_RX_RETRY_BUSY_CALL) {
+ if (results[i] >= 0 || results[i] == RX_CALL_BUSY) {
/* mark server as up */
_InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN);
tsp->downTime = 0;
if (error == RX_CALL_DEAD ||
error == RX_CALL_TIMEOUT ||
+ error == RX_CALL_BUSY ||
+ error == RX_CALL_IDLE ||
error == RX_MSGSIZE)
error = CM_ERROR_RETRY;
else if (error < 0)
if (error == RX_CALL_DEAD ||
error == RX_CALL_TIMEOUT ||
+ error == RX_CALL_BUSY ||
+ error == RX_CALL_IDLE ||
error == RX_MSGSIZE)
error = CM_ERROR_RETRY;
else if (error == VNOVNODE)
if (error == RX_CALL_DEAD ||
error == RX_CALL_TIMEOUT ||
+ error == RX_CALL_BUSY ||
+ error == RX_CALL_IDLE ||
error == RX_MSGSIZE)
error = CM_ERROR_RETRY;
else if (error == RX_RESTARTING)
shouldRetry = 1;
goto out;
}
- if (acode == RX_CALL_TIMEOUT) {
+ if (acode == RX_CALL_TIMEOUT || acode == RX_CALL_IDLE || acode == RX_CALL_BUSY) {
serversleft = afs_BlackListOnce(areq, afid, tsp);
if (afid)
tvp = afs_FindVolume(afid, READ_LOCK);
memset(afs_zeros, 0, AFS_ZEROS);
- rx_SetBusyChannelError(RX_CALL_TIMEOUT);
+ rx_SetBusyChannelError(1); /* turn on busy call error reporting */
/* start RX */
if(!afscall_set_rxpck_received)
if (service == 52) {
rx_SetConnHardDeadTime(tc->id, afs_rx_harddead);
}
- /* set to a RX_CALL_TIMEOUT error to allow MTU retry to trigger */
- rx_SetServerConnIdleDeadErr(tc->id, RX_CALL_DEAD);
+
+ /* Setting idle dead time to non-zero activates RX_CALL_IDLE errors. */
rx_SetConnIdleDeadTime(tc->id, afs_rx_idledead);
/*
AFS_GLOCK();
afs_InitStats();
- rx_SetBusyChannelError(RX_CALL_TIMEOUT);
+ rx_SetBusyChannelError(1); /* turn on busy call error reporting */
rx_Init(htons(7001));
AFS_STATCNT(afs_ResourceInit);
rx_GetSecurityHeaderSize @315
rx_SetSecurityMaxTrailerSize @316
rx_GetSecurityMaxTrailerSize @317
- rx_SetServerConnIdleDeadErr @318
+ ; @318 is available
rx_SetMsgsizeRetryErr @319
rx_IsServerConn @320
rx_IsClientConn @321
static unsigned int rxi_rpc_process_stat_cnt;
/*
- * rxi_busyChannelError is the error to return to the application when a call
- * channel appears busy (inferred from the receipt of RX_PACKET_TYPE_BUSY
- * packets on the channel), and there are other call channels in the
- * connection that are not busy. If 0, we do not return errors upon receiving
- * busy packets; we just keep trying on the same call channel until we hit a
- * timeout.
+ * rxi_busyChannelError is a boolean. It indicates whether or not RX_CALL_BUSY
+ * errors should be reported to the application when a call channel appears busy
+ * (inferred from the receipt of RX_PACKET_TYPE_BUSY packets on the channel),
+ * and there are other call channels in the connection that are not busy.
+ * If 0, we do not return errors upon receiving busy packets; we just keep
+ * trying on the same call channel until we hit a timeout.
*/
static afs_int32 rxi_busyChannelError = 0;
}
/**
- * Sets the error generated when a busy call channel is detected.
+ * Enables or disables the busy call channel error (RX_CALL_BUSY).
*
- * @param[in] error The error to return for a call on a busy channel.
+ * @param[in] onoff Non-zero to enable busy call channel errors.
*
* @pre Neither rx_Init nor rx_InitHost have been called yet
*/
void
-rx_SetBusyChannelError(afs_int32 error)
+rx_SetBusyChannelError(afs_int32 onoff)
{
osi_Assert(rxinit_status != 0);
- rxi_busyChannelError = error;
+ rxi_busyChannelError = onoff ? 1 : 0;
}
/**
rx_SetConnIdleDeadTime(struct rx_connection *conn, int seconds)
{
conn->idleDeadTime = seconds;
+ conn->idleDeadDetection = (seconds ? 1 : 0);
rxi_CheckConnTimeouts(conn);
}
conn->nSpecific = 0;
conn->specific = NULL;
rx_SetConnDeadTime(conn, service->connDeadTime);
- rx_SetConnIdleDeadTime(conn, service->idleDeadTime);
- rx_SetServerConnIdleDeadErr(conn, service->idleDeadErr);
+ conn->idleDeadTime = service->idleDeadTime;
+ conn->idleDeadDetection = service->idleDeadErr ? 1 : 0;
for (i = 0; i < RX_MAXCALLS; i++) {
conn->twind[i] = rx_initSendWindow;
conn->rwind[i] = rx_initReceiveWindow;
* rxi_busyChannelError so the application can retry the request,
* presumably on a less-busy call channel. */
- rxi_CallError(call, rxi_busyChannelError);
+ rxi_CallError(call, RX_CALL_BUSY);
}
}
rxi_SendCallAbort(struct rx_call *call, struct rx_packet *packet,
int istack, int force)
{
- afs_int32 error;
+ afs_int32 error, cerror;
struct clock when, now;
if (!call->error)
return packet;
+ switch (call->error) {
+ case RX_CALL_IDLE:
+ case RX_CALL_BUSY:
+ cerror = RX_CALL_TIMEOUT;
+ break;
+ default:
+ cerror = call->error;
+ }
+
/* Clients should never delay abort messages */
if (rx_IsClientConn(call->conn))
force = 1;
- if (call->abortCode != call->error) {
- call->abortCode = call->error;
+ if (call->abortCode != cerror) {
+ call->abortCode = cerror;
call->abortCount = 0;
}
rxevent_Cancel(&call->delayedAbortEvent, call,
RX_CALL_REFCOUNT_ABORT);
}
- error = htonl(call->error);
+ error = htonl(cerror);
call->abortCount++;
packet =
rxi_SendSpecial(call, call->conn, packet, RX_PACKET_TYPE_ABORT,
afs_uint32 fudgeFactor;
int cerror = 0;
int newmtu = 0;
+ int idle_timeout = 0;
#ifdef AFS_GLOBAL_RXLOCK_KERNEL
if (call->flags & RX_CALL_TQ_BUSY) {
* attached process can die reasonably gracefully. */
}
- if (conn->idleDeadTime) {
- idleDeadTime = conn->idleDeadTime + fudgeFactor;
- }
+ if (conn->idleDeadDetection) {
+ if (conn->idleDeadTime) {
+ idleDeadTime = conn->idleDeadTime + fudgeFactor;
+ }
- /* see if we have a non-activity timeout */
- if (call->startWait && idleDeadTime
- && ((call->startWait + idleDeadTime) < now) &&
- (call->flags & RX_CALL_READER_WAIT)) {
- if (call->state == RX_STATE_ACTIVE) {
- cerror = RX_CALL_TIMEOUT;
- goto mtuout;
- }
- }
- if (call->lastSendData && idleDeadTime && (conn->idleDeadErr != 0)
- && ((call->lastSendData + idleDeadTime) < now)) {
- if (call->state == RX_STATE_ACTIVE) {
- cerror = conn->idleDeadErr;
- goto mtuout;
- }
+ if (idleDeadTime) {
+ /* see if we have a non-activity timeout */
+ if (call->startWait && ((call->startWait + idleDeadTime) < now) &&
+ (call->flags & RX_CALL_READER_WAIT)) {
+ if (call->state == RX_STATE_ACTIVE) {
+ cerror = RX_CALL_TIMEOUT;
+ goto mtuout;
+ }
+ }
+
+ if (call->lastSendData && ((call->lastSendData + idleDeadTime) < now)) {
+ if (call->state == RX_STATE_ACTIVE) {
+ cerror = conn->service ? conn->service->idleDeadErr : RX_CALL_IDLE;
+ idle_timeout = 1;
+ goto mtuout;
+ }
+ }
+ }
}
if (conn->hardDeadTime) {
}
return 0;
mtuout:
- if (conn->msgsizeRetryErr && cerror != RX_CALL_TIMEOUT
- && call->lastReceiveTime) {
+ if (conn->msgsizeRetryErr && cerror != RX_CALL_TIMEOUT && !idle_timeout &&
+ call->lastReceiveTime) {
int oldMTU = conn->peer->ifMTU;
/* if we thought we could send more, perhaps things got worse */
*/
if ((conn->peer->maxPacketSize != 0) &&
(conn->peer->natMTU < RX_MAX_PACKET_SIZE) &&
- (conn->idleDeadErr))
+ conn->idleDeadDetection)
(void)rxi_SendAck(call, NULL, 0, RX_ACK_MTU, 0);
rxi_ScheduleGrowMTUEvent(call, 0);
MUTEX_EXIT(&call->lock);
extern int rx_GetSecurityHeaderSize(struct rx_connection *conn);
extern void rx_SetSecurityMaxTrailerSize(struct rx_connection *conn, int size);
extern int rx_GetSecurityMaxTrailerSize(struct rx_connection *conn);
-extern void rx_SetServerConnIdleDeadErr(struct rx_connection *conn, int err);
extern void rx_SetMsgsizeRetryErr(struct rx_connection *conn, int err);
extern int rx_IsServerConn(struct rx_connection *conn);
extern int rx_IsClientConn(struct rx_connection *conn);
/* 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 error to return in server connections when failing to answer.
+ * (server only) For example, AFS viced sends VNOSERVICE.
+ */
#define rx_SetServerIdleDeadErr(service,err) ((service)->idleDeadErr = (err))
/* Define procedures for getting and setting before and after execute-request procs */
/* Enable or disable asymmetric client checking for a service */
#define rx_SetCheckReach(service, x) ((service)->checkReach = (x))
-
/* Set the overload threshold and the overload error */
#define rx_SetBusyThreshold(threshold, code) (rx_BusyThreshold=(threshold),rx_BusyError=(code))
#define RX_CHECKREACH_TIMEOUT 2 /* Number of seconds before another ping is generated */
#define RX_CHECKREACH_TTL 60 /* Re-check reachability this often */
-/* RX error codes. RX uses error codes from -1 to -64. Rxgen may use other error codes < -64; user programs are expected to return positive error codes */
+/*
+ * RX error codes. RX uses error codes from -1 to -64 and -100.
+ * Rxgen uses other error codes < -64 (see src/rxgen/rpc_errors.h);
+ * user programs are expected to return positive error codes
+ */
/* Something bad happened to the connection; temporary loss of communication */
#define RX_CALL_DEAD (-1)
-/* An invalid operation, such as a client attempting to send data after having received the beginning of a reply from the server */
+/*
+ * An invalid operation, such as a client attempting to send data
+ * after having received the beginning of a reply from the server.
+ */
#define RX_INVALID_OPERATION (-2)
/* An optional timeout per call may be specified */
#define RX_CALL_TIMEOUT (-3)
-/* End of data on a read */
+/* End of data on a read. Not currently in use. */
#define RX_EOF (-4)
-/* Some sort of low-level protocol error */
+/* Some sort of low-level protocol error. */
#define RX_PROTOCOL_ERROR (-5)
-/* Generic user abort code; used when no more specific error code needs to be communicated. For example, multi rx clients use this code to abort a multi rx call */
+/*
+ * Generic user abort code; used when no more specific error code needs to be
+ * communicated. For example, multi rx clients use this code to abort a multi-
+ * rx call.
+ */
#define RX_USER_ABORT (-6)
-/* Port already in use (from rx_Init) */
+/* Port already in use (from rx_Init). This error is never sent on the wire. */
#define RX_ADDRINUSE (-7)
/* EMSGSIZE returned from network. Packet too big, must fragment */
#define RX_MSGSIZE (-8)
+/*
+ * Idle dead timeout error. This error is never sent on the wire.
+ * rxi_SendCallAbort() translates RX_CALL_IDLE to RX_CALL_TIMEOUT.
+ */
+#define RX_CALL_IDLE (-9)
+
+/*
+ * Busy call channel error. This error is never sent on the wire.
+ * rxi_SendCallAbort() translates RX_CALL_BUSY to RX_CALL_TIMEOUT.
+ */
+#define RX_CALL_BUSY (-10)
+
/* transient failure detected ( possibly the server is restarting ) */
-/* this shud be equal to VRESTARTING ( util/errors.h ) for old clients to work */
+/* this should be equal to VRESTARTING ( util/errors.h ) for old clients to work */
#define RX_RESTARTING (-100)
typedef enum {
}
void
-rx_SetServerConnIdleDeadErr(struct rx_connection *conn, int err)
-{
- conn->idleDeadErr = err;
-}
-
-void
rx_SetMsgsizeRetryErr(struct rx_connection *conn, int err)
{
conn->msgsizeRetryErr = err;
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;
+ u_char idleDeadDetection; /* detect idle dead timeouts? */
afs_int32 secondsUntilNatPing; /* how often to ping conn */
struct rxevent *natKeepAliveEvent; /* Scheduled to keep connection open */
afs_int32 msgsizeRetryErr;
extern void rx_SetEpoch(afs_uint32 epoch);
extern int rx_Init(u_int port);
extern int rx_InitHost(u_int host, u_int port);
-extern void rx_SetBusyChannelError(afs_int32 error);
+extern void rx_SetBusyChannelError(afs_int32 onoff);
#ifdef AFS_NT40_ENV
extern void rx_DebugOnOff(int on);
extern void rx_StatsOnOff(int on);