Merge pull request #344 from ddiss/compareandwrite_miscompare_sense
test-tool: check compare and write miscompare sense information
This commit is contained in:
@@ -281,8 +281,10 @@ struct scsi_sense {
|
|||||||
unsigned sense_specific:1;
|
unsigned sense_specific:1;
|
||||||
unsigned ill_param_in_cdb:1;
|
unsigned ill_param_in_cdb:1;
|
||||||
unsigned bit_pointer_valid:1;
|
unsigned bit_pointer_valid:1;
|
||||||
|
unsigned info_valid:1;
|
||||||
unsigned char bit_pointer;
|
unsigned char bit_pointer;
|
||||||
uint16_t field_pointer;
|
uint16_t field_pointer;
|
||||||
|
uint64_t information;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct scsi_data {
|
struct scsi_data {
|
||||||
|
|||||||
@@ -326,14 +326,21 @@ static void parse_sense_descriptors(struct scsi_sense *sense, const uint8_t *sb,
|
|||||||
const unsigned char *p, *const end = sb + sb_len;
|
const unsigned char *p, *const end = sb + sb_len;
|
||||||
|
|
||||||
for (p = sb; p < end; p += p[1]) {
|
for (p = sb; p < end; p += p[1]) {
|
||||||
if (p[1] < 4) /* length */
|
uint8_t addl_len = p[1];
|
||||||
break;
|
if (addl_len < 4)
|
||||||
if (!(p[2] & 0x80)) /* VALID bit */
|
|
||||||
break;
|
break;
|
||||||
switch (p[0]) {
|
switch (p[0]) {
|
||||||
|
case 0:
|
||||||
|
/* Information descriptor with VALID flag */
|
||||||
|
if (addl_len == 0x0a && p[2] & 0x80) {
|
||||||
|
sense->info_valid = 1;
|
||||||
|
sense->information = scsi_get_uint64(p + 4);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
/* Sense key specific sense data descriptor */
|
/* Sense key specific sense data descriptor */
|
||||||
parse_sense_spec(sense, p + 4);
|
if (addl_len == 0x06)
|
||||||
|
parse_sense_spec(sense, p + 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,6 +354,10 @@ void scsi_parse_sense_data(struct scsi_sense *sense, const uint8_t *sb)
|
|||||||
case 0x71:
|
case 0x71:
|
||||||
/* Fixed format */
|
/* Fixed format */
|
||||||
sense->key = sb[2] & 0x0f;
|
sense->key = sb[2] & 0x0f;
|
||||||
|
if (sb[0] & 0x80) { /* VALID */
|
||||||
|
sense->info_valid = 1;
|
||||||
|
sense->information = scsi_get_uint32(sb + 3);
|
||||||
|
}
|
||||||
sense->ascq = scsi_get_uint16(&sb[12]);
|
sense->ascq = scsi_get_uint16(&sb[12]);
|
||||||
parse_sense_spec(sense, sb + 15);
|
parse_sense_spec(sense, sb + 15);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ static CU_TestInfo tests_compareandwrite[] = {
|
|||||||
{ "Simple", test_compareandwrite_simple },
|
{ "Simple", test_compareandwrite_simple },
|
||||||
{ "DpoFua", test_compareandwrite_dpofua },
|
{ "DpoFua", test_compareandwrite_dpofua },
|
||||||
{ "Miscompare", test_compareandwrite_miscompare },
|
{ "Miscompare", test_compareandwrite_miscompare },
|
||||||
|
{ "MiscompareSense", test_compareandwrite_miscompare_sense },
|
||||||
{ "Unwritten", test_compareandwrite_unwritten },
|
{ "Unwritten", test_compareandwrite_unwritten },
|
||||||
{ "InvalidDataOutSize",
|
{ "InvalidDataOutSize",
|
||||||
test_compareandwrite_invalid_dataout_size },
|
test_compareandwrite_invalid_dataout_size },
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ void test_teardown(void);
|
|||||||
void test_compareandwrite_simple(void);
|
void test_compareandwrite_simple(void);
|
||||||
void test_compareandwrite_dpofua(void);
|
void test_compareandwrite_dpofua(void);
|
||||||
void test_compareandwrite_miscompare(void);
|
void test_compareandwrite_miscompare(void);
|
||||||
|
void test_compareandwrite_miscompare_sense(void);
|
||||||
void test_compareandwrite_unwritten(void);
|
void test_compareandwrite_unwritten(void);
|
||||||
void test_compareandwrite_invalid_dataout_size(void);
|
void test_compareandwrite_invalid_dataout_size(void);
|
||||||
|
|
||||||
|
|||||||
@@ -158,3 +158,79 @@ test_compareandwrite_miscompare(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_compareandwrite_miscompare_sense(void)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
CHECK_FOR_DATALOSS;
|
||||||
|
CHECK_FOR_SBC;
|
||||||
|
CHECK_FOR_ISCSI(sd);
|
||||||
|
|
||||||
|
if (inq_bl->max_cmp < 1) {
|
||||||
|
logging(LOG_NORMAL, "[SKIPPED] COMPAREANDWRITE "
|
||||||
|
"max_cmp less than 1.");
|
||||||
|
CU_PASS("[SKIPPED] single block COMPAREANDWRITE not supported "
|
||||||
|
"Skipping test");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logging(LOG_VERBOSE, LOG_BLANK_LINE);
|
||||||
|
logging(LOG_VERBOSE, "Test COMPARE_AND_WRITE of 1 block at the "
|
||||||
|
"start of the LUN");
|
||||||
|
|
||||||
|
logging(LOG_VERBOSE, "Write 1 block of 'A' at LBA:0");
|
||||||
|
memset(scratch, 'A', 2 * block_size);
|
||||||
|
|
||||||
|
WRITE16(sd, 0, block_size,
|
||||||
|
block_size, 0, 0, 0, 0, 0, scratch,
|
||||||
|
EXPECT_STATUS_GOOD);
|
||||||
|
|
||||||
|
memset(scratch + block_size, 'B', block_size);
|
||||||
|
|
||||||
|
logging(LOG_VERBOSE, "Overwrite blocks with 'B' "
|
||||||
|
"at LBA:0 (if they all contain 'A')");
|
||||||
|
COMPAREANDWRITE(sd, 0,
|
||||||
|
scratch, 2 * block_size, block_size,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
EXPECT_STATUS_GOOD);
|
||||||
|
/* we've confirmed that c&w is supported, time for the proper test... */
|
||||||
|
|
||||||
|
logging(LOG_VERBOSE, "Vary location of miscompare in %zd bytes and check"
|
||||||
|
"sense", block_size);
|
||||||
|
memset(scratch + block_size, 'C', block_size);
|
||||||
|
|
||||||
|
for (i = 0; i < block_size; i++) {
|
||||||
|
struct scsi_task *tsk;
|
||||||
|
struct scsi_iovec iov;
|
||||||
|
|
||||||
|
logging(LOG_VERBOSE, "Fill buffer with 'B' except for %d "
|
||||||
|
"offset", i);
|
||||||
|
memset(scratch, 'B', block_size);
|
||||||
|
scratch[i] = 'Z';
|
||||||
|
|
||||||
|
tsk = scsi_cdb_compareandwrite(0, 2 * block_size, block_size,
|
||||||
|
0, 0, 0, 0, 0);
|
||||||
|
CU_ASSERT(tsk != NULL);
|
||||||
|
|
||||||
|
iov.iov_base = scratch;
|
||||||
|
iov.iov_len = 2 * block_size;
|
||||||
|
scsi_task_set_iov_out(tsk, &iov, 1);
|
||||||
|
|
||||||
|
tsk = iscsi_scsi_command_sync(sd->iscsi_ctx, sd->iscsi_lun,
|
||||||
|
tsk, NULL);
|
||||||
|
CU_ASSERT_FATAL(tsk != NULL);
|
||||||
|
CU_ASSERT(tsk->status == SCSI_STATUS_CHECK_CONDITION);
|
||||||
|
CU_ASSERT(tsk->sense.key == SCSI_SENSE_MISCOMPARE);
|
||||||
|
CU_ASSERT(tsk->sense.ascq
|
||||||
|
== SCSI_SENSE_ASCQ_MISCOMPARE_DURING_VERIFY);
|
||||||
|
if (tsk->sense.info_valid) {
|
||||||
|
logging(LOG_VERBOSE, "Check Information field provided"
|
||||||
|
" with miscompare sense response");
|
||||||
|
CU_ASSERT_EQUAL(tsk->sense.information, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
scsi_free_scsi_task(tsk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user