diff --git a/include/iscsi.h b/include/iscsi.h index 7fff12c..664c741 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -400,7 +400,10 @@ EXTERN int iscsi_full_connect_sync(struct iscsi_context *iscsi, const char *port EXTERN int iscsi_disconnect(struct iscsi_context *iscsi); /* - * Disconnect a connection to a target and try to reconnect. + * 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. * * Returns: * 0 reconnect was successful @@ -408,6 +411,16 @@ EXTERN int iscsi_disconnect(struct iscsi_context *iscsi); */ EXTERN int iscsi_reconnect(struct iscsi_context *iscsi); +/* + * Disconnect a connection to a target and try to reconnect (sync version). + * This call will block until the connection is reestablished. + * + * Returns: + * 0 reconnect was successful + * <0 error + */ +EXTERN int iscsi_reconnect_sync(struct iscsi_context *iscsi); + /* * Asynchronous call to perform an ISCSI login. * diff --git a/lib/libiscsi.def b/lib/libiscsi.def index 5d898da..080c142 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -2,6 +2,7 @@ LIBRARY libiscsi EXPORTS iscsi_connect_async iscsi_connect_sync +iscsi_reconnect_sync iscsi_create_context iscsi_destroy_context iscsi_destroy_url diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index b806795..471e06d 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -1,5 +1,6 @@ iscsi_connect_async iscsi_connect_sync +iscsi_reconnect_sync iscsi_create_context iscsi_destroy_context iscsi_destroy_url diff --git a/lib/sync.c b/lib/sync.c index 2e9a39e..d9f929c 100644 --- a/lib/sync.c +++ b/lib/sync.c @@ -167,6 +167,48 @@ int iscsi_logout_sync(struct iscsi_context *iscsi) return state.status; } +static void +reconnect_event_loop(struct iscsi_context *iscsi, struct iscsi_sync_state *state) +{ + struct pollfd pfd; + int ret; + while (iscsi->is_reconnecting) { + pfd.fd = iscsi_get_fd(iscsi); + pfd.events = iscsi_which_events(iscsi); + + if ((ret = poll(&pfd, 1, 1000)) < 0) { + iscsi_set_error(iscsi, "Poll failed"); + state->status = -1; + return; + } + + if (iscsi_service(iscsi, pfd.revents) < 0) { + iscsi_set_error(iscsi, + "iscsi_service failed with : %s", + iscsi_get_error(iscsi)); + state->status = -1; + return; + } + } + state->status = 0; +} + +int iscsi_reconnect_sync(struct iscsi_context *iscsi) +{ + struct iscsi_sync_state state; + + memset(&state, 0, sizeof(state)); + + if (iscsi_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; +} + static void iscsi_task_mgmt_sync_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)