void test_read10_simple(void) { int i, ret; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test READ10 of 1-256 blocks at the start of the LUN"); for (i = 1; i <= 256; i++) { if (maximum_transfer_length && maximum_transfer_length < i) { break; } ret = read10(sd, NULL, 0, i * block_size, block_size, 0, 0, 0, 0, 0, NULL, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test READ10 of 1-256 blocks at the end of the LUN"); for (i = 1; i <= 256; i++) { if (maximum_transfer_length && maximum_transfer_length < i) { break; } ret = read10(sd, NULL, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, NULL, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } }
void test_verify10_mismatch_no_cmp(void) { int i, ret; unsigned char *buf = alloca(256 * block_size); logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test VERIFY10 without BYTCHK for blocks 1-255"); for (i = 1; i <= 256; i++) { int offset = random() % (i * block_size); if (maximum_transfer_length && maximum_transfer_length < i) { break; } ret = read10(sd, NULL, 0, i * block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); /* flip a random byte in the data */ buf[offset] ^= 'X'; logging(LOG_VERBOSE, "Flip some bits in the data"); ret = verify10(sd, 0, i * block_size, block_size, 0, 0, 0, buf, EXPECT_STATUS_GOOD); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] VERIFY10 is not implemented."); CU_PASS("[SKIPPED] Target does not support VERIFY10. Skipping test"); return; } CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test VERIFY10 without BYTCHK of 1-256 blocks at the end of the LUN"); for (i = 1; i <= 256; i++) { int offset = random() % (i * block_size); if (maximum_transfer_length && maximum_transfer_length < i) { break; } ret = read10(sd, NULL, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); /* flip a random byte in the data */ buf[offset] ^= 'X'; logging(LOG_VERBOSE, "Flip some bits in the data"); ret = verify10(sd, num_blocks - i, i * block_size, block_size, 0, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } }
void test_verify12_flags(void) { int ret; unsigned char *buf = alloca(block_size); logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test VERIFY12 flags"); ret = read10(iscsic, tgt_lun, 0, block_size, block_size, 0, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Test VERIFY12 with DPO==1"); ret = verify12(iscsic, tgt_lun, 0, block_size, block_size, 0, 1, 0, buf); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] VERIFY12 is not implemented."); CU_PASS("[SKIPPED] Target does not support VERIFY12. Skipping test"); return; } CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Test VERIFY12 with BYTCHK==1"); ret = verify12(iscsic, tgt_lun, 0, block_size, block_size, 0, 0, 1, buf); CU_ASSERT_EQUAL(ret, 0); }
void test_verify10_vrprotect(void) { int i, ret; unsigned char *buf = alloca(block_size); logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test VERIFY10 with non-zero VRPROTECT"); CHECK_FOR_SBC; if (!inq->protect || (rc16 != NULL && !rc16->prot_en)) { logging(LOG_VERBOSE, "Device does not support/use protection information. All commands should fail."); for (i = 1; i < 8; i++) { ret = read10(iscsic, tgt_lun, 0, block_size, block_size, 0, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); ret = verify10_invalidfieldincdb(iscsic, tgt_lun, 0, block_size, block_size, i, 0, 1, buf); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] VERIFY10 is not implemented."); CU_PASS("[SKIPPED] Target does not support VERIFY10. Skipping test"); return; } CU_ASSERT_EQUAL(ret, 0); } return; } logging(LOG_NORMAL, "No tests for devices that support protection information yet."); }
void test_read10_0blocks(void) { int ret; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test READ10 0-blocks at LBA==0"); ret = read10(iscsic, tgt_lun, 0, 0, block_size, 0, 0, 0, 0, 0, NULL); CU_ASSERT_EQUAL(ret, 0); if (num_blocks > 0x80000000) { CU_PASS("[SKIPPED] LUN is too big"); return; } logging(LOG_VERBOSE, "Test READ10 0-blocks one block past end-of-LUN"); ret = read10_lbaoutofrange(iscsic, tgt_lun, num_blocks + 1, 0, block_size, 0, 0, 0, 0, 0, NULL); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Test READ10 0-blocks at LBA==2^31"); ret = read10_lbaoutofrange(iscsic, tgt_lun, 0x80000000, 0, block_size, 0, 0, 0, 0, 0, NULL); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Test READ10 0-blocks at LBA==-1"); ret = read10_lbaoutofrange(iscsic, tgt_lun, -1, 0, block_size, 0, 0, 0, 0, 0, NULL); CU_ASSERT_EQUAL(ret, 0); }
int main(void) { usb_dev_handle *dev = NULL; /* the device handle */ uint8_t readBuffer[0x200*0x100]; /* Set up USB */ usb_init(); usb_find_busses(); usb_find_devices(); if (!(dev = open_dev())) { perror("device not found!\n"); exit(EXIT_FAILURE); } /* if (usb_set_configuration(dev, 1) < 0) { perror("setting config 1 failed\n"); usb_close(dev); exit(EXIT_FAILURE); } */ if (usb_claim_interface(dev, 0) < 0) { perror("claiming interface failed\n"); usb_close(dev); exit(EXIT_FAILURE); } //FIXME: sniffed read10(readBuffer,0x100,0x0,dev); printReadBuffer(readBuffer); /* Clean up */ usb_release_interface(dev, 0); usb_close(dev); exit(0); }
void test_verify10_flags(void) { int ret; unsigned char *buf = malloc(block_size); logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test VERIFY10 flags"); ret = read10(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Test VERIFY10 with BYTCHK==1"); ret = verify10(sd, 0, block_size, block_size, 0, 0, 1, buf, EXPECT_STATUS_GOOD); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] VERIFY10 is not implemented."); CU_PASS("[SKIPPED] Target does not support VERIFY10. Skipping test"); free(buf); return; } CU_ASSERT_EQUAL(ret, 0); free(buf); }
void test_writesame10_unmap_until_end(void) { int ret; unsigned int i; CHECK_FOR_DATALOSS; CHECK_FOR_THIN_PROVISIONING; CHECK_FOR_LBPWS10; CHECK_FOR_SBC; if (inq_bl->wsnz) { logging(LOG_NORMAL, "[SKIPPED] WRITESAME10 does not support 0-blocks."); CU_PASS("[SKIPPED] WRITESAME10 does not support 0-blocks."); return; } logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITESAME10 of 1-256 blocks at the end of the LUN by setting number-of-blocks==0"); for (i = 1; i <= 256; i++) { unsigned char *buf = malloc(block_size * i); logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i); memset(buf, 0xff, block_size * i); ret = write10(sd, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME10", i); ret = writesame10(sd, num_blocks - i, block_size, 0, 0, 1, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); if (rc16->lbprz) { logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped " "blocks back and verify they are all zero"); logging(LOG_VERBOSE, "Read %d blocks and verify they " "are now zero", i); ret = read10(sd, NULL, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT(all_zeroes(buf, i * block_size)); } else { logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read " "and verify zero test"); } free(buf); } }
void test_mandatory_sbc(void) { int ret; //unsigned char buf[4096]; //struct unmap_list list[1]; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test support for all mandatory opcodes on SBC devices"); CHECK_FOR_SBC; logging(LOG_VERBOSE, "Test INQUIRY."); ret = inquiry(sd, NULL, 0, 0, 255, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Test READCAPACITY10."); ret = readcapacity10(sd, NULL, 0, 0, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); if (sbc3_support) { logging(LOG_VERBOSE, "Test READCAPACITY16. The device claims SBC-3 support."); ret = readcapacity16(sd, NULL, 15, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test READ10."); ret = read10(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, NULL, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); if (sbc3_support) { logging(LOG_VERBOSE, "Test READ16. the device claims SBC-3 support."); ret = read16(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, NULL, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test TESTUNITREADY."); ret = testunitready(sd, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); }
void test_verify12_simple(void) { int i, ret; unsigned char *buf = alloca(256 * block_size); logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test VERIFY12 of 1-256 blocks at the start of the LUN"); for (i = 1; i <= 256; i++) { if (maximum_transfer_length && maximum_transfer_length < i) { break; } ret = read10(sd, NULL, 0, i * block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); ret = verify12(sd, 0, i * block_size, block_size, 0, 0, 1, buf, EXPECT_STATUS_GOOD); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] VERIFY12 is not implemented."); CU_PASS("[SKIPPED] Target does not support VERIFY12. Skipping test"); return; } CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test VERIFY12 of 1-256 blocks at the end of the LUN"); for (i = 1; i <= 256; i++) { if (maximum_transfer_length && maximum_transfer_length < i) { break; } ret = read12(sd, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); ret = verify12(sd, num_blocks - i, i * block_size, block_size, 0, 0, 1, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } }
void test_write10_residuals(void) { struct scsi_task *task_ret; unsigned char buf[10000]; struct iscsi_data data; int ret; unsigned int i; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITE10 commands with residuals"); logging(LOG_VERBOSE, "Block size is %zu", block_size); CHECK_FOR_DATALOSS; CHECK_FOR_SBC; /* Try a write10 of 1 block but xferlength == 0 */ task = malloc(sizeof(struct scsi_task)); CU_ASSERT_PTR_NOT_NULL(task); memset(task, 0, sizeof(struct scsi_task)); task->cdb[0] = SCSI_OPCODE_WRITE10; task->cdb[8] = 1; task->cdb_size = 10; task->xfer_dir = SCSI_XFER_WRITE; task->expxferlen = 0; /* * we don't want autoreconnect since some targets will drop the session * on this condition. */ iscsi_set_noautoreconnect(iscsic, 1); logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==0"); task_ret = iscsi_scsi_command_sync(iscsic, tgt_lun, task, NULL); CU_ASSERT_PTR_NOT_NULL(task_ret); CU_ASSERT_NOT_EQUAL(task->status, SCSI_STATUS_CANCELLED); /* XXX redundant? */ 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] WRITE10 is not implemented."); CU_PASS("WRITE10 is not implemented."); return; } logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); if (task->status != SCSI_STATUS_GOOD) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(iscsic)); } CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { logging(LOG_VERBOSE, "[FAILED] Target did not set residual " "overflow flag"); } CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow", block_size); if (task->residual != block_size) { logging(LOG_VERBOSE, "[FAILED] Target did not set correct " "amount of residual. Expected %zu but got %zu.", block_size, task->residual); } CU_ASSERT_EQUAL(task->residual, block_size); scsi_free_scsi_task(task); task = NULL; /* in case the previous test failed the session */ iscsi_set_noautoreconnect(iscsic, 0); logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==10000"); task = malloc(sizeof(struct scsi_task)); CU_ASSERT_PTR_NOT_NULL(task); memset(task, 0, sizeof(struct scsi_task)); task->cdb[0] = SCSI_OPCODE_WRITE10; task->cdb[8] = 1; task->cdb_size = 10; task->xfer_dir = SCSI_XFER_WRITE; task->expxferlen = 10000; data.size = task->expxferlen; data.data = &buf[0]; task_ret = iscsi_scsi_command_sync(iscsic, tgt_lun, task, &data); CU_ASSERT_PTR_NOT_NULL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); if (task->status != SCSI_STATUS_GOOD) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(iscsic)); } CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); logging(LOG_VERBOSE, "Verify residual underflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { logging(LOG_VERBOSE, "[FAILED] Target did not set residual " "underflow flag"); } CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW); logging(LOG_VERBOSE, "Verify we got %zu bytes of residual underflow", 10000 - block_size); if (task->residual != 10000 - block_size) { logging(LOG_VERBOSE, "[FAILED] Target did not set correct " "amount of residual. Expected %zu but got %zu.", 10000 - block_size, task->residual); } CU_ASSERT_EQUAL(task->residual, 10000 - block_size); scsi_free_scsi_task(task); task = NULL; logging(LOG_VERBOSE, "Try writing one block but with iSCSI expected transfer length==200"); task = malloc(sizeof(struct scsi_task)); CU_ASSERT_PTR_NOT_NULL(task); memset(task, 0, sizeof(struct scsi_task)); task->cdb[0] = SCSI_OPCODE_WRITE10; task->cdb[8] = 1; task->cdb_size = 10; task->xfer_dir = SCSI_XFER_WRITE; task->expxferlen = 200; data.size = task->expxferlen; data.data = &buf[0]; task_ret = iscsi_scsi_command_sync(iscsic, tgt_lun, task, &data); CU_ASSERT_PTR_NOT_NULL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); if (task->status != SCSI_STATUS_GOOD) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(iscsic)); } CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { logging(LOG_VERBOSE, "[FAILED] Target did not set residual " "overflow flag"); } CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); logging(LOG_VERBOSE, "Verify we got %zu bytes of residual overflow", block_size - 200); if (task->residual != block_size - 200) { logging(LOG_VERBOSE, "[FAILED] Target did not set correct " "amount of residual. Expected %zu but got %zu.", block_size - 200, task->residual); } CU_ASSERT_EQUAL(task->residual, block_size - 200); scsi_free_scsi_task(task); task = NULL; logging(LOG_VERBOSE, "Try writing two blocks but iSCSI expected " "transfer length==%zu (==one block)", block_size); task = malloc(sizeof(struct scsi_task)); CU_ASSERT_PTR_NOT_NULL(task); memset(task, 0, sizeof(struct scsi_task)); task->cdb[0] = SCSI_OPCODE_WRITE10; task->cdb[8] = 2; task->cdb_size = 10; task->xfer_dir = SCSI_XFER_WRITE; task->expxferlen = block_size; data.size = task->expxferlen; data.data = &buf[0]; task_ret = iscsi_scsi_command_sync(iscsic, tgt_lun, task, &data); CU_ASSERT_PTR_NOT_NULL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); if (task->status != SCSI_STATUS_GOOD) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(iscsic)); } CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { logging(LOG_VERBOSE, "[FAILED] Target did not set residual " "overflow flag"); } CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); logging(LOG_VERBOSE, "Verify we got one block of residual overflow"); if (task->residual != block_size) { logging(LOG_VERBOSE, "[FAILED] Target did not set correct " "amount of residual. Expected %zu but got %zu.", block_size, task->residual); } CU_ASSERT_EQUAL(task->residual, block_size); scsi_free_scsi_task(task); task = NULL; logging(LOG_VERBOSE, "Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data"); logging(LOG_VERBOSE, "Write two blocks of 'a'"); memset(buf, 'a', 10000); ret = write10(iscsic, tgt_lun, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Write one block of 'b' but set iSCSI EDTL to 2 blocks."); task = malloc(sizeof(struct scsi_task)); CU_ASSERT_PTR_NOT_NULL(task); memset(buf, 'b', 10000); memset(task, 0, sizeof(struct scsi_task)); task->cdb[0] = SCSI_OPCODE_WRITE10; task->cdb[8] = 1; task->cdb_size = 10; task->xfer_dir = SCSI_XFER_WRITE; task->expxferlen = 2 * block_size; data.size = task->expxferlen; data.data = &buf[0]; task_ret = iscsi_scsi_command_sync(iscsic, tgt_lun, task, &data); CU_ASSERT_PTR_NOT_NULL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); if (task->status != SCSI_STATUS_GOOD) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(iscsic)); } CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); logging(LOG_VERBOSE, "Verify residual underflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_UNDERFLOW) { logging(LOG_VERBOSE, "[FAILED] Target did not set residual " "underflow flag"); } CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_UNDERFLOW); logging(LOG_VERBOSE, "Verify we got one block of residual underflow"); if (task->residual != block_size) { logging(LOG_VERBOSE, "[FAILED] Target did not set correct " "amount of residual. Expected %zu but got %zu.", block_size, task->residual); } CU_ASSERT_EQUAL(task->residual, block_size); scsi_free_scsi_task(task); task = NULL; logging(LOG_VERBOSE, "Read the two blocks"); ret = read10(iscsic, tgt_lun, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'"); for (i = 0; i < block_size; i++) { if (buf[i] != 'b') { logging(LOG_NORMAL, "First block did not contain expected 'b'"); CU_FAIL("Block was not written correctly"); break; } } logging(LOG_VERBOSE, "Verify that the second block was NOT overwritten and still contains 'a'"); for (i = block_size; i < 2 * block_size; i++) { if (buf[i] != 'a') { logging(LOG_NORMAL, "Second block was overwritten and no longer contain 'a'"); CU_FAIL("Second block was incorrectly overwritten"); break; } } logging(LOG_VERBOSE, "Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data"); logging(LOG_VERBOSE, "Write two blocks of 'a'"); memset(buf, 'a', 10000); ret = write10(iscsic, tgt_lun, 0, 2 * block_size, block_size, 0, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Write two blocks of 'b' but set iSCSI EDTL to 1 blocks."); task = malloc(sizeof(struct scsi_task)); CU_ASSERT_PTR_NOT_NULL(task); memset(buf, 'b', 10000); memset(task, 0, sizeof(struct scsi_task)); task->cdb[0] = SCSI_OPCODE_WRITE10; task->cdb[8] = 2; task->cdb_size = 10; task->xfer_dir = SCSI_XFER_WRITE; task->expxferlen = block_size; data.size = task->expxferlen; data.data = &buf[0]; task_ret = iscsi_scsi_command_sync(iscsic, tgt_lun, task, &data); CU_ASSERT_PTR_NOT_NULL(task_ret); logging(LOG_VERBOSE, "Verify that the target returned SUCCESS"); if (task->status != SCSI_STATUS_GOOD) { logging(LOG_VERBOSE, "[FAILED] Target returned error %s", iscsi_get_error(iscsic)); } CU_ASSERT_EQUAL(task->status, SCSI_STATUS_GOOD); logging(LOG_VERBOSE, "Verify residual overflow flag is set"); if (task->residual_status != SCSI_RESIDUAL_OVERFLOW) { logging(LOG_VERBOSE, "[FAILED] Target did not set residual " "overflow flag"); } CU_ASSERT_EQUAL(task->residual_status, SCSI_RESIDUAL_OVERFLOW); logging(LOG_VERBOSE, "Verify we got one block of residual overflow"); if (task->residual != block_size) { logging(LOG_VERBOSE, "[FAILED] Target did not set correct " "amount of residual. Expected %zu but got %zu.", block_size, task->residual); } CU_ASSERT_EQUAL(task->residual, block_size); scsi_free_scsi_task(task); task = NULL; logging(LOG_VERBOSE, "Read the two blocks"); ret = read10(iscsic, tgt_lun, 0, 2* block_size, block_size, 0, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Verify that the first block was changed to 'b'"); for (i = 0; i < block_size; i++) { if (buf[i] != 'b') { logging(LOG_NORMAL, "First block did not contain expected 'b'"); CU_FAIL("Block was not written correctly"); break; } } logging(LOG_VERBOSE, "Verify that the second block was NOT overwritten and still contains 'a'"); for (i = block_size; i < 2 * block_size; i++) { if (buf[i] != 'a') { logging(LOG_NORMAL, "Second block was overwritten and no longer contain 'a'"); CU_FAIL("Second block was incorrectly overwritten"); break; } } }
void test_modesense6_control_swp(void) { struct scsi_task *ms_task = NULL; struct scsi_mode_sense *ms; struct scsi_mode_page *page; unsigned char *buf = alloca(block_size); int ret; CHECK_FOR_DATALOSS; CHECK_FOR_SBC; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test of MODESENSE6 CONTROL SWP flag"); logging(LOG_VERBOSE, "Set SWP to enable write protect"); ret = set_swp(sd); if (ret == -2) { CU_PASS("[SKIPPED] Target does not support changing SWP"); return; } CU_ASSERT_EQUAL(ret, 0); if (ret) { goto finished; } logging(LOG_VERBOSE, "Read the CONTROL page back from the device"); ret = modesense6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODEPAGE_CONTROL, 0, 255, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "[SUCCESS] CONTROL page fetched."); logging(LOG_VERBOSE, "Try to unmarshall the DATA-IN buffer."); ms = scsi_datain_unmarshall(ms_task); if (ms == NULL) { logging(LOG_NORMAL, "[FAILED] failed to unmarshall mode sense " "datain buffer"); CU_FAIL("[FAILED] Failed to unmarshall the data-in buffer."); goto finished; } logging(LOG_VERBOSE, "[SUCCESS] Unmarshalling successful."); for (page = ms->pages; page; page = page->next) { if (page->page_code == SCSI_MODEPAGE_CONTROL) { break; } } if(page == NULL) { logging(LOG_NORMAL, "[WARNING] CONTROL page was not returned." "All devices SHOULD implement this page."); } logging(LOG_VERBOSE, "Verify that the SWP bit is set"); if (page->control.swp == 0) { logging(LOG_NORMAL, "[FAILED] SWP bit is not set"); CU_FAIL("[FAILED] SWP is not set"); goto finished; } logging(LOG_VERBOSE, "[SUCCESS] SWP was set successfully"); logging(LOG_VERBOSE, "Read a block from the now Read-Only device"); ret = read10(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Try to write a block to the Read-Only device"); ret = write10(sd, 0, block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_WRITE_PROTECTED); CU_ASSERT_EQUAL(ret, 0); finished: if (ms_task != NULL) { scsi_free_scsi_task(ms_task); } logging(LOG_VERBOSE, "Clear SWP to disable write protect"); clear_swp(sd); }
void test_compareandwrite_dpofua(void) { int ret, dpofua, usage_data_dpofua; struct scsi_task *ms_task = NULL; struct scsi_mode_sense *ms; struct scsi_task *rso_task = NULL; struct scsi_report_supported_op_codes_one_command *rsoc; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test COMPAREANDWRITE DPO/FUA flags"); CHECK_FOR_SBC; CHECK_FOR_DATALOSS; logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data"); MODESENSE6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255, EXPECT_STATUS_GOOD); logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD"); ms = scsi_datain_unmarshall(ms_task); dpofua = ms && (ms->device_specific_parameter & 0x10); scsi_free_scsi_task(ms_task); logging(LOG_VERBOSE, "Read the first block"); ret = read10(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, scratch, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); if (ret == 0) memcpy(scratch + block_size, scratch, block_size); else memset(scratch, 0xa6, 2 * block_size); if (dpofua) { logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow " "DPO/FUA flags in CDBs"); } else { logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail " "CDBs with DPO/FUA set"); } logging(LOG_VERBOSE, "Test COMPAREANDWRITE with DPO==1"); if (dpofua) { COMPAREANDWRITE(sd, 0, scratch, 2 * block_size, block_size, 0, 1, 0, 0, EXPECT_STATUS_GOOD); } else { COMPAREANDWRITE(sd, 0, scratch, 2 * block_size, block_size, 0, 1, 0, 0, EXPECT_INVALID_FIELD_IN_CDB); } logging(LOG_VERBOSE, "Test COMPAREANDWRITE with FUA==1"); if (dpofua) { COMPAREANDWRITE(sd, 0, scratch, 2 * block_size, block_size, 0, 0, 1, 0, EXPECT_STATUS_GOOD); } else { COMPAREANDWRITE(sd, 0, scratch, 2 * block_size, block_size, 0, 0, 1, 0, EXPECT_INVALID_FIELD_IN_CDB); } logging(LOG_VERBOSE, "Test COMPAREANDWRITE with DPO==1 FUA==1"); if (dpofua) { COMPAREANDWRITE(sd, 0, scratch, 2 * block_size, block_size, 0, 1, 1, 0, EXPECT_STATUS_GOOD); } else { COMPAREANDWRITE(sd, 0, scratch, 2 * block_size, block_size, 0, 1, 1, 0, EXPECT_INVALID_FIELD_IN_CDB); } logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES " "for COMPAREANDWRITE"); REPORT_SUPPORTED_OPCODES(sd, &rso_task, 0, SCSI_REPORT_SUPPORTING_OPCODE, SCSI_OPCODE_COMPARE_AND_WRITE, 0, 65535, EXPECT_STATUS_GOOD); logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer"); rsoc = scsi_datain_unmarshall(rso_task); CU_ASSERT_PTR_NOT_NULL_FATAL(rsoc); usage_data_dpofua = rsoc->cdb_usage_data[1] & 0x18; if (dpofua) { logging(LOG_VERBOSE, "DPOFUA is set. Verify the " "DPO/FUA flags are set in the CDB_USAGE_DATA"); if (!usage_data_dpofua) { logging(LOG_NORMAL, "[FAILED] DpoFua not set " "in CDB_USAGE_DATE"); CU_FAIL("DpoFua not set in CDB_USAGE_DATE"); } } else { logging(LOG_VERBOSE, "DPOFUA is clear. Verify the " "DPO/FUA flags are clear in the CDB_USAGE_DATA"); if (usage_data_dpofua) { logging(LOG_NORMAL, "[FAILED] DpoFua not clear " "in CDB_USAGE_DATE"); CU_FAIL("DpoFua not clear in CDB_USAGE_DATE"); } } scsi_free_scsi_task(rso_task); }
void test_verify10_dpo(void) { int ret, dpofua, usage_data_dpo; struct scsi_task *ms_task = NULL; struct scsi_mode_sense *ms; struct scsi_task *rso_task = NULL; struct scsi_report_supported_op_codes_one_command *rsoc; unsigned char *buf = alloca(block_size); logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test VERIFY10 DPO flag"); CHECK_FOR_SBC; ret = read10(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data"); ret = modesense6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD"); ms = scsi_datain_unmarshall(ms_task); dpofua = ms && (ms->device_specific_parameter & 0x10); scsi_free_scsi_task(ms_task); if (dpofua) { logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow " "DPO/FUA flags in CDBs"); } else { logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail " "CDBs with DPO/FUA set"); } logging(LOG_VERBOSE, "Test VERIFY10 with DPO==1"); if (dpofua) { ret = verify10(sd, 0, block_size, block_size, 0, 1, 0, buf, EXPECT_STATUS_GOOD); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] VERIFY10 is not implemented."); CU_PASS("VERIFY10 is not implemented."); return; } CU_ASSERT_EQUAL(ret, 0); } else { ret = verify10(sd, 0, block_size, block_size, 0, 1, 0, buf, EXPECT_INVALID_FIELD_IN_CDB); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] VERIFY10 is not implemented."); CU_PASS("VERIFY10 is not implemented."); return; } CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES " "for VERIFY10"); ret = report_supported_opcodes(sd, &rso_task, 0, SCSI_REPORT_SUPPORTING_OPCODE, SCSI_OPCODE_VERIFY10, 0, 65535, EXPECT_STATUS_GOOD); if (ret == -2) { logging(LOG_NORMAL, "REPORT_SUPPORTED_OPCODES not implemented. " "Skipping this part of the test"); return; } logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer"); rsoc = scsi_datain_unmarshall(rso_task); CU_ASSERT_NOT_EQUAL(rsoc, NULL); usage_data_dpo = rsoc ? rsoc->cdb_usage_data[1] & 0x10 : -1; if (dpofua) { logging(LOG_VERBOSE, "DPOFUA is set. Verify the DPO flag " "is set in the CDB_USAGE_DATA"); CU_ASSERT_EQUAL(usage_data_dpo, 0x10); } else { logging(LOG_VERBOSE, "DPOFUA is clear. Verify the DPO " "flag is clear in the CDB_USAGE_DATA"); CU_ASSERT_EQUAL(usage_data_dpo, 0x00); } scsi_free_scsi_task(rso_task); }
void test_compareandwrite_dpofua(void) { int ret, dpofua, usage_data_dpofua; struct scsi_task *ms_task = NULL; struct scsi_mode_sense *ms; struct scsi_task *rso_task = NULL; struct scsi_report_supported_op_codes_one_command *rsoc; unsigned char *buf = alloca(2 * block_size); logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test COMPAREANDWRITE DPO/FUA flags"); CHECK_FOR_SBC; CHECK_FOR_DATALOSS; logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data"); ret = modesense6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD"); ms = scsi_datain_unmarshall(ms_task); dpofua = ms && (ms->device_specific_parameter & 0x10); scsi_free_scsi_task(ms_task); logging(LOG_VERBOSE, "Read the first block"); ret = read10(sd, NULL, 0, block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); if (ret == 0) memcpy(buf + block_size, buf, block_size); else memset(buf, 0xa6, 2 * block_size); if (dpofua) { logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow " "DPO/FUA flags in CDBs"); } else { logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail " "CDBs with DPO/FUA set"); } logging(LOG_VERBOSE, "Test COMPAREANDWRITE with DPO==1"); if (dpofua) { ret = compareandwrite(sd, 0, buf, 2 * block_size, block_size, 0, 1, 0, 0, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } else { ret = compareandwrite(sd, 0, buf, 2 * block_size, block_size, 0, 1, 0, 0, EXPECT_INVALID_FIELD_IN_CDB); CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test COMPAREANDWRITE with FUA==1"); if (dpofua) { ret = compareandwrite(sd, 0, buf, 2 * block_size, block_size, 0, 0, 1, 0, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } else { ret = compareandwrite(sd, 0, buf, 2 * block_size, block_size, 0, 0, 1, 0, EXPECT_INVALID_FIELD_IN_CDB); CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test COMPAREANDWRITE with DPO==1 FUA==1"); if (dpofua) { ret = compareandwrite(sd, 0, buf, 2 * block_size, block_size, 0, 1, 1, 0, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } else { ret = compareandwrite(sd, 0, buf, 2 * block_size, block_size, 0, 1, 1, 0, EXPECT_INVALID_FIELD_IN_CDB); CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES " "for COMPAREANDWRITE"); ret = report_supported_opcodes(sd, &rso_task, 0, SCSI_REPORT_SUPPORTING_OPCODE, SCSI_OPCODE_COMPARE_AND_WRITE, 0, 65535, EXPECT_STATUS_GOOD); if (ret == -2) { logging(LOG_NORMAL, "REPORT_SUPPORTED_OPCODES not implemented. " "Skipping this part of the test"); return; } logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer"); rsoc = scsi_datain_unmarshall(rso_task); CU_ASSERT_NOT_EQUAL(rsoc, NULL); usage_data_dpofua = rsoc ? rsoc->cdb_usage_data[1] & 0x18 : -1; if (dpofua) { logging(LOG_VERBOSE, "DPOFUA is set. Verify the DPO/FUA flags " "are set in the CDB_USAGE_DATA"); CU_ASSERT_EQUAL(usage_data_dpofua, 0x18); } else { logging(LOG_VERBOSE, "DPOFUA is clear. Verify the DPO/FUA " "flags are clear in the CDB_USAGE_DATA"); CU_ASSERT_EQUAL(usage_data_dpofua, 0x00); } scsi_free_scsi_task(rso_task); }
void test_read10_dpofua(void) { int ret, dpofua, usage_data_dpofua; struct scsi_task *ms_task = NULL; struct scsi_mode_sense *ms; struct scsi_task *rso_task = NULL; struct scsi_report_supported_op_codes_one_command *rsoc; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test READ10 DPO/FUA flags"); CHECK_FOR_SBC; logging(LOG_VERBOSE, "Read the DPOFUA flag from mode sense data"); ret = modesense6(sd, &ms_task, 0, SCSI_MODESENSE_PC_CURRENT, SCSI_MODEPAGE_RETURN_ALL_PAGES, 0, 255, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "[SUCCESS] Mode sense returned status GOOD"); ms = scsi_datain_unmarshall(ms_task); dpofua = ms && (ms->device_specific_parameter & 0x10); scsi_free_scsi_task(ms_task); if (dpofua) { logging(LOG_VERBOSE, "DPOFUA flag is set. Device should allow " "DPO/FUA flags in CDBs"); } else { logging(LOG_VERBOSE, "DPOFUA flag is clear. Device should fail " "CDBs with DPO/FUA set"); } logging(LOG_VERBOSE, "Test READ10 with DPO==1"); if (dpofua) { ret = read10(sd, NULL, 0, block_size, block_size, 0, 1, 0, 0, 0, NULL, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } else { ret = read10(sd, NULL, 0, block_size, block_size, 0, 1, 0, 0, 0, NULL, EXPECT_INVALID_FIELD_IN_CDB); CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test READ10 with FUA==1"); if (dpofua) { ret = read10(sd, NULL, 0, block_size, block_size, 0, 0, 1, 0, 0, NULL, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } else { ret = read10(sd, NULL, 0, block_size, block_size, 0, 0, 1, 0, 0, NULL, EXPECT_INVALID_FIELD_IN_CDB); CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test READ10 with DPO==1 FUA==1"); if (dpofua) { ret = read10(sd, NULL, 0, block_size, block_size, 0, 1, 1, 0, 0, NULL, EXPECT_STATUS_GOOD); CU_ASSERT_EQUAL(ret, 0); } else { ret = read10(sd, NULL, 0, block_size, block_size, 0, 1, 1, 0, 0, NULL, EXPECT_INVALID_FIELD_IN_CDB); CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Try fetching REPORT_SUPPORTED_OPCODES " "for READ10"); ret = report_supported_opcodes(sd, &rso_task, 0, SCSI_REPORT_SUPPORTING_OPCODE, SCSI_OPCODE_READ10, 0, 65535, EXPECT_STATUS_GOOD); if (ret == -2) { logging(LOG_NORMAL, "REPORT_SUPPORTED_OPCODES not implemented. " "Skipping this part of the test"); return; } logging(LOG_VERBOSE, "Unmarshall the DATA-IN buffer"); rsoc = scsi_datain_unmarshall(rso_task); if (rsoc) { usage_data_dpofua = rsoc->cdb_usage_data[1] & 0x18; if (dpofua) { logging(LOG_VERBOSE, "DPOFUA is set. Verify the " "DPO/FUA flags are set in the CDB_USAGE_DATA"); if (!usage_data_dpofua) { logging(LOG_NORMAL, "[FAILED] DpoFua not set " "in CDB_USAGE_DATE"); CU_FAIL("DpoFua not set in CDB_USAGE_DATE"); } } else { logging(LOG_VERBOSE, "DPOFUA is clear. Verify the " "DPO/FUA flags are clear in the CDB_USAGE_DATA"); if (usage_data_dpofua) { logging(LOG_NORMAL, "[FAILED] DpoFua not clear " "in CDB_USAGE_DATE"); CU_FAIL("DpoFua not clear in CDB_USAGE_DATE"); } } } else { logging(LOG_NORMAL, "[FAILED] Target did not return any data " "for ReportSupportedOpcodes\n"); CU_FAIL("Target did not return any data for " "ReportSupportedOpcodes"); } scsi_free_scsi_task(rso_task); }
void test_orwrite_verify(void) { int i, ret; unsigned char *buf = alloca(256 * block_size); unsigned char *readbuf = alloca(256 * block_size); CHECK_FOR_DATALOSS; CHECK_FOR_SBC; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the start of the LUN"); for (i = 1; i <= 256; i++) { if (maximum_transfer_length && maximum_transfer_length < i) { break; } logging(LOG_VERBOSE, "Write %d blocks of all-zero", i); memset(buf, 0, block_size * i); ret = write10(iscsic, tgt_lun, 0, i * block_size, block_size, 0, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "OrWrite %d blocks with 0xa5", i); memset(buf, 0xa5, block_size * i); ret = orwrite(iscsic, tgt_lun, 0, i * block_size, block_size, 0, 0, 0, 0, 0, buf); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] ORWRITE is not implemented."); CU_PASS("ORWRITE is not implemented."); return; } CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Read %d blocks back", i); ret = read10(iscsic, tgt_lun, 0, i * block_size, block_size, 0, 0, 0, 0, 0, readbuf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Verify that the blocks are all 0xa5"); ret = memcmp(buf, readbuf, block_size * i); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "OrWrite %d blocks with 0x5a", i); memset(buf, 0x5a, block_size * i); ret = orwrite(iscsic, tgt_lun, 0, i * block_size, block_size, 0, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Read %d blocks back", i); ret = read10(iscsic, tgt_lun, 0, i * block_size, block_size, 0, 0, 0, 0, 0, readbuf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Verify that the blocks are all 0xff"); memset(buf, 0xff, block_size * i); ret = memcmp(buf, readbuf, block_size * i); CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test ORWRITE of 1-256 blocks at the end of the LUN"); for (i = 1; i <= 256; i++) { if (maximum_transfer_length && maximum_transfer_length < i) { break; } logging(LOG_VERBOSE, "Write %d blocks of all-zero", i); memset(buf, 0, block_size * i); ret = write16(iscsic, tgt_lun, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "OrWrite %d blocks with 0xa5", i); memset(buf, 0xa5, block_size * i); ret = orwrite(iscsic, tgt_lun, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Read %d blocks back", i); ret = read16(iscsic, tgt_lun, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, readbuf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Verify that the blocks are all 0xa5"); ret = memcmp(buf, readbuf, block_size * i); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "OrWrite %d blocks with 0x5a", i); memset(buf, 0x5a, block_size * i); ret = orwrite(iscsic, tgt_lun, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Read %d blocks back", i); ret = read16(iscsic, tgt_lun, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, readbuf); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Verify that the blocks are all 0xff"); memset(buf, 0xff, block_size * i); ret = memcmp(buf, readbuf, block_size * i); CU_ASSERT_EQUAL(ret, 0); } }