From 5532325042e37e44bbb5419ce42c35af776a58d5 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 15 Dec 2015 21:55:03 -0800 Subject: [PATCH] Test-tool: call iscsi_service on MP devices once every second so we respond to NOP The test tool is simplistic and uses the synchronous API. In this API we will only poll() the socket and process events during the lifetime of any iscsi_*_sync() calls. A problem with this approach arises with multipath tests. When iscsi-test-cu is used with multiple devices we will first open a session for each multipath leg, but then as most tests are only using the first device we end up with creating secondary sessions we don't do any iscsi_*_sync() calls on for very long times. If a target is set up to send NOPs on these secondary paths it will not get any responses and eventually tear down the connection. To avoid this, try to make sure we service any secondary paths we have created by calling iscsi_service(POLLIN|POLLOUT) every few seconds to make sure we do service and respond to any NOPs. Signed-off-by: Ronnie Sahlberg --- test-tool/iscsi-support.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test-tool/iscsi-support.c b/test-tool/iscsi-support.c index 51a4fd8..3c7a89d 100644 --- a/test-tool/iscsi-support.c +++ b/test-tool/iscsi-support.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef HAVE_SG_IO #include @@ -46,6 +47,7 @@ #include "scsi-lowlevel.h" #include "iscsi-private.h" #include "iscsi-support.h" +#include "iscsi-multipath.h" /***************************************************************** @@ -269,7 +271,11 @@ static size_t iov_tot_len(struct scsi_iovec *iov, int niov) static struct scsi_task *send_scsi_command(struct scsi_device *sdev, struct scsi_task *task, struct iscsi_data *d) { + static time_t last_time = 0; + if (sdev->iscsi_url) { + time_t current_time = time(NULL); + if (sdev->error_str != NULL) { free(discard_const(sdev->error_str)); sdev->error_str = NULL; @@ -279,6 +285,22 @@ static struct scsi_task *send_scsi_command(struct scsi_device *sdev, struct scsi sdev->error_str = strdup(iscsi_get_error(sdev->iscsi_ctx)); } + if (current_time > last_time + 1) { + int i; + + /* Device [0] is where we are doing all the I/O + * so it will always work the socket and respond + * to NOPs from the target. + * But we need to trigger a service event every + * now and then on all the other devices to ensure that + * we detect and respond to any NOPs. + */ + for (i = 1; i < mp_num_sds; i++) { + iscsi_service(mp_sds[i]->iscsi_ctx, POLLIN|POLLOUT); + } + last_time = current_time; + } + return task; }