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 <john.levon@nutanix.com>
This commit is contained in:
John Levon
2022-01-17 11:21:56 +00:00
committed by Bart Van Assche
parent 314aa26576
commit 30dd7c6429
5 changed files with 60 additions and 3 deletions
+27
View File
@@ -492,6 +492,33 @@ EXTERN int iscsi_reconnect(struct iscsi_context *iscsi);
*/ */
EXTERN int iscsi_reconnect_sync(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. * Asynchronous call to perform an ISCSI login.
* *
+12 -2
View File
@@ -378,7 +378,7 @@ void iscsi_reconnect_cb(struct iscsi_context *iscsi, int status,
iscsi->pending_reconnect = 0; 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; struct iscsi_context *tmp_iscsi;
@@ -397,7 +397,7 @@ int iscsi_reconnect(struct iscsi_context *iscsi)
return 0; return 0;
} }
if (iscsi->old_iscsi && !iscsi->pending_reconnect) { if (iscsi->old_iscsi && !iscsi->pending_reconnect && !force) {
return 0; return 0;
} }
@@ -477,3 +477,13 @@ int iscsi_reconnect(struct iscsi_context *iscsi)
return iscsi_full_connect_async(iscsi, iscsi->portal, return iscsi_full_connect_async(iscsi, iscsi->portal,
iscsi->lun, iscsi_reconnect_cb, NULL); 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);
}
+3 -1
View File
@@ -2,6 +2,7 @@ LIBRARY libiscsi
EXPORTS EXPORTS
iscsi_connect_async iscsi_connect_async
iscsi_connect_sync iscsi_connect_sync
iscsi_force_reconnect_sync
iscsi_reconnect_sync iscsi_reconnect_sync
iscsi_create_context iscsi_create_context
iscsi_destroy_context iscsi_destroy_context
@@ -10,6 +11,7 @@ iscsi_disconnect
iscsi_discovery_async iscsi_discovery_async
iscsi_discovery_sync iscsi_discovery_sync
iscsi_free_discovery_data iscsi_free_discovery_data
iscsi_force_reconnect
iscsi_full_connect_async iscsi_full_connect_async
iscsi_full_connect_sync iscsi_full_connect_sync
iscsi_get_error iscsi_get_error
@@ -283,4 +285,4 @@ scsi_task_set_iov_in
scsi_task_set_iov_out scsi_task_set_iov_out
scsi_version_to_str scsi_version_to_str
scsi_version_descriptor_to_str scsi_version_descriptor_to_str
win32_poll win32_poll
+2
View File
@@ -13,6 +13,8 @@ iscsi_discovery_sync
iscsi_extended_copy_sync iscsi_extended_copy_sync
iscsi_extended_copy_task iscsi_extended_copy_task
iscsi_free_discovery_data iscsi_free_discovery_data
iscsi_force_reconnect
iscsi_force_reconnect_sync
iscsi_full_connect_async iscsi_full_connect_async
iscsi_full_connect_sync iscsi_full_connect_sync
iscsi_get_error iscsi_get_error
+16
View File
@@ -226,6 +226,22 @@ int iscsi_reconnect_sync(struct iscsi_context *iscsi)
return (state.status == SCSI_STATUS_GOOD) ? 0 : -1; 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 static void
iscsi_task_mgmt_sync_cb(struct iscsi_context *iscsi, int status, iscsi_task_mgmt_sync_cb(struct iscsi_context *iscsi, int status,
void *command_data, void *private_data) void *command_data, void *private_data)