Commit fe5611b7 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Changpeng Liu
Browse files

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: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: I43192be9fd7112ad444152c0dd88f99a14aa8d30
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/470705


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
parent 78143515
Loading
Loading
Loading
Loading
+60 −8
Original line number Diff line number Diff line
@@ -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);
}
+6 −1
Original line number Diff line number Diff line
@@ -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);
+5 −0
Original line number Diff line number Diff line
@@ -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.
 */
+1 −1
Original line number Diff line number Diff line
@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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);