diff --git a/Makefile.am b/Makefile.am index 841e5f4..7a1ca9b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -199,6 +199,7 @@ bin_iscsi_test_cu_SOURCES = test-tool/iscsi-test-cu.c \ test-tool/test_readcapacity10_simple.c \ test-tool/test_readcapacity16_simple.c \ test-tool/test_readcapacity16_alloclen.c \ + test-tool/test_unmap_simple.c \ test-tool/test_verify10_simple.c \ test-tool/test_verify10_beyond_eol.c \ test-tool/test_verify10_0blocks.c \ diff --git a/test-tool/iscsi-support.c b/test-tool/iscsi-support.c index 8f2f9e0..1af7ea4 100644 --- a/test-tool/iscsi-support.c +++ b/test-tool/iscsi-support.c @@ -1460,6 +1460,36 @@ readcapacity16(struct iscsi_context *iscsi, int lun, int alloc_len) return 0; } +int +unmap(struct iscsi_context *iscsi, int lun, int anchor, struct unmap_list *list, int list_len) +{ + struct scsi_task *task; + + logging(LOG_VERBOSE, "Send UNMAP list_len:%d anchor:%d", list_len, anchor); + task = iscsi_unmap_sync(iscsi, lun, anchor, 0, list, list_len); + if (task == NULL) { + logging(LOG_NORMAL, "[FAILED] Failed to send UNMAP command: %s", + iscsi_get_error(iscsi)); + return -1; + } + if (task->status == SCSI_STATUS_CHECK_CONDITION + && task->sense.key == SCSI_SENSE_ILLEGAL_REQUEST + && task->sense.ascq == SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE) { + logging(LOG_NORMAL, "[SKIPPED] UNMAP is not implemented on target"); + scsi_free_scsi_task(task); + return -2; + } + if (task->status != SCSI_STATUS_GOOD) { + logging(LOG_NORMAL, "[FAILED] UNMAP command: failed with sense. %s", iscsi_get_error(iscsi)); + scsi_free_scsi_task(task); + return -1; + } + + scsi_free_scsi_task(task); + logging(LOG_VERBOSE, "[OK] UNMAP returned SUCCESS."); + return 0; +} + int verify10(struct iscsi_context *iscsi, int lun, uint32_t lba, uint32_t datalen, int blocksize, int vprotect, int dpo, int bytchk, unsigned char *data) { diff --git a/test-tool/iscsi-support.h b/test-tool/iscsi-support.h index 6c7dcf1..b4f82c3 100644 --- a/test-tool/iscsi-support.h +++ b/test-tool/iscsi-support.h @@ -35,6 +35,39 @@ extern int loglevel; #define LOG_VERBOSE 2 void logging(int level, const char *format, ...); +#define CHECK_FOR_DATALOSS \ +do { \ + if (!data_loss) { \ + logging(LOG_VERBOSE, "[SKIPPED] --dataloss flag is not " \ + "set. Skipping test."); \ + CU_PASS("[SKIPPED] --dataloss flag is not set. " \ + "Skipping test."); \ + return; \ + } \ +} while (0); + +#define CHECK_FOR_THIN_PROVISIONING \ +do { \ + if (lbpme == 0){ \ + logging(LOG_VERBOSE, "[SKIPPED] Logical unit is fully" \ + " provisioned. Skipping test"); \ + CU_PASS("[SKIPPED] Logical unit is fully provisioned." \ + " Skipping test"); \ + return; \ + } \ +} while (0); + +#define CHECK_FOR_SBC \ +do { \ + if (device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) {\ + logging(LOG_VERBOSE, "[SKIPPED] Not SBC device." \ + " Skipping test"); \ + CU_PASS("[SKIPPED] Not SBC device." \ + " Skipping test"); \ + return; \ + } \ +} while (0); + extern uint32_t block_size; extern uint64_t num_blocks; extern int lbpme; @@ -132,6 +165,7 @@ int read16_invalidfieldincdb(struct iscsi_context *iscsi, int lun, uint64_t lba, int read16_lbaoutofrange(struct iscsi_context *iscsi, int lun, uint64_t lba, uint32_t datalen, int blocksize, int rdprotect, int dpo, int fua, int fua_nv, int group, unsigned char *data); int readcapacity10(struct iscsi_context *iscsi, int lun, uint32_t lba, int pmi); int readcapacity16(struct iscsi_context *iscsi, int lun, int alloc_len); +int unmap(struct iscsi_context *iscsi, int lun, int anchor, struct unmap_list *list, int list_len); int verify10(struct iscsi_context *iscsi, int lun, uint32_t lba, uint32_t datalen, int blocksize, int vprotect, int dpo, int bytchk, unsigned char *data); int verify10_nomedium(struct iscsi_context *iscsi, int lun, uint32_t lba, uint32_t datalen, int blocksize, int vprotect, int dpo, int bytchk, unsigned char *data); int verify10_miscompare(struct iscsi_context *iscsi, int lun, uint32_t lba, uint32_t datalen, int blocksize, int vprotect, int dpo, int bytchk, unsigned char *data); diff --git a/test-tool/iscsi-test-cu.c b/test-tool/iscsi-test-cu.c index 6e58be2..d05916a 100644 --- a/test-tool/iscsi-test-cu.c +++ b/test-tool/iscsi-test-cu.c @@ -108,6 +108,11 @@ static CU_TestInfo tests_readcapacity16[] = { CU_TEST_INFO_NULL }; +static CU_TestInfo tests_unmap[] = { + { (char *)"testUnmapSimple", test_unmap_simple }, + CU_TEST_INFO_NULL +}; + static CU_TestInfo tests_verify10[] = { { (char *)"testVerify10Simple", test_verify10_simple }, { (char *)"testVerify10BeyondEol", test_verify10_beyond_eol }, @@ -183,6 +188,8 @@ static CU_SuiteInfo suites[] = { tests_readcapacity10 }, { (char *)"TestReadCapacity16", test_setup, test_teardown, tests_readcapacity16 }, + { (char *)"TestUnmap", test_setup, test_teardown, + tests_unmap }, { (char *)"TestVerify10", test_setup, test_teardown, tests_verify10 }, { (char *)"TestVerify12", test_setup, test_teardown, diff --git a/test-tool/iscsi-test-cu.h b/test-tool/iscsi-test-cu.h index b6d6912..3e4b302 100644 --- a/test-tool/iscsi-test-cu.h +++ b/test-tool/iscsi-test-cu.h @@ -67,6 +67,8 @@ void test_readcapacity10_simple(void); void test_readcapacity16_simple(void); void test_readcapacity16_alloclen(void); +void test_unmap_simple(void); + void test_verify10_simple(void); void test_verify10_beyond_eol(void); void test_verify10_0blocks(void); diff --git a/test-tool/test_read16_0blocks.c b/test-tool/test_read16_0blocks.c index b7aa679..1b45e10 100644 --- a/test-tool/test_read16_0blocks.c +++ b/test-tool/test_read16_0blocks.c @@ -28,6 +28,8 @@ test_read16_0blocks(void) { int ret; + CHECK_FOR_SBC; + logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test READ16 0-blocks at LBA==0"); ret = read16(iscsic, tgt_lun, 0, 0, block_size, diff --git a/test-tool/test_read16_beyond_eol.c b/test-tool/test_read16_beyond_eol.c index 67d262d..0fcc5e7 100644 --- a/test-tool/test_read16_beyond_eol.c +++ b/test-tool/test_read16_beyond_eol.c @@ -29,6 +29,8 @@ test_read16_beyond_eol(void) { int i, ret; + CHECK_FOR_SBC; + logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test READ16 1-256 blocks one block beyond the end"); for (i = 1; i <= 256; i++) { diff --git a/test-tool/test_read16_flags.c b/test-tool/test_read16_flags.c index 8213b92..c77d632 100644 --- a/test-tool/test_read16_flags.c +++ b/test-tool/test_read16_flags.c @@ -30,16 +30,11 @@ test_read16_flags(void) { int ret; + CHECK_FOR_SBC; + logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test READ16 flags"); - /* This test is only valid for SBC devices */ - if (device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) { - CU_PASS("[SKIPPED] LUN is not SBC device. Skipping test"); - return; - } - - logging(LOG_VERBOSE, "Test READ16 with DPO==1"); ret = read16(iscsic, tgt_lun, 0, block_size, block_size, diff --git a/test-tool/test_read16_rdprotect.c b/test-tool/test_read16_rdprotect.c index d1861fb..d83a447 100644 --- a/test-tool/test_read16_rdprotect.c +++ b/test-tool/test_read16_rdprotect.c @@ -30,11 +30,7 @@ test_read16_rdprotect(void) { int i, ret; - - if (device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) { - CU_PASS("[SKIPPED] LUN is not SBC device. Skipping test"); - return; - } + CHECK_FOR_SBC; /* * Try out different non-zero values for RDPROTECT. diff --git a/test-tool/test_read16_simple.c b/test-tool/test_read16_simple.c index c3fb9a6..9bfc4e4 100644 --- a/test-tool/test_read16_simple.c +++ b/test-tool/test_read16_simple.c @@ -31,6 +31,7 @@ test_read16_simple(void) { int i, ret; + CHECK_FOR_SBC; logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test READ16 of 1-256 blocks at the start of the LUN"); diff --git a/test-tool/test_unmap_simple.c b/test-tool/test_unmap_simple.c new file mode 100644 index 0000000..aeb7bf7 --- /dev/null +++ b/test-tool/test_unmap_simple.c @@ -0,0 +1,56 @@ + +/* + Copyright (C) 2013 Ronnie Sahlberg + + 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 "iscsi.h" +#include "scsi-lowlevel.h" +#include "iscsi-support.h" +#include "iscsi-test-cu.h" + + +void +test_unmap_simple(void) +{ + int i, ret; + struct unmap_list list[257]; + + CHECK_FOR_DATALOSS; + CHECK_FOR_THIN_PROVISIONING; + CHECK_FOR_SBC; + + logging(LOG_VERBOSE, ""); + logging(LOG_VERBOSE, "Test UNMAP of 1-256 blocks at the start of the LUN as a single descriptor"); + for (i = 1; i <= 256; i++) { + list[0].lba = 0; + list[0].num = i; + ret = unmap(iscsic, tgt_lun, 0, list, 1); + CU_ASSERT_EQUAL(ret, 0); + } + + + logging(LOG_VERBOSE, "Test UNMAP of 1-256 blocks at the start of the LUN with one descriptor per block"); + for (i = 1; i <= 256; i++) { + list[i].lba = i-1; + list[i].num = 1; + ret = unmap(iscsic, tgt_lun, 0, list, i); + CU_ASSERT_EQUAL(ret, 0); + } +} diff --git a/test-tool/test_write10_0blocks.c b/test-tool/test_write10_0blocks.c index 8f9575d..7318830 100644 --- a/test-tool/test_write10_0blocks.c +++ b/test-tool/test_write10_0blocks.c @@ -28,10 +28,7 @@ test_write10_0blocks(void) { int ret; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } + CHECK_FOR_DATALOSS; if (num_blocks >= 0x80000000) { CU_PASS("LUN is too big for read-beyond-eol tests with WRITE10. Skipping test.\n"); diff --git a/test-tool/test_write10_beyond_eol.c b/test-tool/test_write10_beyond_eol.c index 1f0cb90..eee7c02 100644 --- a/test-tool/test_write10_beyond_eol.c +++ b/test-tool/test_write10_beyond_eol.c @@ -29,10 +29,7 @@ test_write10_beyond_eol(void) { int i, ret; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } + CHECK_FOR_DATALOSS; if (num_blocks >= 0x80000000) { CU_PASS("LUN is too big for write-beyond-eol tests with WRITE10. Skipping test.\n"); diff --git a/test-tool/test_write10_flags.c b/test-tool/test_write10_flags.c index 4ea7704..7ecebe3 100644 --- a/test-tool/test_write10_flags.c +++ b/test-tool/test_write10_flags.c @@ -31,14 +31,11 @@ test_write10_flags(void) int ret; unsigned char *buf; + CHECK_FOR_DATALOSS; + logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test WRITE10 flags"); - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } - buf = malloc(block_size); logging(LOG_VERBOSE, "Test WRITE10 with DPO==1"); ret = write10(iscsic, tgt_lun, 0, diff --git a/test-tool/test_write10_simple.c b/test-tool/test_write10_simple.c index 431889d..0ba8c13 100644 --- a/test-tool/test_write10_simple.c +++ b/test-tool/test_write10_simple.c @@ -31,10 +31,7 @@ test_write10_simple(void) { int i, ret; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } + CHECK_FOR_DATALOSS; logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test WRITE10 of 1-256 blocks at the start of the LUN"); diff --git a/test-tool/test_write10_wrprotect.c b/test-tool/test_write10_wrprotect.c index 66b5d04..19a13be 100644 --- a/test-tool/test_write10_wrprotect.c +++ b/test-tool/test_write10_wrprotect.c @@ -31,10 +31,7 @@ test_write10_wrprotect(void) int i, ret; unsigned char *buf; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } + CHECK_FOR_DATALOSS; /* * Try out different non-zero values for WRPROTECT. diff --git a/test-tool/test_write12_0blocks.c b/test-tool/test_write12_0blocks.c index 9008d93..0448c22 100644 --- a/test-tool/test_write12_0blocks.c +++ b/test-tool/test_write12_0blocks.c @@ -28,10 +28,7 @@ test_write12_0blocks(void) { int ret; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } + CHECK_FOR_DATALOSS; if (num_blocks >= 0x80000000) { CU_PASS("LUN is too big for read-beyond-eol tests with WRITE12. Skipping test.\n"); diff --git a/test-tool/test_write12_beyond_eol.c b/test-tool/test_write12_beyond_eol.c index ee742f6..931ada2 100644 --- a/test-tool/test_write12_beyond_eol.c +++ b/test-tool/test_write12_beyond_eol.c @@ -29,10 +29,7 @@ test_write12_beyond_eol(void) { int i, ret; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } + CHECK_FOR_DATALOSS; if (num_blocks >= 0x80000000) { CU_PASS("LUN is too big for write-beyond-eol tests with WRITE12. Skipping test.\n"); diff --git a/test-tool/test_write12_flags.c b/test-tool/test_write12_flags.c index 247c722..efe6e6a 100644 --- a/test-tool/test_write12_flags.c +++ b/test-tool/test_write12_flags.c @@ -31,14 +31,11 @@ test_write12_flags(void) int ret; unsigned char *buf; + CHECK_FOR_DATALOSS; + logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test WRITE12 flags"); - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } - buf = malloc(block_size); logging(LOG_VERBOSE, "Test WRITE12 with DPO==1"); ret = write12(iscsic, tgt_lun, 0, diff --git a/test-tool/test_write12_simple.c b/test-tool/test_write12_simple.c index 35c9a6f..48e295f 100644 --- a/test-tool/test_write12_simple.c +++ b/test-tool/test_write12_simple.c @@ -31,10 +31,7 @@ test_write12_simple(void) { int i, ret; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } + CHECK_FOR_DATALOSS; logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test WRITE12 of 1-256 blocks at the start of the LUN"); diff --git a/test-tool/test_write12_wrprotect.c b/test-tool/test_write12_wrprotect.c index 035a6a5..f0ed5d1 100644 --- a/test-tool/test_write12_wrprotect.c +++ b/test-tool/test_write12_wrprotect.c @@ -31,10 +31,7 @@ test_write12_wrprotect(void) int i, ret; unsigned char *buf; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } + CHECK_FOR_DATALOSS; /* * Try out different non-zero values for WRPROTECT. diff --git a/test-tool/test_write16_0blocks.c b/test-tool/test_write16_0blocks.c index 19d8de7..b4ee573 100644 --- a/test-tool/test_write16_0blocks.c +++ b/test-tool/test_write16_0blocks.c @@ -28,16 +28,8 @@ test_write16_0blocks(void) { int ret; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } - - /* This test is only valid for SBC devices */ - if (device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) { - CU_PASS("[SKIPPED] LUN is not SBC device. Skipping test"); - return; - } + CHECK_FOR_DATALOSS; + CHECK_FOR_SBC; logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test WRITE16 0-blocks at LBA==0"); diff --git a/test-tool/test_write16_beyond_eol.c b/test-tool/test_write16_beyond_eol.c index eadcf04..324b4a1 100644 --- a/test-tool/test_write16_beyond_eol.c +++ b/test-tool/test_write16_beyond_eol.c @@ -29,16 +29,8 @@ test_write16_beyond_eol(void) { int i, ret; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } - - /* This test is only valid for SBC devices */ - if (device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) { - CU_PASS("[SKIPPED] LUN is not SBC device. Skipping test"); - return; - } + CHECK_FOR_DATALOSS; + CHECK_FOR_SBC; logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test WRITE16 1-256 blocks one block beyond the end"); diff --git a/test-tool/test_write16_flags.c b/test-tool/test_write16_flags.c index f96a5ab..f7e26eb 100644 --- a/test-tool/test_write16_flags.c +++ b/test-tool/test_write16_flags.c @@ -31,20 +31,12 @@ test_write16_flags(void) int ret; unsigned char *buf; + CHECK_FOR_DATALOSS; + CHECK_FOR_SBC; + logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test WRITE16 flags"); - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } - - /* This test is only valid for SBC devices */ - if (device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) { - CU_PASS("[SKIPPED] LUN is not SBC device. Skipping test"); - return; - } - buf = malloc(block_size); logging(LOG_VERBOSE, "Test WRITE16 with DPO==1"); ret = write16(iscsic, tgt_lun, 0, diff --git a/test-tool/test_write16_simple.c b/test-tool/test_write16_simple.c index 4ef5029..7b9587b 100644 --- a/test-tool/test_write16_simple.c +++ b/test-tool/test_write16_simple.c @@ -31,16 +31,8 @@ test_write16_simple(void) { int i, ret; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } - - /* This test is only valid for SBC devices */ - if (device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) { - CU_PASS("[SKIPPED] LUN is not SBC device. Skipping test"); - return; - } + CHECK_FOR_DATALOSS; + CHECK_FOR_SBC; logging(LOG_VERBOSE, ""); logging(LOG_VERBOSE, "Test WRITE16 of 1-256 blocks at the start of the LUN"); diff --git a/test-tool/test_write16_wrprotect.c b/test-tool/test_write16_wrprotect.c index dc2eea3..c5db34d 100644 --- a/test-tool/test_write16_wrprotect.c +++ b/test-tool/test_write16_wrprotect.c @@ -31,15 +31,8 @@ test_write16_wrprotect(void) int i, ret; unsigned char *buf; - if (!data_loss) { - CU_PASS("[SKIPPED] --dataloss flag is not set. Skipping test."); - return; - } - - if (device_type != SCSI_INQUIRY_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS) { - CU_PASS("[SKIPPED] LUN is not SBC device. Skipping test"); - return; - } + CHECK_FOR_DATALOSS; + CHECK_FOR_SBC; /* * Try out different non-zero values for WRPROTECT.