From 30dd7c6429c2e470859a57aec2e7dfaf32a9a060 Mon Sep 17 00:00:00 2001 From: John Levon Date: Mon, 17 Jan 2022 11:21:56 +0000 Subject: [PATCH] add iscsi_force_reconnect() If a connection attempt is hung, then iscsi_reconnect() won't do anything. This makes sense if we'd just re-try to connect to the same target, but if (for example) login redirect might point us to a different, healthy, target, it should be possible to restart the full connection process on request. Signed-off-by: John Levon --- include/iscsi.h | 27 +++++++++++++++++++++++++++ lib/connect.c | 14 ++++++++++++-- lib/libiscsi.def | 4 +++- lib/libiscsi.syms.in | 2 ++ lib/sync.c | 16 ++++++++++++++++ 5 files changed, 60 insertions(+), 3 deletions(-) diff --git a/include/iscsi.h b/include/iscsi.h index 35960a0..2760fc6 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -492,6 +492,33 @@ EXTERN int iscsi_reconnect(struct iscsi_context *iscsi); */ EXTERN int iscsi_reconnect_sync(struct iscsi_context *iscsi); +/* + * Disconnect a connection to a target and try to reconnect (async version). + * This call returns immediately and the reconnect is processed in the + * background. Commands send to this connection will be queued and not + * processed until we have successfully reconnected. + * + * This will re-start connection (to the configured original portal) even if a + * pending reconnection is already underway, which may be useful if the current + * connection is not progressing. It does not over-ride any existing re-try + * backoff or max retries state. + * + * Returns: + * 0 reconnect was successful + * <0 error + */ +EXTERN int iscsi_force_reconnect(struct iscsi_context *iscsi); + +/* + * Disconnect a connection to a target and try to force reconnection (sync + * version). This call will block until the connection is reestablished. + * + * Returns: + * 0 reconnect was successful + * <0 error + */ +EXTERN int iscsi_force_reconnect_sync(struct iscsi_context *iscsi); + /* * Asynchronous call to perform an ISCSI login. * diff --git a/lib/connect.c b/lib/connect.c index 68b6ca2..74b7251 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -378,7 +378,7 @@ void iscsi_reconnect_cb(struct iscsi_context *iscsi, int status, iscsi->pending_reconnect = 0; } -int iscsi_reconnect(struct iscsi_context *iscsi) +static int reconnect(struct iscsi_context *iscsi, int force) { struct iscsi_context *tmp_iscsi; @@ -397,7 +397,7 @@ int iscsi_reconnect(struct iscsi_context *iscsi) return 0; } - if (iscsi->old_iscsi && !iscsi->pending_reconnect) { + if (iscsi->old_iscsi && !iscsi->pending_reconnect && !force) { return 0; } @@ -477,3 +477,13 @@ int iscsi_reconnect(struct iscsi_context *iscsi) return iscsi_full_connect_async(iscsi, iscsi->portal, iscsi->lun, iscsi_reconnect_cb, NULL); } + +int iscsi_reconnect(struct iscsi_context *iscsi) +{ + return reconnect(iscsi, 0); +} + +int iscsi_force_reconnect(struct iscsi_context *iscsi) +{ + return reconnect(iscsi, 1); +} diff --git a/lib/libiscsi.def b/lib/libiscsi.def index 6ca845f..a32be9d 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -2,6 +2,7 @@ LIBRARY libiscsi EXPORTS iscsi_connect_async iscsi_connect_sync +iscsi_force_reconnect_sync iscsi_reconnect_sync iscsi_create_context iscsi_destroy_context @@ -10,6 +11,7 @@ iscsi_disconnect iscsi_discovery_async iscsi_discovery_sync iscsi_free_discovery_data +iscsi_force_reconnect iscsi_full_connect_async iscsi_full_connect_sync iscsi_get_error @@ -283,4 +285,4 @@ scsi_task_set_iov_in scsi_task_set_iov_out scsi_version_to_str scsi_version_descriptor_to_str -win32_poll \ No newline at end of file +win32_poll diff --git a/lib/libiscsi.syms.in b/lib/libiscsi.syms.in index 38d71d2..74b084a 100644 --- a/lib/libiscsi.syms.in +++ b/lib/libiscsi.syms.in @@ -13,6 +13,8 @@ iscsi_discovery_sync iscsi_extended_copy_sync iscsi_extended_copy_task iscsi_free_discovery_data +iscsi_force_reconnect +iscsi_force_reconnect_sync iscsi_full_connect_async iscsi_full_connect_sync iscsi_get_error diff --git a/lib/sync.c b/lib/sync.c index 36ef6f0..62ce32b 100644 --- a/lib/sync.c +++ b/lib/sync.c @@ -226,6 +226,22 @@ int iscsi_reconnect_sync(struct iscsi_context *iscsi) return (state.status == SCSI_STATUS_GOOD) ? 0 : -1; } +int iscsi_force_reconnect_sync(struct iscsi_context *iscsi) +{ + struct iscsi_sync_state state; + + memset(&state, 0, sizeof(state)); + + if (iscsi_force_reconnect(iscsi) != 0) { + iscsi_set_error(iscsi, "Failed to reconnect. %s", iscsi_get_error(iscsi)); + return -1; + } + + reconnect_event_loop(iscsi, &state); + + return (state.status == SCSI_STATUS_GOOD) ? 0 : -1; +} + static void iscsi_task_mgmt_sync_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)