From 63fd8679fa2dad420489be2dabb41e4d6909f0e3 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Mon, 13 Apr 2015 10:06:32 +0200 Subject: [PATCH 1/5] reconnect: do not queue TESTUNIT_READY cdbs those are part of the login process to consume UNIT_ATTENTIONS. Its questionable if we should consume them at all, but iff we change that behaviour we should do it for the initial login as well as for a reconnect. Signed-off-by: Peter Lieven --- lib/connect.c | 2 +- lib/iscsi-command.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/connect.c b/lib/connect.c index 048f19c..6e19ea2 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -130,7 +130,7 @@ iscsi_login_cb(struct iscsi_context *iscsi, int status, void *command_data _U_, return; } - if (ct->lun != -1 && !iscsi->old_iscsi) { + if (ct->lun != -1) { if (iscsi_testunitready_task(iscsi, ct->lun, iscsi_testunitready_cb, ct) == NULL) { iscsi_set_error(iscsi, "iscsi_testunitready_async failed."); diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c index 493e288..66f442b 100644 --- a/lib/iscsi-command.c +++ b/lib/iscsi-command.c @@ -206,7 +206,8 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun, struct iscsi_pdu *pdu; int flags; - if (iscsi->old_iscsi) { + if (iscsi->old_iscsi && + (iscsi->is_loggedin == 0 || task->cdb[0] != SCSI_OPCODE_TESTUNITREADY)) { iscsi = iscsi->old_iscsi; ISCSI_LOG(iscsi, 2, "iscsi_scsi_command_async: queuing cmd to old_iscsi while reconnecting"); } From a8b33cefaceeb3f76743c83ebdd789a37b934845 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Mon, 13 Apr 2015 10:13:36 +0200 Subject: [PATCH 2/5] drop iscsi->is_reconnecting iscsi->is_reconnecting != 0 is equal to iscsi->old_iscsi != NULL. Signed-off-by: Peter Lieven --- include/iscsi-private.h | 1 - lib/connect.c | 6 +----- lib/socket.c | 6 +++--- lib/sync.c | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 66c4b07..c993e11 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -111,7 +111,6 @@ struct iscsi_context { int secneg_phase; int login_attempts; int is_loggedin; - int is_reconnecting; int bind_interfaces_cnt; int nops_in_flight; diff --git a/lib/connect.c b/lib/connect.c index 6e19ea2..2c485e3 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -344,7 +344,6 @@ static void iscsi_reconnect_cb(struct iscsi_context *iscsi _U_, int status, ISCSI_LOG(iscsi, 2, "reconnect was successful"); iscsi->pending_reconnect = 0; - iscsi->is_reconnecting = 0; } int iscsi_reconnect(struct iscsi_context *old_iscsi) @@ -366,7 +365,7 @@ int iscsi_reconnect(struct iscsi_context *old_iscsi) return 0; } - if (old_iscsi->is_reconnecting && !old_iscsi->pending_reconnect) { + if (old_iscsi->old_iscsi && !old_iscsi->pending_reconnect) { return 0; } @@ -389,9 +388,6 @@ int iscsi_reconnect(struct iscsi_context *old_iscsi) ISCSI_LOG(old_iscsi, 2, "reconnect initiated"); - old_iscsi->is_reconnecting = 1; - iscsi->is_reconnecting = 1; - iscsi_set_targetname(iscsi, old_iscsi->target_name); iscsi_set_header_digest(iscsi, old_iscsi->want_header_digest); diff --git a/lib/socket.c b/lib/socket.c index 0646532..f26cb6a 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -402,7 +402,7 @@ iscsi_which_events(struct iscsi_context *iscsi) { int events = iscsi->is_connected ? POLLIN : POLLOUT; - if (iscsi->pending_reconnect && iscsi->is_reconnecting && + if (iscsi->pending_reconnect && iscsi->old_iscsi && time(NULL) < iscsi->next_reconnect) { return 0; } @@ -779,7 +779,7 @@ iscsi_service_reconnect_if_loggedin(struct iscsi_context *iscsi) return 0; } } - if (iscsi->is_reconnecting) { + if (iscsi->old_iscsi) { return 0; } return -1; @@ -796,7 +796,7 @@ iscsi_service(struct iscsi_context *iscsi, int revents) if (time(NULL) >= iscsi->next_reconnect) { return iscsi_reconnect(iscsi); } else { - if (iscsi->is_reconnecting) { + if (iscsi->old_iscsi) { return 0; } } diff --git a/lib/sync.c b/lib/sync.c index d9f929c..3b42208 100644 --- a/lib/sync.c +++ b/lib/sync.c @@ -172,7 +172,7 @@ reconnect_event_loop(struct iscsi_context *iscsi, struct iscsi_sync_state *state { struct pollfd pfd; int ret; - while (iscsi->is_reconnecting) { + while (iscsi->old_iscsi) { pfd.fd = iscsi_get_fd(iscsi); pfd.events = iscsi_which_events(iscsi); From e219f1bb971b05c365aa82741cdb5fa8b3dc63f0 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Mon, 13 Apr 2015 10:26:28 +0200 Subject: [PATCH 3/5] utils/examples: avoid busy waiting on wait for reconnect Signed-off-by: Peter Lieven --- examples/iscsi-dd.c | 6 ++++++ examples/iscsiclient.c | 1 + lib/sync.c | 6 ++++++ utils/iscsi-ls.c | 32 +++++++++++++++++++------------- utils/iscsi-perf.c | 6 ++++++ 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/examples/iscsi-dd.c b/examples/iscsi-dd.c index 9b12670..998477e 100644 --- a/examples/iscsi-dd.c +++ b/examples/iscsi-dd.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "iscsi.h" #include "scsi-lowlevel.h" @@ -377,6 +378,11 @@ int main(int argc, char *argv[]) pfd[1].fd = iscsi_get_fd(client.dst_iscsi); pfd[1].events = iscsi_which_events(client.dst_iscsi); + if (!pfd[0].events && !pfd[1].events) { + sleep(1); + continue; + } + if (poll(&pfd[0], 2, -1) < 0) { printf("Poll failed"); exit(10); diff --git a/examples/iscsiclient.c b/examples/iscsiclient.c index f89f2b3..2aadf0b 100644 --- a/examples/iscsiclient.c +++ b/examples/iscsiclient.c @@ -47,6 +47,7 @@ WSADATA wsaData; #include #include #include +#include #include "iscsi.h" #include "scsi-lowlevel.h" diff --git a/lib/sync.c b/lib/sync.c index 3b42208..d89ee7d 100644 --- a/lib/sync.c +++ b/lib/sync.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "iscsi.h" #include "iscsi-private.h" #include "scsi-lowlevel.h" @@ -176,6 +177,11 @@ reconnect_event_loop(struct iscsi_context *iscsi, struct iscsi_sync_state *state pfd.fd = iscsi_get_fd(iscsi); pfd.events = iscsi_which_events(iscsi); + if (!pfd.events) { + sleep(1); + continue; + } + if ((ret = poll(&pfd, 1, 1000)) < 0) { iscsi_set_error(iscsi, "Poll failed"); state->status = -1; diff --git a/utils/iscsi-ls.c b/utils/iscsi-ls.c index e4bd93e..3776208 100644 --- a/utils/iscsi-ls.c +++ b/utils/iscsi-ls.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "iscsi.h" #include "scsi-lowlevel.h" @@ -54,21 +55,26 @@ struct client_state { void event_loop(struct iscsi_context *iscsi, struct client_state *state) { - struct pollfd pfd; + struct pollfd pfd; - while (state->finished == 0) { - pfd.fd = iscsi_get_fd(iscsi); - pfd.events = iscsi_which_events(iscsi); + while (state->finished == 0) { + pfd.fd = iscsi_get_fd(iscsi); + pfd.events = iscsi_which_events(iscsi); - if (poll(&pfd, 1, -1) < 0) { - fprintf(stderr, "Poll failed"); - exit(10); - } - if (iscsi_service(iscsi, pfd.revents) < 0) { - fprintf(stderr, "iscsi_service failed with : %s\n", iscsi_get_error(iscsi)); - exit(10); - } - } + if (!pfd.events) { + sleep(1); + continue; + } + + if (poll(&pfd, 1, -1) < 0) { + fprintf(stderr, "Poll failed"); + exit(10); + } + if (iscsi_service(iscsi, pfd.revents) < 0) { + fprintf(stderr, "iscsi_service failed with : %s\n", iscsi_get_error(iscsi)); + exit(10); + } + } } void show_lun(struct iscsi_context *iscsi, int lun) diff --git a/utils/iscsi-perf.c b/utils/iscsi-perf.c index 77ae39b..ed99d18 100644 --- a/utils/iscsi-perf.c +++ b/utils/iscsi-perf.c @@ -395,6 +395,7 @@ int main(int argc, char *argv[]) while (client.in_flight && !client.err_cnt && finished < 2) { pfd[0].fd = iscsi_get_fd(client.iscsi); pfd[0].events = iscsi_which_events(client.iscsi); + if (proc_alarm) { if (iscsi_get_nops_in_flight(client.iscsi) > MAX_NOP_FAILURES) { iscsi_reconnect(client.iscsi); @@ -407,6 +408,11 @@ int main(int argc, char *argv[]) proc_alarm = 0; } + if (!pfd[0].events) { + sleep(1); + continue; + } + if (poll(&pfd[0], 1, -1) < 0) { continue; } From 913b2ab70861f0c42826f5b4112de79a1fbbdf4c Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Mon, 13 Apr 2015 12:08:08 +0200 Subject: [PATCH 4/5] reconnect: avoid deadlock if socker error is received during reconnect If we are reconnecting and the connection is already established we end up looping forever if there is a socket error before we finish the login process. Fix this by invoking the reconnect callback if there is an error and no new reconnect is scheduled. Signed-off-by: Peter Lieven --- include/iscsi-private.h | 3 +++ lib/connect.c | 4 ++-- lib/socket.c | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/iscsi-private.h b/include/iscsi-private.h index c993e11..17322d8 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -367,6 +367,9 @@ uint32_t iscsi_itt_post_increment(struct iscsi_context *iscsi); void iscsi_timeout_scan(struct iscsi_context *iscsi); +void iscsi_reconnect_cb(struct iscsi_context *iscsi _U_, int status, + void *command_data, void *private_data); + #ifdef __cplusplus } #endif diff --git a/lib/connect.c b/lib/connect.c index 2c485e3..a4354d1 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -249,8 +249,8 @@ void iscsi_defer_reconnect(struct iscsi_context *iscsi) } } -static void iscsi_reconnect_cb(struct iscsi_context *iscsi _U_, int status, - void *command_data _U_, void *private_data _U_) +void iscsi_reconnect_cb(struct iscsi_context *iscsi _U_, int status, + void *command_data _U_, void *private_data _U_) { int i; if (status != SCSI_STATUS_GOOD) { diff --git a/lib/socket.c b/lib/socket.c index f26cb6a..5e76055 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -780,6 +780,9 @@ iscsi_service_reconnect_if_loggedin(struct iscsi_context *iscsi) } } if (iscsi->old_iscsi) { + if (!iscsi->pending_reconnect) { + iscsi_reconnect_cb(iscsi, SCSI_STATUS_ERROR, NULL, NULL); + } return 0; } return -1; From 2858cb54837064ee58c8909aa80691d81d7830e3 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Mon, 13 Apr 2015 14:34:23 +0200 Subject: [PATCH 5/5] NOP: copy the LUN from target NOP-In to NOP-Out Signed-off-by: Peter Lieven --- include/iscsi-private.h | 2 +- lib/nop.c | 8 ++++---- lib/pdu.c | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/iscsi-private.h b/include/iscsi-private.h index 17322d8..9d50d6a 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -316,7 +316,7 @@ int iscsi_process_r2t(struct iscsi_context *iscsi, struct iscsi_pdu *pdu, struct iscsi_in_pdu *in); int iscsi_process_reject(struct iscsi_context *iscsi, struct iscsi_in_pdu *in); -int iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt); +int iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt, uint32_t lun); #if defined(WIN32) void iscsi_set_error(struct iscsi_context *iscsi, const char *error_string, diff --git a/lib/nop.c b/lib/nop.c index af7a2a6..80ac12f 100644 --- a/lib/nop.c +++ b/lib/nop.c @@ -91,7 +91,7 @@ iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb, } int -iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt) +iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt, uint32_t lun) { struct iscsi_pdu *pdu; @@ -115,7 +115,7 @@ iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt) iscsi_pdu_set_ttt(pdu, ttt); /* lun */ - iscsi_pdu_set_lun(pdu, 0); + iscsi_pdu_set_lun(pdu, lun); /* cmdsn is not increased if Immediate delivery*/ iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn); @@ -127,8 +127,8 @@ iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt) } ISCSI_LOG(iscsi, (iscsi->nops_in_flight > 1) ? 1 : 6, - "NOP Out Send (nops_in_flight: %d, pdu->cmdsn %08x, pdu->itt %08x, pdu->ttt %08x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x)", - iscsi->nops_in_flight, pdu->cmdsn, 0xffffffff, ttt, iscsi->maxcmdsn, iscsi->expcmdsn); + "NOP Out Send (nops_in_flight: %d, pdu->cmdsn %08x, pdu->itt %08x, pdu->ttt %08x, pdu->lun %8x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x)", + iscsi->nops_in_flight, pdu->cmdsn, 0xffffffff, ttt, lun, iscsi->maxcmdsn, iscsi->expcmdsn); return 0; } diff --git a/lib/pdu.c b/lib/pdu.c index 383db20..f0e8491 100644 --- a/lib/pdu.c +++ b/lib/pdu.c @@ -321,12 +321,13 @@ int iscsi_process_target_nop_in(struct iscsi_context *iscsi, { uint32_t ttt = scsi_get_uint32(&in->hdr[20]); uint32_t itt = scsi_get_uint32(&in->hdr[16]); + uint32_t lun = scsi_get_uint16(&in->hdr[8]); iscsi_adjust_statsn(iscsi, in); iscsi_adjust_maxexpcmdsn(iscsi, in); ISCSI_LOG(iscsi, (iscsi->nops_in_flight > 1) ? 1 : 6, - "NOP-In received (pdu->itt %08x, pdu->ttt %08x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x, iscsi->statsn %08x)", + "NOP-In received (pdu->itt %08x, pdu->ttt %08x, pdu->lun %8x, iscsi->maxcmdsn %08x, iscsi->expcmdsn %08x, iscsi->statsn %08x)", itt, ttt, iscsi->maxcmdsn, iscsi->expcmdsn, iscsi->statsn); /* if the server does not want a response */ @@ -334,7 +335,7 @@ int iscsi_process_target_nop_in(struct iscsi_context *iscsi, return 0; } - iscsi_send_target_nop_out(iscsi, ttt); + iscsi_send_target_nop_out(iscsi, ttt, lun); return 0; } @@ -671,8 +672,7 @@ iscsi_pdu_set_cdb(struct iscsi_pdu *pdu, struct scsi_task *task) void iscsi_pdu_set_lun(struct iscsi_pdu *pdu, uint32_t lun) { - pdu->outdata.data[8] = lun >> 8; - pdu->outdata.data[9] = lun & 0xff; + scsi_set_uint16(&pdu->outdata.data[8], lun); } void