void test_writesame16_simple(void) { int i, ret; unsigned char *buf = alloca(block_size); CHECK_FOR_DATALOSS; CHECK_FOR_SBC; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITESAME16 of 1-256 blocks at the start of the LUN"); for (i = 1; i <= 256; i++) { ret = writesame16(iscsic, tgt_lun, 0, block_size, i, 0, 0, 0, 0, buf); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] WRITEVERIFY16 is not implemented."); CU_PASS("[SKIPPED] Target does not support WRITESAME16. Skipping test"); return; } CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test WRITESAME16 of 1-256 blocks at the end of the LUN"); for (i = 1; i <= 256; i++) { ret = writesame16(iscsic, tgt_lun, num_blocks - i, block_size, i, 0, 0, 0, 0, buf); CU_ASSERT_EQUAL(ret, 0); } }
void test_writesame16_wrprotect(void) { int i, ret; unsigned char *buf = alloca(block_size); /* * Try out different non-zero values for WRPROTECT. */ logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITESAME16 with non-zero WRPROTECT"); CHECK_FOR_DATALOSS; CHECK_FOR_SBC; memset(buf, 0, block_size); 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 = writesame16(sd, 0, block_size, 1, 0, 0, i, 0, buf, EXPECT_INVALID_FIELD_IN_CDB); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] WRITESAME16 is not implemented."); CU_PASS("[SKIPPED] Target does not support WRITESAME16. Skipping test"); return; } CU_ASSERT_EQUAL(ret, 0); } return; } logging(LOG_NORMAL, "No tests for devices that support protection information yet."); }
void test_writesame16_unmap_until_end(void) { int ret; unsigned int i, j; unsigned char *buf = alloca(256 * block_size); unsigned char *zeroBlock; CHECK_FOR_DATALOSS; CHECK_FOR_THIN_PROVISIONING; CHECK_FOR_LBPWS; CHECK_FOR_SBC; zeroBlock = malloc(block_size); memset(zeroBlock, 0, block_size); logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITESAME16 of 1-256 blocks at the end of the LUN by setting number-of-blocks==0"); for (i = 1; i <= 256; i++) { logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i); memset(buf, 0xff, block_size * i); ret = write16(iscsic, tgt_lun, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, buf); logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i); ret = writesame16(iscsic, tgt_lun, num_blocks - i, 0, i, 0, 1, 0, 0, NULL); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] WRITESAME16 is not implemented."); CU_PASS("[SKIPPED] Target does not support WRITESAME16. Skipping test"); return; } 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 = read16(iscsic, tgt_lun, num_blocks - i, i * block_size, block_size, 0, 0, 0, 0, 0, buf); for (j = 0; j < i; j++) { CU_ASSERT_EQUAL(memcmp(buf + j*block_size, zeroBlock, block_size), 0); } } else { logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read " "and verify zero test"); } } free(zeroBlock); }
void test_writesame16_unmap_vpd(void) { int ret; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITESAME16 UNMAP availability is " "consistent with VPD settings"); CHECK_FOR_DATALOSS; CHECK_FOR_SBC; logging(LOG_VERBOSE, "Check if WRITESAME16 can be used for UNMAP."); logging(LOG_VERBOSE, "Unmap 1 block using WRITESAME16"); memset(scratch, 0, block_size); ret = writesame16(sd, 0, block_size, 1, 0, 1, 0, 0, scratch, EXPECT_STATUS_GOOD); if (ret != 0) { logging(LOG_VERBOSE, "WRITESAME16 UNMAP is not available. " "Verify that VPD settings reflect this."); logging(LOG_VERBOSE, "Verify that LBPWS is clear."); if (inq_lbp && inq_lbp->lbpws) { logging(LOG_NORMAL, "[FAILED] WRITESAME16 UNMAP is not " "implemented but LBPWS is set"); CU_FAIL("[FAILED] WRITESAME16 UNMAP is unavailable but " "LBPWS==1"); } else { logging(LOG_VERBOSE, "[SUCCESS] LBPWS is clear."); } } else { logging(LOG_VERBOSE, "WRITESAME16 UNMAP is available. Verify " "that VPD settings reflect this."); logging(LOG_VERBOSE, "Verify that LBPME is set."); if (rc16 && rc16->lbpme) { logging(LOG_VERBOSE, "[SUCCESS] LBPME is set."); } else { logging(LOG_NORMAL, "[FAILED] WRITESAME16 UNMAP is " "implemented but LBPME is not set"); CU_FAIL("[FAILED] UNMAP is available but LBPME==0"); } logging(LOG_VERBOSE, "Verify that LBPWS is set."); if (inq_lbp && inq_lbp->lbpws) { logging(LOG_VERBOSE, "[SUCCESS] LBPWS is set."); } else { logging(LOG_NORMAL, "[FAILED] WRITESAME16 UNMAP is " "implemented but LBPWS is not set"); CU_FAIL("[FAILED] UNMAP is available but LBPWS==0"); } } }
void test_writesame16_0blocks(void) { int ret; CHECK_FOR_DATALOSS; CHECK_FOR_SBC; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITESAME16 0-blocks at LBA==0 (WSNZ=%d)", inq_bl->wsnz); ret = writesame16(iscsic, tgt_lun, 0, block_size, 0, 0, 0, 0, 0, NULL); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] WRITESAME16 is not implemented."); CU_PASS("[SKIPPED] Target does not support WRITESAME16. Skipping test"); return; } else if (ret == -3) { CU_PASS("[SKIPPED] Target does not support WRITESAME16 with NUMBER OF LOGICAL BLOCKS == 0"); } else if (ret == -4) { CU_PASS("[SKIPPED] Number of WRITESAME16 logical blocks to be written exceeds MAXIMUM WRITE SAME LENGTH"); } else { if (inq_bl->wsnz) { CU_ASSERT_EQUAL(ret, -1); } else { CU_ASSERT_EQUAL(ret, 0); } } logging(LOG_VERBOSE, "Test WRITESAME16 0-blocks one block past end-of-LUN"); ret = writesame16_lbaoutofrange(iscsic, tgt_lun, num_blocks + 1, block_size, inq_bl->wsnz, 0, 0, 0, 0, NULL); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Test WRITESAME16 0-blocks at LBA==2^63"); ret = writesame16_lbaoutofrange(iscsic, tgt_lun, 0x8000000000000000ULL, block_size, inq_bl->wsnz, 0, 0, 0, 0, NULL); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Test WRITESAME16 0-blocks at LBA==-1"); ret = writesame16_lbaoutofrange(iscsic, tgt_lun, -1, block_size, inq_bl->wsnz, 0, 0, 0, 0, NULL); CU_ASSERT_EQUAL(ret, 0); }
void test_writesame16_unmap(void) { int ret; unsigned int i; unsigned char *buf; CHECK_FOR_DATALOSS; CHECK_FOR_THIN_PROVISIONING; CHECK_FOR_LBPWS; CHECK_FOR_SBC; logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITESAME16 of 1-256 blocks at the start of the LUN"); buf = calloc(65536, block_size); for (i = 1; i <= 256; i++) { logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i); memset(buf, 0xff, i * block_size); ret = write16(sd, 0, i * block_size, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i); memset(buf, 0, block_size); ret = writesame16(sd, 0, block_size, i, 0, 1, 0, 0, buf, EXPECT_STATUS_GOOD); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] WRITESAME16 is not implemented."); CU_PASS("[SKIPPED] Target does not support WRITESAME16. Skipping test"); goto finished; } 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 = read16(sd, NULL, 0, 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"); } } logging(LOG_VERBOSE, "Test WRITESAME16 of 1-256 blocks at the end of the LUN"); for (i = 1; i <= 256; i++) { logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i); memset(buf, 0xff, i * block_size); ret = write16(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 WRITESAME16", i); memset(buf, 0, block_size); ret = writesame16(sd, num_blocks - i, block_size, i, 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 = read16(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"); } } logging(LOG_VERBOSE, "Verify that WRITESAME16 ANCHOR==1 + UNMAP==0 is invalid"); ret = writesame16(sd, 0, block_size, 1, 1, 0, 0, 0, buf, EXPECT_INVALID_FIELD_IN_CDB); CU_ASSERT_EQUAL(ret, 0); if (inq_lbp->anc_sup) { logging(LOG_VERBOSE, "Test WRITESAME16 ANCHOR==1 + UNMAP==0"); memset(buf, 0, block_size); ret = writesame16(sd, 0, block_size, 1, 1, 1, 0, 0, buf, EXPECT_STATUS_GOOD); } else { logging(LOG_VERBOSE, "Test WRITESAME16 ANCHOR==1 + UNMAP==0 no ANC_SUP so expecting to fail"); ret = writesame16(sd, 0, block_size, 1, 1, 1, 0, 0, buf, EXPECT_INVALID_FIELD_IN_CDB); } CU_ASSERT_EQUAL(ret, 0); if (inq_bl == NULL) { logging(LOG_VERBOSE, "[FAILED] WRITESAME16 works but " "BlockLimits VPD is missing."); CU_FAIL("[FAILED] WRITESAME16 works but " "BlockLimits VPD is missing."); goto finished; } i = 256; if (i <= num_blocks && (inq_bl->max_ws_len == 0 || inq_bl->max_ws_len >= i)) { logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN " "as either 0 (==no limit) or >= %d. Test Unmapping " "%d blocks to verify that it can handle 2-byte " "lengths", i, i); logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i); memset(buf, 0xff, i * block_size); ret = write16(sd, 0, 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 WRITESAME16", i); memset(buf, 0, block_size); ret = writesame16(sd, 0, block_size, i, 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 = read16(sd, NULL, 0, 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"); } } else if (i <= num_blocks) { logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN " "as <256. Verify that a 256 block unmap fails with " "INVALID_FIELD_IN_CDB."); logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i); ret = writesame16(sd, 0, block_size, i, 0, 1, 0, 0, buf, EXPECT_INVALID_FIELD_IN_CDB); CU_ASSERT_EQUAL(ret, 0); } i = 65536; if (i <= num_blocks && (inq_bl->max_ws_len == 0 || inq_bl->max_ws_len >= i)) { logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN " "as either 0 (==no limit) or >= %d. Test Unmapping " "%d blocks to verify that it can handle 4-byte " "lengths", i, i); logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i); memset(buf, 0xff, i * block_size); ret = write16(sd, 0, 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 WRITESAME16", i); memset(buf, 0, block_size); ret = writesame16(sd, 0, block_size, i, 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 = read16(sd, NULL, 0, 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"); } } else if (i <= num_blocks) { logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN " "as <256. Verify that a 256 block unmap fails with " "INVALID_FIELD_IN_CDB."); logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i); ret = writesame16(sd, 0, block_size, i, 0, 1, 0, 0, buf, EXPECT_INVALID_FIELD_IN_CDB); CU_ASSERT_EQUAL(ret, 0); } finished: free(buf); }
void test_writesame16_0blocks(void) { int ret; unsigned char *buf = alloca(block_size); CHECK_FOR_DATALOSS; CHECK_FOR_SBC; if (!inq_bl) { CU_PASS("BlockLimits VPD is not available. Skipping test.\n"); return; } logging(LOG_VERBOSE, LOG_BLANK_LINE); logging(LOG_VERBOSE, "Test WRITESAME16 0-blocks at LBA==0 (WSNZ=%d)", inq_bl->wsnz); memset(buf, 0, block_size); if (inq_bl->wsnz) { ret = writesame16(sd, 0, block_size, 0, 0, 0, 0, 0, buf, EXPECT_INVALID_FIELD_IN_CDB); logging(LOG_NORMAL, "[SKIPPED] WRITESAME16 does not support 0-blocks."); CU_ASSERT_EQUAL(ret, 0); return; } ret = writesame16(sd, 0, block_size, 0, 0, 0, 0, 0, buf, EXPECT_STATUS_GOOD); if (ret == -2) { logging(LOG_NORMAL, "[SKIPPED] WRITESAME16 is not implemented."); CU_PASS("[SKIPPED] Target does not support WRITESAME16. Skipping test"); return; } else if (ret == -3) { CU_PASS("[SKIPPED] Target does not support WRITESAME16 with NUMBER OF LOGICAL BLOCKS == 0"); } else if (ret == -4) { CU_PASS("[SKIPPED] Number of WRITESAME16 logical blocks to be written exceeds MAXIMUM WRITE SAME LENGTH"); } else { CU_ASSERT_EQUAL(ret, 0); } logging(LOG_VERBOSE, "Test WRITESAME16 0-blocks one block past end-of-LUN"); ret = writesame16(sd, num_blocks + 1, block_size, 0, 0, 0, 0, 0, buf, EXPECT_LBA_OOB); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Test WRITESAME16 0-blocks at LBA==2^63"); ret = writesame16(sd, 0x8000000000000000ULL, block_size, 0, 0, 0, 0, 0, buf, EXPECT_LBA_OOB); CU_ASSERT_EQUAL(ret, 0); logging(LOG_VERBOSE, "Test WRITESAME16 0-blocks at LBA==-1"); ret = writesame16(sd, -1, block_size, 0, 0, 0, 0, 0, buf, EXPECT_LBA_OOB); CU_ASSERT_EQUAL(ret, 0); }