From 0407cf6aed5e7acf0d99afaa9ce5d5179a8986cc Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 15 Dec 2015 21:17:50 -0800 Subject: [PATCH] Fail pending LOGOUT commands on session reconnect Certain iSCSI commands such as NOP and LOGOUT commands are discarded instead of re-queued when we have a session failure and reconnect. Change the LOGOUT command to instead fail with SCSI_STATUS_ERROR when this happens. Otherwise, IF we are in iscsi_logout_sync() and we get a session failure at the same-ish time we may end up automatically re-connecting the session, but since we have discarded the logout command we will never get a reply and will hang indefinitely in the event loop for synchronous commands. Arguably, we could also just return SCSI_STATUS_GOOD here since when we perform a logout, we probably don't care too much about how we disconnected from the server, only that we did disconnect from the server. That is academic anyway since this only affects the sync API which is only meant for trivial applications, which will likely not inspect the result and just do a: ... iscsi_logout_sync() iscsi_destroy_context() ... anyway. Signed-off-by: Ronnie Sahlberg --- include/iscsi-private.h | 2 ++ lib/connect.c | 12 ++++++++++++ lib/login.c | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 77425b0..1d0f263 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -233,6 +233,8 @@ struct iscsi_pdu { #define ISCSI_PDU_DROP_ON_RECONNECT 0x00000004 /* stop sending after this PDU has been sent */ #define ISCSI_PDU_CORK_WHEN_SENT 0x00000008 +/* Fail the command with error on reconnect */ +#define ISCSI_PDU_ERROR_ON_RECONNECT 0x00000016 uint32_t flags; diff --git a/lib/connect.c b/lib/connect.c index a1bc505..fd7dcb8 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -336,6 +336,18 @@ void iscsi_reconnect_cb(struct iscsi_context *iscsi _U_, int status, continue; } + if (pdu->flags & ISCSI_PDU_ERROR_ON_RECONNECT) { + /* + * We only want to re-queue SCSI COMMAND PDUs. + * All other PDUs are discarded at this point. + * This includes DATA-OUT, NOP and task management. + */ + pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL, + pdu->private_data); + iscsi_free_pdu(old_iscsi, pdu); + continue; + } + if (pdu->flags & ISCSI_PDU_DROP_ON_RECONNECT) { /* * We only want to re-queue SCSI COMMAND PDUs. diff --git a/lib/login.c b/lib/login.c index b37d174..5033ac9 100644 --- a/lib/login.c +++ b/lib/login.c @@ -1266,7 +1266,7 @@ iscsi_logout_async(struct iscsi_context *iscsi, iscsi_command_cb cb, ISCSI_PDU_LOGOUT_REQUEST, ISCSI_PDU_LOGOUT_RESPONSE, iscsi_itt_post_increment(iscsi), - ISCSI_PDU_DROP_ON_RECONNECT|ISCSI_PDU_CORK_WHEN_SENT); + ISCSI_PDU_ERROR_ON_RECONNECT|ISCSI_PDU_CORK_WHEN_SENT); if (pdu == NULL) { iscsi_set_error(iscsi, "Out-of-memory: Failed to allocate " "logout pdu.");