コード例 #1
0
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);
}
コード例 #2
0
void
test_compareandwrite_simple(void)
{
	int i, ret;
	unsigned j;
	unsigned char *buf = alloca(2 * 256 * block_size);
	int maxbl;

	CHECK_FOR_DATALOSS;
	CHECK_FOR_SBC;

	if (inq_bl && inq_bl->max_cmp) {
		maxbl = inq_bl->max_cmp;
	} else {
		/* Assume we are not limited */
		maxbl = 256;
	}

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
		"start of the LUN");
	for (i = 1; i < 256; i++) {
		logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:0", i);
		memset(buf, 'A', 2 * i * block_size);
		if (maximum_transfer_length && maximum_transfer_length < i) {
			break;
		}
		ret = write16(iscsic, tgt_lun, 0, i * block_size,
		    block_size, 0, 0, 0, 0, 0, buf);
		if (ret == -2) {
			logging(LOG_NORMAL, "[SKIPPED] WRITE16 is not implemented.");
			CU_PASS("WRITE16 is not implemented.");
			return;
		}	
		CU_ASSERT_EQUAL(ret, 0);

		if (i > maxbl) {
			logging(LOG_VERBOSE, "Number of blocks %d is greater than "
				"BlockLimits.MaximumCompareAndWriteLength(%d). "
				"Command should fail with INVALID_FIELD_IN_CDB",
				i, maxbl);
			ret = compareandwrite_invalidfieldincdb(iscsic, tgt_lun, 0,
				buf, 2 * i * block_size, block_size,
				0, 0, 0, 0);
			if (ret == -2) {
				CU_PASS("[SKIPPED] Target does not support "
					"COMPARE_AND_WRITE. Skipping test");
				return;
			}
			CU_ASSERT_EQUAL(ret, 0);

			continue;
		}

		memset(buf + i * block_size, 'B', i * block_size);

		logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
			"at LBA:0 (if they all contain 'A')", i);
		ret = compareandwrite(iscsic, tgt_lun, 0,
			buf, 2 * i * block_size, block_size,
			0, 0, 0, 0);
		if (ret == -2) {
			CU_PASS("[SKIPPED] Target does not support "
				"COMPARE_AND_WRITE. Skipping test");
			return;
		}
		CU_ASSERT_EQUAL(ret, 0);

		logging(LOG_VERBOSE, "Read %d blocks at LBA:0 and verify "
			"they are all 'B'", i);
		ret = read16(iscsic, tgt_lun, 0, i * block_size,
		    block_size, 0, 0, 0, 0, 0, buf);
		CU_ASSERT_EQUAL(ret, 0);

		for (j = 0; j < i * block_size; j++) {
			if (buf[j] != 'B') {
				logging(LOG_VERBOSE, "[FAILED] Data did not "
					"read back as 'B'");
				CU_FAIL("Block was not written correctly");
				return;
			}
		}
	}


	logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
		"end of the LUN");
	for (i = 1; i < 256; i++) {
		logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:%" PRIu64,
			i, num_blocks - i);
		memset(buf, 'A', 2 * i * block_size);
		if (maximum_transfer_length && maximum_transfer_length < i) {
			break;
		}
		ret = write16(iscsic, tgt_lun, num_blocks - i, i * block_size,
		    block_size, 0, 0, 0, 0, 0, buf);
		CU_ASSERT_EQUAL(ret, 0);

		if (i > maxbl) {
			logging(LOG_VERBOSE, "Number of blocks %d is greater than "
				"BlockLimits.MaximumCompareAndWriteLength(%d). "
				"Command should fail with INVALID_FIELD_IN_CDB",
				i, maxbl);
			ret = compareandwrite_invalidfieldincdb(iscsic, tgt_lun, 0,
				buf, 2 * i * block_size, block_size,
				0, 0, 0, 0);
			CU_ASSERT_EQUAL(ret, 0);

			continue;
		}
		memset(buf + i * block_size, 'B', i * block_size);

		logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
			"at LBA:%" PRIu64 " (if they all contain 'A')",
			i, num_blocks - i);
		ret = compareandwrite(iscsic, tgt_lun, num_blocks - i,
			buf, 2 * i * block_size, block_size, 0, 0, 0, 0);
		CU_ASSERT_EQUAL(ret, 0);

		logging(LOG_VERBOSE, "Read %d blocks at LBA:%" PRIu64 
			" and verify they are all 'B'",
			i, num_blocks - i);
		ret = read16(iscsic, tgt_lun, num_blocks - i, i * block_size,
		    block_size, 0, 0, 0, 0, 0, buf);
		CU_ASSERT_EQUAL(ret, 0);

		for (j = 0; j < i * block_size; j++) {
			if (buf[j] != 'B') {
				logging(LOG_VERBOSE, "[FAILED] Data did not "
					"read back as 'B'");
				CU_FAIL("Block was not written correctly");
				return;
			}
		}
	}
}
コード例 #3
0
void
test_compareandwrite_simple(void)
{
	int i, ret;
	unsigned j;
	unsigned char *buf = alloca(2 * 256 * block_size);

	CHECK_FOR_DATALOSS;
	CHECK_FOR_SBC;

	logging(LOG_VERBOSE, LOG_BLANK_LINE);
	logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
		"start of the LUN");
	for (i = 1; i < 256; i++) {
		logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:0", i);
		memset(buf, 'A', 2 * i * block_size);
		if (maximum_transfer_length && maximum_transfer_length < i) {
			break;
		}
		ret = write16(iscsic, tgt_lun, 0, i * block_size,
		    block_size, 0, 0, 0, 0, 0, buf);
		if (ret == -2) {
			logging(LOG_NORMAL, "[SKIPPED] WRITE16 is not implemented.");
			CU_PASS("WRITE16 is not implemented.");
			return;
		}	
		CU_ASSERT_EQUAL(ret, 0);

		memset(buf + i * block_size, 'B', i * block_size);

		logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
			"at LBA:0 (if they all contain 'A')", i);
		ret = compareandwrite(iscsic, tgt_lun, 0,
			buf, 2 * i * block_size, block_size, 0, 0, 0, 0);
		if (ret == -2) {
			CU_PASS("[SKIPPED] Target does not support "
				"COMPARE_AND_WRITE. Skipping test");
			return;
		}
		CU_ASSERT_EQUAL(ret, 0);

		logging(LOG_VERBOSE, "Read %d blocks at LBA:0 and verify "
			"they are all 'B'", i);
		ret = read16(iscsic, tgt_lun, 0, i * block_size,
		    block_size, 0, 0, 0, 0, 0, buf);
		CU_ASSERT_EQUAL(ret, 0);

		for (j = 0; j < i * block_size; j++) {
			if (buf[j] != 'B') {
				logging(LOG_VERBOSE, "[FAILED] Data did not "
					"read back as 'B'");
				CU_FAIL("Block was not written correctly");
				return;
			}
		}
	}


	logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1-256 blocks at the "
		"end of the LUN");
	for (i = 1; i < 256; i++) {
		logging(LOG_VERBOSE, "Write %d blocks of 'A' at LBA:%" PRIu64,
			i, num_blocks - i);
		memset(buf, 'A', 2 * i * block_size);
		if (maximum_transfer_length && maximum_transfer_length < i) {
			break;
		}
		ret = write16(iscsic, tgt_lun, num_blocks - i, i * block_size,
		    block_size, 0, 0, 0, 0, 0, buf);
		CU_ASSERT_EQUAL(ret, 0);

		memset(buf + i * block_size, 'B', i * block_size);

		logging(LOG_VERBOSE, "Overwrite %d blocks with 'B' "
			"at LBA:%" PRIu64 " (if they all contain 'A')",
			i, num_blocks - i);
		ret = compareandwrite(iscsic, tgt_lun, num_blocks - i,
			buf, 2 * i * block_size, block_size, 0, 0, 0, 0);
		CU_ASSERT_EQUAL(ret, 0);

		logging(LOG_VERBOSE, "Read %d blocks at LBA:%" PRIu64 
			" and verify they are all 'B'",
			i, num_blocks - i);
		ret = read16(iscsic, tgt_lun, num_blocks - i, i * block_size,
		    block_size, 0, 0, 0, 0, 0, buf);
		CU_ASSERT_EQUAL(ret, 0);

		for (j = 0; j < i * block_size; j++) {
			if (buf[j] != 'B') {
				logging(LOG_VERBOSE, "[FAILED] Data did not "
					"read back as 'B'");
				CU_FAIL("Block was not written correctly");
				return;
			}
		}
	}
}