Add iscsi_tcp_set_user_timeout function
This patch adds a user configurable option to set the TCP_USER_TIMEOUT socket option. With this timeout set a broken TCP session is shutdown after a given timeout even there are unacked packets. SO_KEEPALIVE seems not to work in this case.
This commit is contained in:
@@ -85,6 +85,8 @@ struct iscsi_context {
|
|||||||
int fd;
|
int fd;
|
||||||
int is_connected;
|
int is_connected;
|
||||||
|
|
||||||
|
int tcp_user_timeout;
|
||||||
|
|
||||||
int current_phase;
|
int current_phase;
|
||||||
int next_phase;
|
int next_phase;
|
||||||
#define ISCSI_LOGIN_SECNEG_PHASE_OFFER_CHAP 0
|
#define ISCSI_LOGIN_SECNEG_PHASE_OFFER_CHAP 0
|
||||||
|
|||||||
@@ -967,6 +967,13 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi);
|
|||||||
EXTERN void
|
EXTERN void
|
||||||
iscsi_set_debug(struct iscsi_context *iscsi, int level);
|
iscsi_set_debug(struct iscsi_context *iscsi, int level);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is to set the TCP_USER_TIMEOUT option. It has to be called after iscsi
|
||||||
|
* context creation. The value given in ms is then applied each time a new socket is created.
|
||||||
|
*/
|
||||||
|
EXTERN void
|
||||||
|
iscsi_set_tcp_user_timeout(struct iscsi_context *iscsi, int timeout_ms);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -230,6 +230,8 @@ try_again:
|
|||||||
|
|
||||||
iscsi->debug = old_iscsi->debug;
|
iscsi->debug = old_iscsi->debug;
|
||||||
|
|
||||||
|
iscsi->tcp_user_timeout = old_iscsi->tcp_user_timeout;
|
||||||
|
|
||||||
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);
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ iscsi_set_isid_reserved
|
|||||||
iscsi_set_session_type
|
iscsi_set_session_type
|
||||||
iscsi_set_targetname
|
iscsi_set_targetname
|
||||||
iscsi_set_tcp_keepalive
|
iscsi_set_tcp_keepalive
|
||||||
|
iscsi_set_tcp_user_timeout
|
||||||
iscsi_startstopunit_sync
|
iscsi_startstopunit_sync
|
||||||
iscsi_startstopunit_task
|
iscsi_startstopunit_task
|
||||||
iscsi_synchronizecache10_sync
|
iscsi_synchronizecache10_sync
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ iscsi_set_isid_reserved
|
|||||||
iscsi_set_session_type
|
iscsi_set_session_type
|
||||||
iscsi_set_targetname
|
iscsi_set_targetname
|
||||||
iscsi_set_tcp_keepalive
|
iscsi_set_tcp_keepalive
|
||||||
|
iscsi_set_tcp_user_timeout
|
||||||
iscsi_startstopunit_sync
|
iscsi_startstopunit_sync
|
||||||
iscsi_startstopunit_task
|
iscsi_startstopunit_task
|
||||||
iscsi_synchronizecache10_sync
|
iscsi_synchronizecache10_sync
|
||||||
|
|||||||
47
lib/socket.c
47
lib/socket.c
@@ -159,7 +159,14 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
|
|||||||
iscsi->connect_data = private_data;
|
iscsi->connect_data = private_data;
|
||||||
|
|
||||||
set_nonblocking(iscsi->fd);
|
set_nonblocking(iscsi->fd);
|
||||||
iscsi_set_tcp_keepalive(iscsi, 30, 3, 30);
|
|
||||||
|
if (iscsi->tcp_user_timeout > 0) {
|
||||||
|
set_tcp_user_timeout(iscsi);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iscsi_set_tcp_keepalive(iscsi, 30, 3, 30);
|
||||||
|
}
|
||||||
|
|
||||||
if (connect(iscsi->fd, ai->ai_addr, socksize) != 0
|
if (connect(iscsi->fd, ai->ai_addr, socksize) != 0
|
||||||
&& errno != EINPROGRESS) {
|
&& errno != EINPROGRESS) {
|
||||||
@@ -524,6 +531,40 @@ iscsi_free_iscsi_inqueue(struct iscsi_in_pdu *inqueue)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef TCP_USER_TIMEOUT
|
||||||
|
#define TCP_USER_TIMEOUT 18
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int set_tcp_user_timeout(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_user_timeout;
|
||||||
|
if (setsockopt(iscsi->fd, level, TCP_USER_TIMEOUT, &value, sizeof(value)) != 0) {
|
||||||
|
iscsi_set_error(iscsi, "TCP: Failed to set tcp user timeout. Error %s(%d)", strerror(errno), errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
DPRINTF(iscsi,3,"TCP_USER_TIMEOUT set to %d",value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iscsi_set_tcp_user_timeout(struct iscsi_context *iscsi, int timeout_ms)
|
||||||
|
{
|
||||||
|
iscsi->tcp_user_timeout=timeout_ms;
|
||||||
|
DPRINTF(iscsi,2,"TCP_USER_TIMEOUT will be set to %dms on next socket creation",timeout_ms);
|
||||||
|
}
|
||||||
|
|
||||||
int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, int interval)
|
int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, int interval)
|
||||||
{
|
{
|
||||||
int level, value;
|
int level, value;
|
||||||
@@ -544,6 +585,7 @@ int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, in
|
|||||||
iscsi_set_error(iscsi, "TCP: Failed to set socket option SO_KEEPALIVE. Error %s(%d)", strerror(errno), errno);
|
iscsi_set_error(iscsi, "TCP: Failed to set socket option SO_KEEPALIVE. Error %s(%d)", strerror(errno), errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
DPRINTF(iscsi,3,"SO_KEEPALIVE set to %d",value);
|
||||||
#endif
|
#endif
|
||||||
#ifdef TCP_KEEPCNT
|
#ifdef TCP_KEEPCNT
|
||||||
value = count;
|
value = count;
|
||||||
@@ -551,6 +593,7 @@ int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, in
|
|||||||
iscsi_set_error(iscsi, "TCP: Failed to set tcp keepalive count. Error %s(%d)", strerror(errno), errno);
|
iscsi_set_error(iscsi, "TCP: Failed to set tcp keepalive count. Error %s(%d)", strerror(errno), errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
DPRINTF(iscsi,3,"TCP_KEEPCNT set to %d",value);
|
||||||
#endif
|
#endif
|
||||||
#ifdef TCP_KEEPINTVL
|
#ifdef TCP_KEEPINTVL
|
||||||
value = interval;
|
value = interval;
|
||||||
@@ -558,6 +601,7 @@ int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, in
|
|||||||
iscsi_set_error(iscsi, "TCP: Failed to set tcp keepalive interval. Error %s(%d)", strerror(errno), errno);
|
iscsi_set_error(iscsi, "TCP: Failed to set tcp keepalive interval. Error %s(%d)", strerror(errno), errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
DPRINTF(iscsi,3,"TCP_KEEPINTVL set to %d",value);
|
||||||
#endif
|
#endif
|
||||||
#ifdef TCP_KEEPIDLE
|
#ifdef TCP_KEEPIDLE
|
||||||
value = idle;
|
value = idle;
|
||||||
@@ -565,6 +609,7 @@ int iscsi_set_tcp_keepalive(struct iscsi_context *iscsi, int idle, int count, in
|
|||||||
iscsi_set_error(iscsi, "TCP: Failed to set tcp keepalive idle. Error %s(%d)", strerror(errno), errno);
|
iscsi_set_error(iscsi, "TCP: Failed to set tcp keepalive idle. Error %s(%d)", strerror(errno), errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
DPRINTF(iscsi,3,"TCP_KEEPIDLE set to %d",value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user