TESTS: add a new helper check_result to validate the result of SCSI helpers
Many/most all SCSI helpers do pretty much the same checking for the SCSI result and status. Break this out into a separate helper that we can use to reduce code duplication. Signed-off-by: Ronnie Sahlberg <sahlberg@localhost>
This commit is contained in:
committed by
Ronnie Sahlberg
parent
97177ec0e4
commit
905695575f
@@ -2,6 +2,7 @@
|
|||||||
iscsi-test tool support
|
iscsi-test tool support
|
||||||
|
|
||||||
Copyright (C) 2012 by Lee Duncan <leeman.duncan@gmail.com>
|
Copyright (C) 2012 by Lee Duncan <leeman.duncan@gmail.com>
|
||||||
|
Copyright (C) 2014 Ronnie Sahlberg <ronniesahlberg@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -63,8 +64,102 @@ int readonly;
|
|||||||
int sbc3_support;
|
int sbc3_support;
|
||||||
int maximum_transfer_length;
|
int maximum_transfer_length;
|
||||||
|
|
||||||
|
int no_medium_ascqs[3] = {
|
||||||
|
SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT,
|
||||||
|
SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN,
|
||||||
|
SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED
|
||||||
|
};
|
||||||
|
int lba_oob_ascqs[1] = {
|
||||||
|
SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE
|
||||||
|
};
|
||||||
|
int invalid_cdb_ascqs[1] = {
|
||||||
|
SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB
|
||||||
|
};
|
||||||
|
int write_protect_ascqs[1] = {
|
||||||
|
SCSI_SENSE_ASCQ_WRITE_PROTECTED
|
||||||
|
};
|
||||||
|
|
||||||
int (*real_iscsi_queue_pdu)(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
|
int (*real_iscsi_queue_pdu)(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
|
||||||
|
|
||||||
|
static const char *scsi_status_str(int status)
|
||||||
|
{
|
||||||
|
switch(status) {
|
||||||
|
case SCSI_STATUS_GOOD: return "SUCCESS";
|
||||||
|
case SCSI_STATUS_CHECK_CONDITION: return "CHECK_CONDITION";
|
||||||
|
case SCSI_STATUS_CONDITION_MET: return "CONDITIONS_MET";
|
||||||
|
case SCSI_STATUS_BUSY: return "BUSY";
|
||||||
|
case SCSI_STATUS_RESERVATION_CONFLICT: return "RESERVATION_CONFLICT";
|
||||||
|
case SCSI_STATUS_TASK_SET_FULL: return "TASK_SET_FULL";
|
||||||
|
case SCSI_STATUS_ACA_ACTIVE: return "ACA_ACTIVE";
|
||||||
|
case SCSI_STATUS_TASK_ABORTED: return "TASK_ABORTED";
|
||||||
|
}
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
|
||||||
|
static int check_result(const char *opcode, struct iscsi_context *iscsi,
|
||||||
|
struct scsi_task *task,
|
||||||
|
int status, enum scsi_sense_key key,
|
||||||
|
int *ascq, int num_ascq)
|
||||||
|
{
|
||||||
|
int ascq_ok;
|
||||||
|
|
||||||
|
if (task == NULL) {
|
||||||
|
logging(LOG_NORMAL, "[FAILED] Failed to send %s command: "
|
||||||
|
"%s", opcode, iscsi_get_error(iscsi));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
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] %s is not implemented.",
|
||||||
|
opcode);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
if (status == SCSI_STATUS_GOOD && task->status != SCSI_STATUS_GOOD) {
|
||||||
|
logging(LOG_NORMAL, "[FAILED] %s command failed with "
|
||||||
|
"sense. %s", opcode, iscsi_get_error(iscsi));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (status != SCSI_STATUS_GOOD && task->status == SCSI_STATUS_GOOD) {
|
||||||
|
logging(LOG_NORMAL, "[FAILED] %s successful but should "
|
||||||
|
"have failed with %s(0x%02x)/%s(0x%04x)",
|
||||||
|
opcode,
|
||||||
|
scsi_sense_key_str(key), key,
|
||||||
|
scsi_sense_ascq_str(ascq[0]), ascq[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* did we get any of the expected ASCQs ?*/
|
||||||
|
if (status == SCSI_STATUS_CHECK_CONDITION) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < num_ascq; i++) {
|
||||||
|
if (ascq[i] == task->sense.ascq) {
|
||||||
|
ascq_ok = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num_ascq == 0) {
|
||||||
|
ascq_ok = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (status == SCSI_STATUS_CHECK_CONDITION &&
|
||||||
|
(task->status != status
|
||||||
|
|| task->sense.key != key
|
||||||
|
|| !ascq_ok)) {
|
||||||
|
logging(LOG_NORMAL, "[FAILED] %s failed with wrong sense. "
|
||||||
|
"Should have failed with %s(0x%02x)/%s(0x%04x)"
|
||||||
|
"but failed with Sense:%s\n",
|
||||||
|
opcode,
|
||||||
|
scsi_sense_key_str(key), key,
|
||||||
|
scsi_sense_ascq_str(ascq[0]), ascq[0],
|
||||||
|
iscsi_get_error(iscsi));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
logging(LOG_VERBOSE, "[OK] %s returned %s %s(0x%02x) %s(0x%04x)",
|
||||||
|
opcode, scsi_status_str(status),
|
||||||
|
scsi_sense_key_str(task->sense.key), task->sense.key,
|
||||||
|
scsi_sense_ascq_str(task->sense.ascq), task->sense.ascq);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void logging(int level, const char *format, ...)
|
void logging(int level, const char *format, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|||||||
@@ -29,6 +29,18 @@ extern const char *initiatorname1;
|
|||||||
extern const char *initiatorname2;
|
extern const char *initiatorname2;
|
||||||
extern const char *tgt_url;
|
extern const char *tgt_url;
|
||||||
|
|
||||||
|
#define EXPECT_STATUS_GOOD SCSI_STATUS_GOOD, SCSI_SENSE_NO_SENSE, NULL, 0
|
||||||
|
#define EXPECT_NO_MEDIUM SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_NOT_READY, no_medium_ascqs, 3
|
||||||
|
#define EXPECT_LBA_OOB SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, lba_oob_ascqs, 1
|
||||||
|
#define EXPECT_INVALID_FIELD_IN_CDB SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_ILLEGAL_REQUEST, invalid_cdb_ascqs, 1
|
||||||
|
#define EXPECT_MISCOMPARE SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_MISCOMPARE, 0, 0
|
||||||
|
#define EXPECT_WRITE_PROTECTED SCSI_STATUS_CHECK_CONDITION, SCSI_SENSE_DATA_PROTECTION, write_protect_ascqs, 1
|
||||||
|
|
||||||
|
int no_medium_ascqs[3];
|
||||||
|
int lba_oob_ascqs[1];
|
||||||
|
int invalid_cdb_ascqs[1];
|
||||||
|
int write_protect_ascqs[1];
|
||||||
|
|
||||||
extern int loglevel;
|
extern int loglevel;
|
||||||
#define LOG_SILENT 0
|
#define LOG_SILENT 0
|
||||||
#define LOG_NORMAL 1
|
#define LOG_NORMAL 1
|
||||||
|
|||||||
Reference in New Issue
Block a user