From b104afd497502321765c2c1ed3f020b1fe4b400a Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Mon, 29 Feb 2016 14:13:27 -0800 Subject: [PATCH v2 4/9] iscsi_tcp set SO_LINGER to abort connection for error handling When requests are being failed it's important to abort the TCP connection rather than let TCP wait and attempt a graceful shutdown. That can be accomplished by setting the SO_LINGER socket option with a linger time of 0 to drop queued data and close the connection with a RST instead of a FIN. Signed-off-by: Chris Leech --- usr/io.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/usr/io.c b/usr/io.c index f552e1e..48b233c 100644 --- a/usr/io.c +++ b/usr/io.c @@ -391,9 +391,24 @@ iscsi_io_tcp_poll(iscsi_conn_t *conn, int timeout_ms) void iscsi_io_tcp_disconnect(iscsi_conn_t *conn) { + struct linger so_linger = { .l_onoff = 1, .l_linger = 0 }; + if (conn->socket_fd >= 0) { log_debug(1, "disconnecting conn %p, fd %d", conn, conn->socket_fd); + + /* If the state is not IN_LOGOUT, this isn't a clean shutdown + * and there's some sort of error handling going on. In that + * case, set a 0 SO_LINGER to force an abortive close (RST) and + * free whatever is sitting in the TCP transmit queue. This is + * done to prevent stale data from being sent should the + * network connection be restored before TCP times out. + */ + if (conn->state != ISCSI_CONN_STATE_IN_LOGOUT) { + setsockopt(conn->socket_fd, SOL_SOCKET, SO_LINGER, + &so_linger, sizeof(so_linger)); + } + close(conn->socket_fd); conn->socket_fd = -1; } -- 2.5.5