diff --git a/Makefile.am b/Makefile.am index 5ac7fa1..5998971 100644 --- a/Makefile.am +++ b/Makefile.am @@ -198,6 +198,7 @@ bin_iscsi_test_cu_SOURCES = test-tool/iscsi-test-cu.c \ test-tool/test_prout_register_simple.c \ test-tool/test_prout_reserve_simple.c \ test-tool/test_prout_reserve_access.c \ + test-tool/test_prout_reserve_ownership.c \ test-tool/test_read6_simple.c \ test-tool/test_read6_beyond_eol.c \ test-tool/test_read6_0blocks.c \ diff --git a/test-tool/iscsi-support.c b/test-tool/iscsi-support.c index 40dd096..71f4981 100644 --- a/test-tool/iscsi-support.c +++ b/test-tool/iscsi-support.c @@ -809,6 +809,56 @@ prin_verify_reserved_as(struct iscsi_context *iscsi, int lun, return ret; } +int +prin_verify_not_reserved(struct iscsi_context *iscsi, int lun) +{ + struct scsi_task *task; + const int buf_sz = 16384; + struct scsi_persistent_reserve_in_read_reservation *rr = NULL; + int ret = 0; + + + logging(LOG_VERBOSE, + "Send PRIN/READ_RESERVATION to verify not reserved init=%s", + iscsi->initiator_name); + + task = iscsi_persistent_reserve_in_sync(iscsi, lun, + SCSI_PERSISTENT_RESERVE_READ_RESERVATION, buf_sz); + if (task == NULL) { + logging(LOG_NORMAL, + "[FAILED] Failed to send PRIN command: %s", + iscsi_get_error(iscsi)); + return -1; + } + + if (task->status != SCSI_STATUS_GOOD) { + logging(LOG_NORMAL, + "[FAILED] PRIN command: failed with sense: %s", + iscsi_get_error(iscsi)); + ret = -1; + goto dun; + } + rr = scsi_datain_unmarshall(task); + if (rr == NULL) { + logging(LOG_NORMAL, + "[FAILED] Failed to unmarshall PRIN/READ_RESERVATION data: %s", + iscsi_get_error(iscsi)); + ret = -1; + goto dun; + } + if (rr->reserved) { + logging(LOG_NORMAL, + "[FAILED] Failed to find Target not reserved as expected."); + ret = -1; + goto dun; + } + + dun: + /* ??? free rr? */ + scsi_free_scsi_task(task); + return ret; +} + int verify_read_works(struct iscsi_context *iscsi, int lun, unsigned char *buf) { diff --git a/test-tool/iscsi-support.h b/test-tool/iscsi-support.h index 50b6364..6128386 100644 --- a/test-tool/iscsi-support.h +++ b/test-tool/iscsi-support.h @@ -192,6 +192,7 @@ int prout_reserve(struct iscsi_context *iscsi, int lun, unsigned long long key, enum scsi_persistent_out_type pr_type); int prout_release(struct iscsi_context *iscsi, int lun, unsigned long long key, enum scsi_persistent_out_type pr_type); +int prin_verify_not_reserved(struct iscsi_context *iscsi, int lun); int prin_verify_reserved_as(struct iscsi_context *iscsi, int lun, unsigned long long key, enum scsi_persistent_out_type pr_type); int verify_read_works(struct iscsi_context *iscsi, int lun, unsigned char *buf); diff --git a/test-tool/iscsi-test-cu.c b/test-tool/iscsi-test-cu.c index 85e0053..d4d8fdf 100644 --- a/test-tool/iscsi-test-cu.c +++ b/test-tool/iscsi-test-cu.c @@ -103,9 +103,12 @@ static CU_TestInfo tests_prout_register[] = { }; static CU_TestInfo tests_prout_reserve[] = { - { (char *)"testProutReserveSimple", test_prout_reserve_simple }, - { (char *)"testProutReserveAccessEA", test_prout_reserve_access_ea }, - { (char *)"testProutReserveAccessWE", test_prout_reserve_access_we }, + { (char *)"testProutReserveSimple", + test_prout_reserve_simple }, + { (char *)"testProutReserveAccessEA", + test_prout_reserve_access_ea }, + { (char *)"testProutReserveAccessWE", + test_prout_reserve_access_we }, { (char *)"testProutReserveAccessEARO", test_prout_reserve_access_earo }, { (char *)"testProutReserveAccessWERO", @@ -114,6 +117,18 @@ static CU_TestInfo tests_prout_reserve[] = { test_prout_reserve_access_eaar }, { (char *)"testProutReserveAccessWEAR", test_prout_reserve_access_wear }, + { (char *)"testProutReserveOwnershipEA", + test_prout_reserve_ownership_ea }, + { (char *)"testProutReserveOwnershipWE", + test_prout_reserve_ownership_we }, + { (char *)"testProutReserveOwnershipEARO", + test_prout_reserve_ownership_earo }, + { (char *)"testProutReserveOwnershipWERO", + test_prout_reserve_ownership_wero }, + { (char *)"testProutReserveOwnershipEAAR", + test_prout_reserve_ownership_eaar }, + { (char *)"testProutReserveOwnershipWEAR", + test_prout_reserve_ownership_wear }, CU_TEST_INFO_NULL }; diff --git a/test-tool/iscsi-test-cu.h b/test-tool/iscsi-test-cu.h index 03ffe06..6c03856 100644 --- a/test-tool/iscsi-test-cu.h +++ b/test-tool/iscsi-test-cu.h @@ -71,6 +71,12 @@ void test_prout_reserve_access_earo(void); void test_prout_reserve_access_wero(void); void test_prout_reserve_access_eaar(void); void test_prout_reserve_access_wear(void); +void test_prout_reserve_ownership_ea(void); +void test_prout_reserve_ownership_we(void); +void test_prout_reserve_ownership_earo(void); +void test_prout_reserve_ownership_wero(void); +void test_prout_reserve_ownership_eaar(void); +void test_prout_reserve_ownership_wear(void); void test_read6_simple(void); void test_read6_beyond_eol(void); diff --git a/test-tool/test_prout_reserve_ownership.c b/test-tool/test_prout_reserve_ownership.c new file mode 100644 index 0000000..d374d4b --- /dev/null +++ b/test-tool/test_prout_reserve_ownership.c @@ -0,0 +1,132 @@ +/* + Copyright (C) 2013 by Lee Duncan + + 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-test-cu.h" + + +static void +verify_persistent_reserve_ownership(struct iscsi_context *iscsi1, int lun1, + struct iscsi_context *iscsi2, int lun2, + const enum scsi_persistent_out_type pr_type, + int resvn_is_shared) +{ + int ret; + const unsigned long long key1 = rand_key(); + const unsigned long long key2 = rand_key(); + + + logging(LOG_VERBOSE, LOG_BLANK_LINE); + logging(LOG_VERBOSE, + "Verify ownership for reservation type: %s", + scsi_pr_type_str(pr_type)); + + /* send TURs to clear possible check conditions */ + (void) testunitready_clear_ua(iscsi1, lun1); + (void) testunitready_clear_ua(iscsi2, lun2); + + /* register our reservation key with the target */ + ret = prout_register_and_ignore(iscsi1, lun1, key1); + CU_ASSERT_EQUAL(0, ret); + ret = prout_register_and_ignore(iscsi2, lun2, key2); + CU_ASSERT_EQUAL(0, ret); + + /* reserve the target through initiator 1 */ + ret = prout_reserve(iscsi1, lun1, key1, pr_type); + CU_ASSERT_EQUAL(0, ret); + + /* verify target reservation */ + ret = prin_verify_reserved_as(iscsi1, lun1, + pr_type_is_all_registrants(pr_type) ? 0 : key1, + pr_type); + CU_ASSERT_EQUAL(0, ret); + + /* unregister init1 */ + ret = prout_register_key(iscsi1, lun1, 0, key1); + CU_ASSERT_EQUAL(0, ret); + + /* verify if reservation is still present */ + if (resvn_is_shared) { + /* verify target reservation */ + ret = prin_verify_reserved_as(iscsi1, lun1, + pr_type_is_all_registrants(pr_type) ? 0 : key1, + pr_type); + CU_ASSERT_EQUAL(0, ret); + + /* release our reservation */ + ret = prout_release(iscsi2, lun2, key2, pr_type); + CU_ASSERT_EQUAL(0, ret); + } else { + /* verify target is not reserved now */ + ret = prin_verify_not_reserved(iscsi1, lun1); + CU_ASSERT_EQUAL(0, ret); + + /* send TUR to clear possible check condition */ + (void) testunitready_clear_ua(iscsi2, lun2); + } + + /* remove our remaining key from the target */ + ret = prout_register_key(iscsi2, lun2, 0, key2); + CU_ASSERT_EQUAL(0, ret); +} + +void +test_prout_reserve_ownership_ea(void) +{ + verify_persistent_reserve_ownership(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS, 0); +} + +void +test_prout_reserve_ownership_we(void) +{ + verify_persistent_reserve_ownership(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE, 0); +} + +void +test_prout_reserve_ownership_earo(void) +{ + verify_persistent_reserve_ownership(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_REGISTRANTS_ONLY, 0); +} + +void +test_prout_reserve_ownership_wero(void) +{ + verify_persistent_reserve_ownership(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_REGISTRANTS_ONLY, 0); +} + +void +test_prout_reserve_ownership_eaar(void) +{ + verify_persistent_reserve_ownership(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_EXCLUSIVE_ACCESS_ALL_REGISTRANTS, 1); +} + +void +test_prout_reserve_ownership_wear(void) +{ + verify_persistent_reserve_ownership(iscsic, tgt_lun, iscsic2, tgt_lun2, + SCSI_PERSISTENT_RESERVE_TYPE_WRITE_EXCLUSIVE_ALL_REGISTRANTS, 1); +}