diff --git a/Makefile.am b/Makefile.am index 081209d..7c4540b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -102,7 +102,8 @@ bin_iscsi_test_SOURCES = test-tool/iscsi-test.c \ test-tool/0330_writeverify16_simple.c test-tool/0331_writeverify16_wrprotect.c \ test-tool/0334_writeverify16_beyondeol.c \ test-tool/0340_compareandwrite_simple.c test-tool/0341_compareandwrite_mismatch.c \ - test-tool/0343_compareandwrite_beyondeol.c + test-tool/0343_compareandwrite_beyondeol.c \ + test-tool/0350_orwrite_simple.c endif diff --git a/include/iscsi.h b/include/iscsi.h index f774cb8..0436230 100644 --- a/include/iscsi.h +++ b/include/iscsi.h @@ -656,7 +656,7 @@ iscsi_write16_task(struct iscsi_context *iscsi, int lun, uint64_t lba, int wrprotect, int dpo, int fua, int fua_nv, int group_number, iscsi_command_cb cb, void *private_data); EXTERN struct scsi_task * -iscsi_orwrite16_task(struct iscsi_context *iscsi, int lun, uint64_t lba, +iscsi_orwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba, unsigned char *data, uint32_t datalen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number, iscsi_command_cb cb, void *private_data); @@ -787,7 +787,7 @@ iscsi_write16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba, int wrprotect, int dpo, int fua, int fua_nv, int group_number); EXTERN struct scsi_task * -iscsi_orwrite16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba, +iscsi_orwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba, unsigned char *data, uint32_t datalen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number); diff --git a/include/scsi-lowlevel.h b/include/scsi-lowlevel.h index 2fe80c9..c607ccc 100644 --- a/include/scsi-lowlevel.h +++ b/include/scsi-lowlevel.h @@ -40,7 +40,7 @@ enum scsi_opcode { SCSI_OPCODE_READ16 = 0x88, SCSI_OPCODE_COMPARE_AND_WRITE = 0x89, SCSI_OPCODE_WRITE16 = 0x8A, - SCSI_OPCODE_ORWRITE16 = 0x8B, + SCSI_OPCODE_ORWRITE = 0x8B, SCSI_OPCODE_WRITE_VERIFY16 = 0x8E, SCSI_OPCODE_VERIFY16 = 0x8F, SCSI_OPCODE_PREFETCH16 = 0x90, @@ -133,7 +133,7 @@ struct scsi_write16_params { uint64_t lba; uint32_t num_blocks; }; -struct scsi_orwrite16_params { +struct scsi_orwrite_params { uint64_t lba; uint32_t num_blocks; }; @@ -229,7 +229,7 @@ struct scsi_task { struct scsi_write10_params write10; struct scsi_write12_params write12; struct scsi_write16_params write16; - struct scsi_orwrite16_params orwrite16; + struct scsi_orwrite_params orwrite; struct scsi_compareandwrite_params compareandwrite; struct scsi_writeverify10_params writeverify10; struct scsi_writeverify12_params writeverify12; @@ -662,7 +662,7 @@ EXTERN struct scsi_task *scsi_cdb_read16(uint64_t lba, uint32_t xferlen, int blo EXTERN struct scsi_task *scsi_cdb_write10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number); EXTERN struct scsi_task *scsi_cdb_write12(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number); EXTERN struct scsi_task *scsi_cdb_write16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number); -EXTERN struct scsi_task *scsi_cdb_orwrite16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number); +EXTERN struct scsi_task *scsi_cdb_orwrite(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number); EXTERN struct scsi_task *scsi_cdb_compareandwrite(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number); EXTERN struct scsi_task *scsi_cdb_writeverify10(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number); EXTERN struct scsi_task *scsi_cdb_writeverify12(uint32_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int bytchk, int group_number); diff --git a/lib/libiscsi.def b/lib/libiscsi.def index ac299cc..9120089 100644 --- a/lib/libiscsi.def +++ b/lib/libiscsi.def @@ -88,8 +88,8 @@ iscsi_write12_sync iscsi_write12_task iscsi_write16_sync iscsi_write16_task -iscsi_orwrite16_sync -iscsi_orwrite16_task +iscsi_orwrite_sync +iscsi_orwrite_task iscsi_compareandwrite_sync iscsi_compareandwrite_task iscsi_writeverify10_sync @@ -124,7 +124,7 @@ scsi_cdb_verify16 scsi_cdb_write10 scsi_cdb_write12 scsi_cdb_write16 -scsi_cdb_orwrite16 +scsi_cdb_orwrite scsi_cdb_writeverify10 scsi_cdb_writeverify12 scsi_cdb_writeverify16 diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms index 174687a..20af681 100644 --- a/lib/libiscsi.syms +++ b/lib/libiscsi.syms @@ -86,8 +86,8 @@ iscsi_write12_sync iscsi_write12_task iscsi_write16_sync iscsi_write16_task -iscsi_orwrite16_sync -iscsi_orwrite16_task +iscsi_orwrite_sync +iscsi_orwrite_task iscsi_compareandwrite_sync iscsi_compareandwrite_task iscsi_writeverify10_sync @@ -122,7 +122,7 @@ scsi_cdb_verify16 scsi_cdb_write10 scsi_cdb_write12 scsi_cdb_write16 -scsi_cdb_orwrite16 +scsi_cdb_orwrite scsi_cdb_writeverify10 scsi_cdb_writeverify12 scsi_cdb_writeverify16 diff --git a/lib/scsi-command.c b/lib/scsi-command.c index 8365c5f..96d3130 100644 --- a/lib/scsi-command.c +++ b/lib/scsi-command.c @@ -871,7 +871,7 @@ iscsi_write16_task(struct iscsi_context *iscsi, int lun, uint64_t lba, } struct scsi_task * -iscsi_orwrite16_task(struct iscsi_context *iscsi, int lun, uint64_t lba, +iscsi_orwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba, unsigned char *data, uint32_t datalen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number, iscsi_command_cb cb, void *private_data) @@ -885,11 +885,11 @@ iscsi_orwrite16_task(struct iscsi_context *iscsi, int lun, uint64_t lba, return NULL; } - task = scsi_cdb_orwrite16(lba, datalen, blocksize, wrprotect, + task = scsi_cdb_orwrite(lba, datalen, blocksize, wrprotect, dpo, fua, fua_nv, group_number); if (task == NULL) { iscsi_set_error(iscsi, "Out-of-memory: Failed to create " - "orwrite16 cdb."); + "orwrite cdb."); return NULL; } diff --git a/lib/scsi-lowlevel.c b/lib/scsi-lowlevel.c index ebd62be..cae8d30 100644 --- a/lib/scsi-lowlevel.c +++ b/lib/scsi-lowlevel.c @@ -984,10 +984,10 @@ scsi_cdb_write16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, i } /* - * ORWRITE16 + * ORWRITE */ struct scsi_task * -scsi_cdb_orwrite16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number) +scsi_cdb_orwrite(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number) { struct scsi_task *task; @@ -997,7 +997,7 @@ scsi_cdb_orwrite16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, } memset(task, 0, sizeof(struct scsi_task)); - task->cdb[0] = SCSI_OPCODE_ORWRITE16; + task->cdb[0] = SCSI_OPCODE_ORWRITE; task->cdb[1] |= ((wrprotect & 0x07) << 5); if (dpo) { @@ -1024,8 +1024,8 @@ scsi_cdb_orwrite16(uint64_t lba, uint32_t xferlen, int blocksize, int wrprotect, } task->expxferlen = xferlen; - task->params.orwrite16.lba = lba; - task->params.orwrite16.num_blocks = xferlen/blocksize; + task->params.orwrite.lba = lba; + task->params.orwrite.num_blocks = xferlen/blocksize; return task; } diff --git a/lib/sync.c b/lib/sync.c index 961eb5e..6c93b96 100644 --- a/lib/sync.c +++ b/lib/sync.c @@ -529,7 +529,7 @@ iscsi_write16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba, } struct scsi_task * -iscsi_orwrite16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba, +iscsi_orwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba, unsigned char *data, uint32_t datalen, int blocksize, int wrprotect, int dpo, int fua, int fua_nv, int group_number) { @@ -537,12 +537,12 @@ iscsi_orwrite16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba, memset(&state, 0, sizeof(state)); - if (iscsi_orwrite16_task(iscsi, lun, lba, + if (iscsi_orwrite_task(iscsi, lun, lba, data, datalen, blocksize, wrprotect, dpo, fua, fua_nv, group_number, scsi_sync_cb, &state) == NULL) { iscsi_set_error(iscsi, - "Failed to send Orwrite16 command"); + "Failed to send Orwrite command"); return NULL; } diff --git a/test-tool/0350_orwrite_simple.c b/test-tool/0350_orwrite_simple.c new file mode 100644 index 0000000..11d0708 --- /dev/null +++ b/test-tool/0350_orwrite_simple.c @@ -0,0 +1,261 @@ +/* + Copyright (C) 2012 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 + 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-test.h" + +int T0350_orwrite_simple(const char *initiator, const char *url, int data_loss, int show_info) +{ + struct iscsi_context *iscsi; + struct scsi_task *task; + struct scsi_readcapacity16 *rc16; + int ret, i, j, lun; + uint32_t block_size; + uint64_t num_blocks; + unsigned char r1data[512 * 256]; + unsigned char r2data[512 * 256]; + unsigned char ordata[512 * 256]; + + printf("0350_orwrite_simple:\n"); + printf("===================\n"); + if (show_info) { + printf("Test basic ORWRITE functionality.\n"); + printf("1, Verify we can write the first 1-255 blocks of the LUN.\n"); + printf("2, Verify we can write the last 1-255 blocks of the LUN.\n"); + printf("\n"); + return 0; + } + + iscsi = iscsi_context_login(initiator, url, &lun); + if (iscsi == NULL) { + printf("Failed to login to target\n"); + return -1; + } + + /* find the size of the LUN */ + task = iscsi_readcapacity16_sync(iscsi, lun); + if (task == NULL) { + printf("Failed to send READCAPACITY16 command: %s\n", iscsi_get_error(iscsi)); + ret = -1; + goto finished; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("READCAPACITY16 command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + rc16 = scsi_datain_unmarshall(task); + if (rc16 == NULL) { + printf("failed to unmarshall READCAPACITY16 data. %s\n", iscsi_get_error(iscsi)); + ret = -1; + scsi_free_scsi_task(task); + goto finished; + } + block_size = rc16->block_length; + num_blocks = rc16->returned_lba; + scsi_free_scsi_task(task); + + + if (!data_loss) { + printf("--dataloss flag is not set. Skipping test\n"); + ret = -1; + goto finished; + } + + + ret = 0; + + + /* write the first 1 - 255 blocks at the start of the LUN */ + printf("Orwrite first 1-255 blocks ... "); + for (i = 1; i < 256; i++) { + task = iscsi_read16_sync(iscsi, lun, 0, i * block_size, block_size, 0, 0, 0, 0, 0); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send READ16 command: %s\n", iscsi_get_error(iscsi)); + ret++; + goto test2; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("READ16 command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret++; + scsi_free_scsi_task(task); + goto test2; + } + + if (task->datain.data == NULL) { + printf("[FAILED]\n"); + printf("Failed to access DATA-IN buffer %s\n", iscsi_get_error(iscsi)); + ret++; + scsi_free_scsi_task(task); + goto test2; + } + memcpy(r1data, task->datain.data, i * block_size); + memset(ordata, 0x5a, i * block_size); + for (j = 0; j < (int)(i * block_size); j++) { + r2data[j] = r1data[j] | ordata[j]; + } + scsi_free_scsi_task(task); + + task = iscsi_orwrite_sync(iscsi, lun, 0, ordata, i * block_size, block_size, 0, 0, 0, 0, 0); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send ORWRITE command: %s\n", iscsi_get_error(iscsi)); + ret++; + goto test2; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("ORWRITE command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret++; + scsi_free_scsi_task(task); + goto test2; + } + scsi_free_scsi_task(task); + + task = iscsi_read16_sync(iscsi, lun, 0, i * block_size, block_size, 0, 0, 0, 0, 0); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send READ16 command: %s\n", iscsi_get_error(iscsi)); + ret++; + goto test2; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("READ16 command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret++; + scsi_free_scsi_task(task); + goto test2; + } + + if (task->datain.data == NULL) { + printf("[FAILED]\n"); + printf("Failed to access DATA-IN buffer %s\n", iscsi_get_error(iscsi)); + ret++; + scsi_free_scsi_task(task); + goto test2; + } + + if (memcmp(r2data, task->datain.data, i * block_size)) { + printf("[FAILED]\n"); + printf("Blocks were not updated as expected.\n"); + ret++; + scsi_free_scsi_task(task); + goto test2; + } + + scsi_free_scsi_task(task); + } + printf("[OK]\n"); + + +test2: + /* write the last 1 - 255 blocks at the end of the LUN */ + printf("Compare and write last 1-255 blocks ... "); + for (i = 1; i < 256; i++) { + task = iscsi_read16_sync(iscsi, lun, num_blocks + 1 - i, i * block_size, block_size, 0, 0, 0, 0, 0); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send READ16 command: %s\n", iscsi_get_error(iscsi)); + ret++; + goto test3; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("READ16 command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret++; + scsi_free_scsi_task(task); + goto test3; + } + + if (task->datain.data == NULL) { + printf("[FAILED]\n"); + printf("Failed to access DATA-IN buffer %s\n", iscsi_get_error(iscsi)); + ret++; + scsi_free_scsi_task(task); + goto test3; + } + memcpy(r1data, task->datain.data, i * block_size); + memcpy(r1data, task->datain.data, i * block_size); + memset(ordata, 0xa5, i * block_size); + for (j = 0; j < (int)(i * block_size); j++) { + r2data[j] = r1data[j] | ordata[j]; + } + scsi_free_scsi_task(task); + + task = iscsi_orwrite_sync(iscsi, lun, num_blocks + 1 - i, ordata, i * block_size, block_size, 0, 0, 0, 0, 0); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send ORWRITE command: %s\n", iscsi_get_error(iscsi)); + ret++; + goto test3; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("ORWRITE command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret++; + scsi_free_scsi_task(task); + goto test3; + } + scsi_free_scsi_task(task); + task = iscsi_read16_sync(iscsi, lun, num_blocks + 1 - i, i * block_size, block_size, 0, 0, 0, 0, 0); + if (task == NULL) { + printf("[FAILED]\n"); + printf("Failed to send READ16 command: %s\n", iscsi_get_error(iscsi)); + ret++; + goto test3; + } + if (task->status != SCSI_STATUS_GOOD) { + printf("[FAILED]\n"); + printf("READ16 command: failed with sense. %s\n", iscsi_get_error(iscsi)); + ret++; + scsi_free_scsi_task(task); + goto test3; + } + + if (task->datain.data == NULL) { + printf("[FAILED]\n"); + printf("Failed to access DATA-IN buffer %s\n", iscsi_get_error(iscsi)); + ret++; + scsi_free_scsi_task(task); + goto test3; + } + + if (memcmp(r2data, task->datain.data, i * block_size)) { + printf("[FAILED]\n"); + printf("Blocks were not updated as expected.\n"); + ret++; + scsi_free_scsi_task(task); + goto test3; + } + + scsi_free_scsi_task(task); + } + printf("[OK]\n"); + +test3: + +finished: + iscsi_logout_sync(iscsi); + iscsi_destroy_context(iscsi); + return ret; +} diff --git a/test-tool/iscsi-test.c b/test-tool/iscsi-test.c index 16123c2..679b13c 100644 --- a/test-tool/iscsi-test.c +++ b/test-tool/iscsi-test.c @@ -162,6 +162,9 @@ struct scsi_test tests[] = { { "T0341_compareandwrite_mismatch", T0341_compareandwrite_mismatch }, { "T0343_compareandwrite_beyondeol", T0343_compareandwrite_beyondeol }, +/* orwrite*/ +{ "T0350_orwrite_simple", T0350_orwrite_simple }, + { NULL, NULL } }; diff --git a/test-tool/iscsi-test.h b/test-tool/iscsi-test.h index 062e0bb..2b9061c 100644 --- a/test-tool/iscsi-test.h +++ b/test-tool/iscsi-test.h @@ -118,3 +118,5 @@ int T0334_writeverify16_beyondeol(const char *initiator, const char *url, int da int T0340_compareandwrite_simple(const char *initiator, const char *url, int data_loss, int show_info); int T0341_compareandwrite_mismatch(const char *initiator, const char *url, int data_loss, int show_info); int T0343_compareandwrite_beyondeol(const char *initiator, const char *url, int data_loss, int show_info); + +int T0350_orwrite_simple(const char *initiator, const char *url, int data_loss, int show_info);