diff --git a/lib/libiscsi.def b/lib/libiscsi.def index cbca74d..df17bdc 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -210,6 +210,7 @@ scsi_get_uint16 scsi_get_uint32 scsi_get_uint64 scsi_inquiry_pagecode_to_str +scsi_malloc scsi_modesense_dataout_marshall scsi_modesense_get_page scsi_protocol_identifier_to_str diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index f57cc65..533cb71 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -208,6 +208,7 @@ scsi_get_uint16 scsi_get_uint32 scsi_get_uint64 scsi_inquiry_pagecode_to_str +scsi_malloc scsi_modesense_dataout_marshall scsi_modesense_get_page scsi_protocol_identifier_to_str diff --git a/test-tool/iscsi-support.c b/test-tool/iscsi-support.c index d26bfe7..fcac5fe 100644 --- a/test-tool/iscsi-support.c +++ b/test-tool/iscsi-support.c @@ -1840,120 +1840,63 @@ reserve6_conflict(struct iscsi_context *iscsi, int lun) } int -unmap(struct iscsi_context *iscsi, int lun, int anchor, struct unmap_list *list, int list_len) +unmap(struct iscsi_context *iscsi, int lun, int anchor, struct unmap_list *list, int list_len, int status, enum scsi_sense_key key, int *ascq, int num_ascq) { struct scsi_task *task; + struct scsi_iovec *iov; + unsigned char *data; + int xferlen; + int i; + int ret; - 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)); + logging(LOG_VERBOSE, "Send UNMAP (Expecting %s) list_len:%d anchor:%d", + scsi_status_str(status), + list_len, anchor); + + if (!data_loss) { + printf("--dataloss flag is not set in. Skipping unmap\n"); 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)); + + xferlen = 8 + list_len * 16; + + task = scsi_cdb_unmap(anchor, 0, xferlen); + assert(task != NULL); + + data = scsi_malloc(task, xferlen); + if (data == NULL) { + logging(LOG_NORMAL, "Out-of-memory: Failed to create " + "unmap parameters."); scsi_free_scsi_task(task); return -1; } - scsi_free_scsi_task(task); - logging(LOG_VERBOSE, "[OK] UNMAP returned SUCCESS."); - return 0; -} - -int -unmap_writeprotected(struct iscsi_context *iscsi, int lun, int anchor, struct unmap_list *list, int list_len) -{ - struct scsi_task *task; - - logging(LOG_VERBOSE, "Send UNMAP (Expecting WRITE_PROTECTED) " - "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; + scsi_set_uint16(&data[0], xferlen - 2); + scsi_set_uint16(&data[2], xferlen - 8); + for (i = 0; i < list_len; i++) { + scsi_set_uint32(&data[8 + 16 * i], list[i].lba >> 32); + scsi_set_uint32(&data[8 + 16 * i + 4], list[i].lba & 0xffffffff); + scsi_set_uint32(&data[8 + 16 * i + 8], list[i].num); } - 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 successful but should " - "have failed with DATA_PROTECTION/WRITE_PROTECTED"); + + iov = scsi_malloc(task, sizeof(struct scsi_iovec)); + if (iov == NULL) { + logging(LOG_NORMAL, "Out-of-memory: Failed to create " + "iov array."); scsi_free_scsi_task(task); return -1; } - if (task->status != SCSI_STATUS_CHECK_CONDITION - || task->sense.key != SCSI_SENSE_DATA_PROTECTION - || task->sense.ascq != SCSI_SENSE_ASCQ_WRITE_PROTECTED) { - logging(LOG_NORMAL, "[FAILED] UNMAP failed with wrong sense. " - "Should have failed with DATA_PRTOTECTION/" - "WRITE_PROTECTED. Sense:%s\n", - iscsi_get_error(iscsi)); + iov->iov_base = data; + iov->iov_len = xferlen; + scsi_task_set_iov_out(task, iov, 1); + + task = iscsi_scsi_command_sync(iscsi, lun, task, NULL); + + ret = check_result("UNMAP", iscsi, task, status, key, ascq, num_ascq); + if (task) { scsi_free_scsi_task(task); - return -1; } - - scsi_free_scsi_task(task); - logging(LOG_VERBOSE, "[OK] UNMAP returned DATA_PROTECTION/WRITE_PROTECTED."); - return 0; -} - -int -unmap_nomedium(struct iscsi_context *iscsi, int lun, int anchor, struct unmap_list *list, int list_len) -{ - struct scsi_task *task; - - logging(LOG_VERBOSE, "Send UNMAP (Expecting MEDIUM_NOT_PRESENT) " - "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 successful but should " - "have failed with NOT_READY/MEDIUM_NOT_PRESENT*"); - scsi_free_scsi_task(task); - return -1; - } - if (task->status != SCSI_STATUS_CHECK_CONDITION - || task->sense.key != SCSI_SENSE_NOT_READY - || (task->sense.ascq != SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT - && task->sense.ascq != SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN - && task->sense.ascq != SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED)) { - logging(LOG_NORMAL, "[FAILED] UNMAP Should have failed " - "with NOT_READY/MEDIUM_NOT_PRESENT* But failed " - "with %s", iscsi_get_error(iscsi)); - scsi_free_scsi_task(task); - return -1; - } - - scsi_free_scsi_task(task); - logging(LOG_VERBOSE, "[OK] UNMAP returned MEDIUM_NOT_PRESENT."); - return 0; + return ret; } int diff --git a/test-tool/iscsi-support.h b/test-tool/iscsi-support.h index 5cca4af..3396f25 100644 --- a/test-tool/iscsi-support.h +++ b/test-tool/iscsi-support.h @@ -2,6 +2,7 @@ iscsi-test tool support Copyright (C) 2012 by Lee Duncan + Copyright (C) 2014 by 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 @@ -280,9 +281,7 @@ int synchronizecache16(struct iscsi_context *iscsi, int lun, uint64_t lba, int n int testunitready_clear_ua(struct iscsi_context *iscsi, int lun); int testunitready(struct iscsi_context *iscsi, int lun, int status, enum scsi_sense_key key, int *ascq, int num_ascq); int mode_sense(struct iscsi_context *iscsi, int lun); -int unmap(struct iscsi_context *iscsi, int lun, int anchor, struct unmap_list *list, int list_len); -int unmap_writeprotected(struct iscsi_context *iscsi, int lun, int anchor, struct unmap_list *list, int list_len); -int unmap_nomedium(struct iscsi_context *iscsi, int lun, int anchor, struct unmap_list *list, int list_len); +int unmap(struct iscsi_context *iscsi, int lun, int anchor, struct unmap_list *list, int list_len, int status, enum scsi_sense_key key, int *ascq, int num_ascq); 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 status, enum scsi_sense_key key, int *ascq, int num_ascq); int verify12(struct iscsi_context *iscsi, int lun, uint32_t lba, uint32_t datalen, int blocksize, int vprotect, int dpo, int bytchk, unsigned char *data, int status, enum scsi_sense_key key, int *ascq, int num_ascq); int verify16(struct iscsi_context *iscsi, int lun, uint64_t lba, uint32_t datalen, int blocksize, int vprotect, int dpo, int bytchk, unsigned char *data, int status, enum scsi_sense_key key, int *ascq, int num_ascq); diff --git a/test-tool/test_get_lba_status_unmap_single.c b/test-tool/test_get_lba_status_unmap_single.c index 2892f8f..0c8b4f9 100644 --- a/test-tool/test_get_lba_status_unmap_single.c +++ b/test-tool/test_get_lba_status_unmap_single.c @@ -60,7 +60,8 @@ test_get_lba_status_unmap_single(void) PRIu64 " (number of logical blocks: %d)", i, lbppb); list[0].lba = i; list[0].num = lbppb; - ret = unmap(iscsic, tgt_lun, 0, list, 1); + ret = unmap(iscsic, tgt_lun, 0, list, 1, + EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Read the status of the block at LBA:%" @@ -122,7 +123,8 @@ test_get_lba_status_unmap_single(void) logging(LOG_VERBOSE, "Unmap %" PRIu64 " blocks at LBA 0", i); list[0].lba = 0; list[0].num = i; - ret = unmap(iscsic, tgt_lun, 0, list, 1); + ret = unmap(iscsic, tgt_lun, 0, list, 1, + EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Read the status of the block at LBA:0"); diff --git a/test-tool/test_nomedia_sbc.c b/test-tool/test_nomedia_sbc.c index f17230c..42f95e4 100644 --- a/test-tool/test_nomedia_sbc.c +++ b/test-tool/test_nomedia_sbc.c @@ -266,7 +266,8 @@ test_nomedia_sbc(void) logging(LOG_VERBOSE, "Test UNMAP when medium is ejected."); list[0].lba = 0; list[0].num = lbppb; - ret = unmap_nomedium(iscsic, tgt_lun, 0, list, 1); + ret = unmap(iscsic, tgt_lun, 0, list, 1, + EXPECT_NO_MEDIUM); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] target does not support " "UNMAP"); diff --git a/test-tool/test_readonly_sbc.c b/test-tool/test_readonly_sbc.c index 03550f2..d15e301 100644 --- a/test-tool/test_readonly_sbc.c +++ b/test-tool/test_readonly_sbc.c @@ -97,7 +97,8 @@ test_readonly_sbc(void) logging(LOG_VERBOSE, "Test UNMAP of one physical block fails with WRITE_PROTECTED"); list[0].lba = 0; list[0].num = lbppb; - ret = unmap_writeprotected(iscsic, tgt_lun, 0, list, 1); + ret = unmap(iscsic, tgt_lun, 0, list, 1, + EXPECT_WRITE_PROTECTED); if (ret == -2) { logging(LOG_VERBOSE, "UNMAP not supported on target. Skipped."); } @@ -106,7 +107,8 @@ test_readonly_sbc(void) logging(LOG_VERBOSE, "Test UNMAP of one logical block fails with WRITE_PROTECTED"); list[0].lba = 0; list[0].num = 1; - ret = unmap_writeprotected(iscsic, tgt_lun, 0, list, 1); + ret = unmap(iscsic, tgt_lun, 0, list, 1, + EXPECT_WRITE_PROTECTED); if (ret == -2) { logging(LOG_VERBOSE, "UNMAP not supported on target. Skipped."); } diff --git a/test-tool/test_unmap_0blocks.c b/test-tool/test_unmap_0blocks.c index 63bf1dd..400840b 100644 --- a/test-tool/test_unmap_0blocks.c +++ b/test-tool/test_unmap_0blocks.c @@ -1,4 +1,3 @@ - /* Copyright (C) 2013 Ronnie Sahlberg @@ -41,7 +40,8 @@ test_unmap_0blocks(void) for (i = 0; i < 256; i++) { list[0].lba = i; list[0].num = 0; - ret = unmap(iscsic, tgt_lun, 0, list, 1); + ret = unmap(iscsic, tgt_lun, 0, list, 1, + EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } @@ -49,14 +49,16 @@ test_unmap_0blocks(void) for (i = 0; i < 256; i++) { list[i].lba = i; list[i].num = 0; - ret = unmap(iscsic, tgt_lun, 0, list, i); + ret = unmap(iscsic, tgt_lun, 0, list, i, + EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test UNMAP of 0 blocks at end-of-LUN"); list[0].lba = num_blocks; list[0].num = 0; - ret = unmap(iscsic, tgt_lun, 0, list, 1); + ret = unmap(iscsic, tgt_lun, 0, list, 1, + EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); @@ -65,12 +67,14 @@ test_unmap_0blocks(void) list[i].lba = i/2; list[i].num = 0; } - ret = unmap(iscsic, tgt_lun, 0, list, 256); + ret = unmap(iscsic, tgt_lun, 0, list, 256, + EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Test UNMAP without any descriptors."); - ret = unmap(iscsic, tgt_lun, 0, list, 0); + ret = unmap(iscsic, tgt_lun, 0, list, 0, + EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } diff --git a/test-tool/test_unmap_simple.c b/test-tool/test_unmap_simple.c index a30400a..1dfb4e2 100644 --- a/test-tool/test_unmap_simple.c +++ b/test-tool/test_unmap_simple.c @@ -64,7 +64,8 @@ test_unmap_simple(void) logging(LOG_VERBOSE, "UNMAP blocks 0-%d", i); list[0].lba = 0; list[0].num = i; - ret = unmap(iscsic, tgt_lun, 0, list, 1); + ret = unmap(iscsic, tgt_lun, 0, list, 1, + EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Read blocks 0-%d", i); @@ -98,7 +99,8 @@ test_unmap_simple(void) for (i = 0; i < 256; i++) { list[i].lba = i; list[i].num = 1; - ret = unmap(iscsic, tgt_lun, 0, list, i + 1); + ret = unmap(iscsic, tgt_lun, 0, list, i + 1, + EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Read blocks 0-%d", i); diff --git a/test-tool/test_unmap_vpd.c b/test-tool/test_unmap_vpd.c index 26e15b5..203e88a 100644 --- a/test-tool/test_unmap_vpd.c +++ b/test-tool/test_unmap_vpd.c @@ -40,8 +40,8 @@ test_unmap_vpd(void) logging(LOG_VERBOSE, "Check if UNMAP is available."); list[0].lba = 0; list[0].num = 0; - ret = unmap(iscsic, tgt_lun, 0, list, 1); - + ret = unmap(iscsic, tgt_lun, 0, list, 1, + EXPECT_STATUS_GOOD); if (ret != 0) { logging(LOG_VERBOSE, "UNMAP is not available. Verify that VPD " "settings reflect this.");