Add iscsi_set_tcp_syncnt function
This patch adds support for setting TCP_SYNCNT to overwrite the system default values. This allows indirect support for a configurable connect timeout. Linux uses a exponential backoff for SYN retries starting with 1 second. This means for a value n for TCP_SYNCNT, the connect will effectively timeout after 2^(n+1)-1 seconds.
This commit is contained in:
@@ -89,6 +89,7 @@ struct iscsi_context {
|
|||||||
int tcp_keepcnt;
|
int tcp_keepcnt;
|
||||||
int tcp_keepintvl;
|
int tcp_keepintvl;
|
||||||
int tcp_keepidle;
|
int tcp_keepidle;
|
||||||
|
int tcp_syncnt;
|
||||||
|
|
||||||
int current_phase;
|
int current_phase;
|
||||||
int next_phase;
|
int next_phase;
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ try_again:
|
|||||||
iscsi->tcp_keepidle = old_iscsi->tcp_keepidle;
|
iscsi->tcp_keepidle = old_iscsi->tcp_keepidle;
|
||||||
iscsi->tcp_keepcnt = old_iscsi->tcp_keepcnt;
|
iscsi->tcp_keepcnt = old_iscsi->tcp_keepcnt;
|
||||||
iscsi->tcp_keepintvl = old_iscsi->tcp_keepintvl;
|
iscsi->tcp_keepintvl = old_iscsi->tcp_keepintvl;
|
||||||
|
iscsi->tcp_syncnt = old_iscsi->tcp_syncnt;
|
||||||
|
|
||||||
if (iscsi_full_connect_sync(iscsi, iscsi->portal, iscsi->lun) != 0) {
|
if (iscsi_full_connect_sync(iscsi, iscsi->portal, iscsi->lun) != 0) {
|
||||||
iscsi_destroy_context(iscsi);
|
iscsi_destroy_context(iscsi);
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ iscsi_create_context(const char *initiator_name)
|
|||||||
iscsi->tcp_keepintvl=30;
|
iscsi->tcp_keepintvl=30;
|
||||||
iscsi->tcp_keepidle=30;
|
iscsi->tcp_keepidle=30;
|
||||||
|
|
||||||
|
if (getenv("LIBISCSI_DEBUG") != NULL) {
|
||||||
|
iscsi_set_debug(iscsi,atoi(getenv("LIBISCSI_DEBUG")));
|
||||||
|
}
|
||||||
|
|
||||||
if (getenv("LIBISCSI_TCP_USER_TIMEOUT") != NULL) {
|
if (getenv("LIBISCSI_TCP_USER_TIMEOUT") != NULL) {
|
||||||
iscsi_set_tcp_user_timeout(iscsi,atoi(getenv("LIBISCSI_TCP_USER_TIMEOUT")));
|
iscsi_set_tcp_user_timeout(iscsi,atoi(getenv("LIBISCSI_TCP_USER_TIMEOUT")));
|
||||||
}
|
}
|
||||||
@@ -91,8 +95,8 @@ iscsi_create_context(const char *initiator_name)
|
|||||||
iscsi_set_tcp_keepidle(iscsi,atoi(getenv("LIBISCSI_TCP_KEEPIDLE")));
|
iscsi_set_tcp_keepidle(iscsi,atoi(getenv("LIBISCSI_TCP_KEEPIDLE")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getenv("LIBISCSI_DEBUG") != NULL) {
|
if (getenv("LIBISCSI_TCP_SYNCNT") != NULL) {
|
||||||
iscsi_set_debug(iscsi,atoi(getenv("LIBISCSI_DEBUG")));
|
iscsi_set_tcp_syncnt(iscsi,atoi(getenv("LIBISCSI_TCP_SYNCNT")));
|
||||||
}
|
}
|
||||||
|
|
||||||
return iscsi;
|
return iscsi;
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ iscsi_set_tcp_user_timeout
|
|||||||
iscsi_set_tcp_keepidle
|
iscsi_set_tcp_keepidle
|
||||||
iscsi_set_tcp_keepcnt
|
iscsi_set_tcp_keepcnt
|
||||||
iscsi_set_tcp_keepintvl
|
iscsi_set_tcp_keepintvl
|
||||||
|
iscsi_set_tcp_syncnt
|
||||||
iscsi_startstopunit_sync
|
iscsi_startstopunit_sync
|
||||||
iscsi_startstopunit_task
|
iscsi_startstopunit_task
|
||||||
iscsi_synchronizecache10_sync
|
iscsi_synchronizecache10_sync
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ iscsi_set_tcp_user_timeout
|
|||||||
iscsi_set_tcp_keepidle
|
iscsi_set_tcp_keepidle
|
||||||
iscsi_set_tcp_keepcnt
|
iscsi_set_tcp_keepcnt
|
||||||
iscsi_set_tcp_keepintvl
|
iscsi_set_tcp_keepintvl
|
||||||
|
iscsi_set_tcp_syncnt
|
||||||
iscsi_startstopunit_sync
|
iscsi_startstopunit_sync
|
||||||
iscsi_startstopunit_task
|
iscsi_startstopunit_task
|
||||||
iscsi_synchronizecache10_sync
|
iscsi_synchronizecache10_sync
|
||||||
|
|||||||
42
lib/socket.c
42
lib/socket.c
@@ -86,6 +86,34 @@ int set_tcp_user_timeout(struct iscsi_context *iscsi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TCP_SYNCNT
|
||||||
|
#define TCP_SYNCNT 7
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int set_tcp_syncnt(struct iscsi_context *iscsi)
|
||||||
|
{
|
||||||
|
int level, value;
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__sun)
|
||||||
|
struct protoent *buf;
|
||||||
|
|
||||||
|
if ((buf = getprotobyname("tcp")) != NULL)
|
||||||
|
level = buf->p_proto;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
level = SOL_TCP;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
value = iscsi->tcp_syncnt;
|
||||||
|
if (setsockopt(iscsi->fd, level, TCP_SYNCNT, &value, sizeof(value)) != 0) {
|
||||||
|
iscsi_set_error(iscsi, "TCP: Failed to set tcp syn retries. Error %s(%d)", strerror(errno), errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
DPRINTF(iscsi,3,"TCP_SYNCNT set to %d",value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
|
iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
|
||||||
iscsi_command_cb cb, void *private_data)
|
iscsi_command_cb cb, void *private_data)
|
||||||
@@ -194,6 +222,10 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
|
|||||||
set_tcp_user_timeout(iscsi);
|
set_tcp_user_timeout(iscsi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iscsi->tcp_syncnt > 0) {
|
||||||
|
set_tcp_syncnt(iscsi);
|
||||||
|
}
|
||||||
|
|
||||||
if (connect(iscsi->fd, ai->ai_addr, socksize) != 0
|
if (connect(iscsi->fd, ai->ai_addr, socksize) != 0
|
||||||
&& errno != EINPROGRESS) {
|
&& errno != EINPROGRESS) {
|
||||||
iscsi_set_error(iscsi, "Connect failed with errno : "
|
iscsi_set_error(iscsi, "Connect failed with errno : "
|
||||||
@@ -461,7 +493,7 @@ iscsi_service(struct iscsi_context *iscsi, int revents)
|
|||||||
if (iscsi->is_connected == 0 && iscsi->fd != -1 && revents&POLLOUT) {
|
if (iscsi->is_connected == 0 && iscsi->fd != -1 && revents&POLLOUT) {
|
||||||
int err = 0;
|
int err = 0;
|
||||||
socklen_t err_size = sizeof(err);
|
socklen_t err_size = sizeof(err);
|
||||||
|
DPRINTF(iscsi,3,"inside iscsi service is_connected=0");
|
||||||
if (getsockopt(iscsi->fd, SOL_SOCKET, SO_ERROR,
|
if (getsockopt(iscsi->fd, SOL_SOCKET, SO_ERROR,
|
||||||
&err, &err_size) != 0 || err != 0) {
|
&err, &err_size) != 0 || err != 0) {
|
||||||
if (err == 0) {
|
if (err == 0) {
|
||||||
@@ -480,6 +512,8 @@ iscsi_service(struct iscsi_context *iscsi, int revents)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPRINTF(iscsi,2,"connection to %s established",iscsi->connected_portal);
|
||||||
|
|
||||||
iscsi->is_connected = 1;
|
iscsi->is_connected = 1;
|
||||||
iscsi->socket_status_cb(iscsi, SCSI_STATUS_GOOD, NULL,
|
iscsi->socket_status_cb(iscsi, SCSI_STATUS_GOOD, NULL,
|
||||||
iscsi->connect_data);
|
iscsi->connect_data);
|
||||||
@@ -557,6 +591,12 @@ iscsi_free_iscsi_inqueue(struct iscsi_in_pdu *inqueue)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void iscsi_set_tcp_syncnt(struct iscsi_context *iscsi, int value)
|
||||||
|
{
|
||||||
|
iscsi->tcp_syncnt=value;
|
||||||
|
DPRINTF(iscsi,2,"TCP_SYNCNT will be set to %d on next socket creation",value);
|
||||||
|
}
|
||||||
|
|
||||||
void iscsi_set_tcp_user_timeout(struct iscsi_context *iscsi, int timeout_ms)
|
void iscsi_set_tcp_user_timeout(struct iscsi_context *iscsi, int timeout_ms)
|
||||||
{
|
{
|
||||||
iscsi->tcp_user_timeout=timeout_ms;
|
iscsi->tcp_user_timeout=timeout_ms;
|
||||||
|
|||||||
Reference in New Issue
Block a user