lib/iscsi: Request logout to asynchronously to initiator
Request logout to the initiator asynchronously when exiting the running connection from the target. Based on this patch, the next patch will make flushing PDUs possible only when the connection is RUNNING (or INVALID) and remove the tight loop in iscsi_conn_flush_pdus(). Set timeout of logout request as 30 seconds. 30 seconds is as same as NOP timeout and will be reasonable for now. Add and use logout_request_timer to check the timeout. When the connection gets internal a logout request, move the connection to EXITING state if the connection is in INVALID state, request logout to initiator and start 30 seconds timer if the connection is in RUNNING state and logout is not requested yet, or do nothing otherwise. Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Change-Id: I43192be9fd7112ad444152c0dd88f99a14aa8d30 Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/470705 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
parent
7814351539
commit
fe5611b79b
@ -287,6 +287,7 @@ spdk_iscsi_conn_construct(struct spdk_iscsi_portal *portal,
|
||||
SPDK_ERRLOG("iscsi_conn_params_init() failed\n");
|
||||
goto error_return;
|
||||
}
|
||||
conn->logout_request_timer = NULL;
|
||||
conn->logout_timer = NULL;
|
||||
conn->shutdown_timer = NULL;
|
||||
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "Launching connection on acceptor thread\n");
|
||||
@ -639,6 +640,7 @@ _iscsi_conn_destruct(struct spdk_iscsi_conn *conn)
|
||||
|
||||
iscsi_poll_group_remove_conn(conn->pg, conn);
|
||||
spdk_sock_close(&conn->sock);
|
||||
spdk_poller_unregister(&conn->logout_request_timer);
|
||||
spdk_poller_unregister(&conn->logout_timer);
|
||||
|
||||
rc = iscsi_conn_free_tasks(conn);
|
||||
@ -731,8 +733,63 @@ iscsi_conn_check_shutdown(void *arg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_send_logout_request(struct spdk_iscsi_conn *conn)
|
||||
{
|
||||
struct spdk_iscsi_pdu *rsp_pdu;
|
||||
struct iscsi_bhs_async *rsph;
|
||||
|
||||
rsp_pdu = spdk_get_pdu();
|
||||
assert(rsp_pdu != NULL);
|
||||
|
||||
rsph = (struct iscsi_bhs_async *)&rsp_pdu->bhs;
|
||||
rsp_pdu->data = NULL;
|
||||
|
||||
rsph->opcode = ISCSI_OP_ASYNC;
|
||||
to_be32(&rsph->ffffffff, 0xFFFFFFFF);
|
||||
rsph->async_event = 1;
|
||||
to_be16(&rsph->param3, ISCSI_LOGOUT_REQUEST_TIMEOUT);
|
||||
|
||||
to_be32(&rsph->stat_sn, conn->StatSN);
|
||||
to_be32(&rsph->exp_cmd_sn, conn->sess->ExpCmdSN);
|
||||
to_be32(&rsph->max_cmd_sn, conn->sess->MaxCmdSN);
|
||||
|
||||
spdk_iscsi_conn_write_pdu(conn, rsp_pdu);
|
||||
}
|
||||
|
||||
static int
|
||||
logout_request_timeout(void *arg)
|
||||
{
|
||||
struct spdk_iscsi_conn *conn = arg;
|
||||
|
||||
if (conn->state < ISCSI_CONN_STATE_EXITING) {
|
||||
conn->state = ISCSI_CONN_STATE_EXITING;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
iscsi_conn_request_logout(struct spdk_iscsi_conn *conn)
|
||||
{
|
||||
if (conn->state == ISCSI_CONN_STATE_INVALID) {
|
||||
/* Move it to EXITING state if the connection is in login. */
|
||||
conn->state = ISCSI_CONN_STATE_EXITING;
|
||||
} else if (conn->state == ISCSI_CONN_STATE_RUNNING &&
|
||||
conn->logout_request_timer == NULL) {
|
||||
/* If the connection is running and logout is not requested yet,
|
||||
* request logout to initiator and wait for the logout process
|
||||
* to start.
|
||||
*/
|
||||
iscsi_send_logout_request(conn);
|
||||
|
||||
conn->logout_request_timer = spdk_poller_register(logout_request_timeout,
|
||||
conn, ISCSI_LOGOUT_REQUEST_TIMEOUT * 1000000);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
spdk_iscsi_conns_start_exit(struct spdk_iscsi_tgt_node *target)
|
||||
spdk_iscsi_conns_request_logout(struct spdk_iscsi_tgt_node *target)
|
||||
{
|
||||
struct spdk_iscsi_conn *conn;
|
||||
int i;
|
||||
@ -749,12 +806,7 @@ spdk_iscsi_conns_start_exit(struct spdk_iscsi_tgt_node *target)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Do not set conn->state if the connection has already started exiting.
|
||||
* This ensures we do not move a connection from EXITED state back to EXITING.
|
||||
*/
|
||||
if (conn->state < ISCSI_CONN_STATE_EXITING) {
|
||||
conn->state = ISCSI_CONN_STATE_EXITING;
|
||||
}
|
||||
iscsi_conn_request_logout(conn);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&g_conns_mutex);
|
||||
@ -763,7 +815,7 @@ spdk_iscsi_conns_start_exit(struct spdk_iscsi_tgt_node *target)
|
||||
void
|
||||
spdk_shutdown_iscsi_conns(void)
|
||||
{
|
||||
spdk_iscsi_conns_start_exit(NULL);
|
||||
spdk_iscsi_conns_request_logout(NULL);
|
||||
|
||||
g_shutdown_timer = spdk_poller_register(iscsi_conn_check_shutdown, NULL, 1000);
|
||||
}
|
||||
|
@ -94,6 +94,11 @@ struct spdk_iscsi_conn {
|
||||
uint64_t last_fill;
|
||||
uint64_t last_nopin;
|
||||
|
||||
/* Timer used to destroy connection after requesting logout if
|
||||
* initiator does not send logout request.
|
||||
*/
|
||||
struct spdk_poller *logout_request_timer;
|
||||
|
||||
/* Timer used to destroy connection after logout if initiator does
|
||||
* not close the connection.
|
||||
*/
|
||||
@ -174,7 +179,7 @@ extern struct spdk_iscsi_conn *g_conns_array;
|
||||
|
||||
int spdk_initialize_iscsi_conns(void);
|
||||
void spdk_shutdown_iscsi_conns(void);
|
||||
void spdk_iscsi_conns_start_exit(struct spdk_iscsi_tgt_node *target);
|
||||
void spdk_iscsi_conns_request_logout(struct spdk_iscsi_tgt_node *target);
|
||||
int spdk_iscsi_get_active_conns(struct spdk_iscsi_tgt_node *target);
|
||||
|
||||
int spdk_iscsi_conn_construct(struct spdk_iscsi_portal *portal, struct spdk_sock *sock);
|
||||
|
@ -122,6 +122,11 @@
|
||||
*/
|
||||
#define DEFAULT_MAX_QUEUE_DEPTH 64
|
||||
|
||||
/** Defines how long we should wait for a logout request when the target
|
||||
* requests logout to the initiator asynchronously.
|
||||
*/
|
||||
#define ISCSI_LOGOUT_REQUEST_TIMEOUT 30 /* in seconds */
|
||||
|
||||
/** Defines how long we should wait for a TCP close after responding to a
|
||||
* logout request, before terminating the connection ourselves.
|
||||
*/
|
||||
|
@ -689,7 +689,7 @@ iscsi_tgt_node_destruct(struct spdk_iscsi_tgt_node *target,
|
||||
target->destruct_cb_fn = cb_fn;
|
||||
target->destruct_cb_arg = cb_arg;
|
||||
|
||||
spdk_iscsi_conns_start_exit(target);
|
||||
spdk_iscsi_conns_request_logout(target);
|
||||
|
||||
if (spdk_iscsi_get_active_conns(target) != 0) {
|
||||
target->destruct_poller = spdk_poller_register(iscsi_tgt_node_check_active_conns,
|
||||
|
@ -119,7 +119,7 @@ DEFINE_STUB(spdk_scsi_dev_delete_port, int,
|
||||
|
||||
DEFINE_STUB_V(spdk_shutdown_iscsi_conns, (void));
|
||||
|
||||
DEFINE_STUB_V(spdk_iscsi_conns_start_exit, (struct spdk_iscsi_tgt_node *target));
|
||||
DEFINE_STUB_V(spdk_iscsi_conns_request_logout, (struct spdk_iscsi_tgt_node *target));
|
||||
|
||||
DEFINE_STUB(spdk_iscsi_get_active_conns, int, (struct spdk_iscsi_tgt_node *target), 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user