From b9dd210194b027b5f6e940c5a34b8013274bbd58 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Wed, 3 Jun 2015 16:47:36 +0200 Subject: [PATCH] test/multipath: add logical unit reset test This test issues a logical unit reset iSCSI TMF request, and then confirms that all paths report a subsequent unit attention condition. Signed-off-by: David Disseldorp --- test-tool/Makefile.am | 3 +- test-tool/iscsi-test-cu.c | 1 + test-tool/iscsi-test-cu.h | 1 + test-tool/test_multipathio_reset.c | 102 +++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 test-tool/test_multipathio_reset.c diff --git a/test-tool/Makefile.am b/test-tool/Makefile.am index 1745685..fceda37 100644 --- a/test-tool/Makefile.am +++ b/test-tool/Makefile.am @@ -215,7 +215,8 @@ iscsi_test_cu_SOURCES = iscsi-test-cu.c \ test_writeverify16_flags.c \ test_writeverify16_dpo.c \ test_writeverify16_residuals.c \ - test_multipathio_simple.c + test_multipathio_simple.c \ + test_multipathio_reset.c endif diff --git a/test-tool/iscsi-test-cu.c b/test-tool/iscsi-test-cu.c index c290c95..d3dcbf6 100644 --- a/test-tool/iscsi-test-cu.c +++ b/test-tool/iscsi-test-cu.c @@ -445,6 +445,7 @@ static CU_TestInfo tests_writeverify16[] = { static CU_TestInfo tests_multipathio[] = { { (char *)"Simple", test_multipathio_simple }, + { (char *)"Reset", test_multipathio_reset }, CU_TEST_INFO_NULL }; diff --git a/test-tool/iscsi-test-cu.h b/test-tool/iscsi-test-cu.h index 3550a93..eb13703 100644 --- a/test-tool/iscsi-test-cu.h +++ b/test-tool/iscsi-test-cu.h @@ -301,5 +301,6 @@ void test_writeverify16_dpo(void); void test_writeverify16_residuals(void); void test_multipathio_simple(void); +void test_multipathio_reset(void); #endif /* _ISCSI_TEST_CU_H_ */ diff --git a/test-tool/test_multipathio_reset.c b/test-tool/test_multipathio_reset.c new file mode 100644 index 0000000..e7b78ad --- /dev/null +++ b/test-tool/test_multipathio_reset.c @@ -0,0 +1,102 @@ +/* + Copyright (C) 2013 Ronnie Sahlberg + Copyright (C) 2015 David Disseldorp + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include +#include + +#include + +#include "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-support.h" +#include "iscsi-test-cu.h" +#include "iscsi-multipath.h" + +#define MPATH_MAX_TUR_RETRIES 5 + +static int +test_iscsi_tur_until_good(struct scsi_device *iscsi_sd, + int *num_uas) +{ + int num_turs; + + *num_uas = 0; + for (num_turs = 0; num_turs < MPATH_MAX_TUR_RETRIES; num_turs++) { + struct scsi_task *tsk; + tsk = iscsi_testunitready_sync(iscsi_sd->iscsi_ctx, + iscsi_sd->iscsi_lun); + if (tsk->status == SCSI_STATUS_GOOD) { + logging(LOG_VERBOSE, "TUR good after %d retries", + num_turs); + return 0; + } else if ((tsk->status == SCSI_STATUS_CHECK_CONDITION) + && (tsk->sense.key == SCSI_SENSE_UNIT_ATTENTION)) { + logging(LOG_VERBOSE, "Got UA for TUR"); + (*num_uas)++; + } else { + logging(LOG_NORMAL, "unexpected non-UA failure: %d,%d", + tsk->status, tsk->sense.key); + } + } + + return -ETIMEDOUT; +} + +void +test_multipathio_reset(void) +{ + int reset_path; + + CHECK_FOR_DATALOSS; + CHECK_FOR_SBC; + MPATH_SKIP_IF_UNAVAILABLE(mp_sds, mp_num_sds); + MPATH_SKIP_UNLESS_ISCSI(mp_sds, mp_num_sds); + + logging(LOG_VERBOSE, LOG_BLANK_LINE); + + for (reset_path = 0; reset_path < mp_num_sds; reset_path++) { + int num_uas; + int ret; + int tur_path; + struct scsi_device *reset_sd = mp_sds[reset_path]; + + logging(LOG_VERBOSE, "Awaiting good TUR"); + ret = test_iscsi_tur_until_good(reset_sd, &num_uas); + CU_ASSERT_EQUAL(ret, 0); + + logging(LOG_VERBOSE, + "Test multipath LUN Reset using path %d", reset_path); + + ret = iscsi_task_mgmt_lun_reset_sync(reset_sd->iscsi_ctx, + reset_sd->iscsi_lun); + if (ret != 0) { + logging(LOG_NORMAL, "LUN reset failed. %s", + iscsi_get_error(reset_sd->iscsi_ctx)); + } + CU_ASSERT_EQUAL(ret, 0); + + /* check for and clear LU reset UA on all paths */ + for (tur_path = 0; tur_path < mp_num_sds; tur_path++) { + logging(LOG_VERBOSE, "check for LU reset unit " + "attention via TUR on path %d", tur_path); + ret = test_iscsi_tur_until_good(mp_sds[tur_path], &num_uas); + CU_ASSERT_EQUAL(ret, 0); + CU_ASSERT_NOT_EQUAL(num_uas, 0); + } + } +}