scsi: translate nvme error to scsi error (#54)
This patch translates NVMe status code to SCSI sense according to NVM Express: SCSI Translation Reference. http://nvmexpress.org/wp-content/uploads/NVM_Express_-_SCSI_Translation_Reference-1_5_20150624_Gold.pdf
This commit is contained in:
parent
c257e5b4ad
commit
a5f0327897
@ -137,6 +137,7 @@ struct spdk_bdev_fn_table {
|
||||
|
||||
/** Blockdev I/O completion status */
|
||||
enum spdk_bdev_io_status {
|
||||
SPDK_BDEV_IO_STATUS_NVME_ERROR = -2,
|
||||
SPDK_BDEV_IO_STATUS_FAILED = -1,
|
||||
SPDK_BDEV_IO_STATUS_PENDING = 0,
|
||||
SPDK_BDEV_IO_STATUS_SUCCESS = 1,
|
||||
@ -242,6 +243,17 @@ struct spdk_bdev_io {
|
||||
} reset;
|
||||
} u;
|
||||
|
||||
/** Error information from a device */
|
||||
union {
|
||||
/** Only valid when status is SPDK_BDEV_IO_STATUS_NVME_ERROR */
|
||||
struct {
|
||||
/** NVMe status code type */
|
||||
int sct;
|
||||
/** NVMe status code */
|
||||
int sc;
|
||||
} nvme;
|
||||
} error;
|
||||
|
||||
/** User function that will be called when this completes */
|
||||
spdk_bdev_io_completion_cb cb;
|
||||
|
||||
|
@ -260,8 +260,8 @@ void spdk_scsi_task_alloc_data(struct spdk_scsi_task *task, uint32_t alloc_len,
|
||||
uint8_t **data);
|
||||
void spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc,
|
||||
int ascq);
|
||||
void spdk_scsi_task_set_check_condition(struct spdk_scsi_task *task, int sk,
|
||||
int asc, int ascq);
|
||||
void spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk, int asc,
|
||||
int ascq);
|
||||
|
||||
static inline struct spdk_scsi_task *
|
||||
spdk_scsi_task_get_primary(struct spdk_scsi_task *task)
|
||||
|
@ -85,6 +85,38 @@ enum spdk_scsi_sense {
|
||||
SPDK_SCSI_SENSE_MISCOMPARE = 0x0e,
|
||||
};
|
||||
|
||||
enum spdk_scsi_asc {
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE = 0x00,
|
||||
SPDK_SCSI_ASC_PERIPHERAL_DEVICE_WRITE_FAULT = 0x03,
|
||||
SPDK_SCSI_ASC_LOGICAL_UNIT_NOT_READY = 0x04,
|
||||
SPDK_SCSI_ASC_WARNING = 0x0b,
|
||||
SPDK_SCSI_ASC_LOGICAL_BLOCK_GUARD_CHECK_FAILED = 0x10,
|
||||
SPDK_SCSI_ASC_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = 0x10,
|
||||
SPDK_SCSI_ASC_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = 0x10,
|
||||
SPDK_SCSI_ASC_UNRECOVERED_READ_ERROR = 0x11,
|
||||
SPDK_SCSI_ASC_MISCOMPARE_DURING_VERIFY_OPERATION = 0x1d,
|
||||
SPDK_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE = 0x20,
|
||||
SPDK_SCSI_ASC_ACCESS_DENIED = 0x20,
|
||||
SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE = 0x21,
|
||||
SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB = 0x24,
|
||||
SPDK_SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED = 0x25,
|
||||
SPDK_SCSI_ASC_WRITE_PROTECTED = 0x27,
|
||||
SPDK_SCSI_ASC_FORMAT_COMMAND_FAILED = 0x31,
|
||||
SPDK_SCSI_ASC_INTERNAL_TARGET_FAILURE = 0x44,
|
||||
};
|
||||
|
||||
enum spdk_scsi_ascq {
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE = 0x00,
|
||||
SPDK_SCSI_ASCQ_BECOMING_READY = 0x01,
|
||||
SPDK_SCSI_ASCQ_FORMAT_COMMAND_FAILED = 0x01,
|
||||
SPDK_SCSI_ASCQ_LOGICAL_BLOCK_GUARD_CHECK_FAILED = 0x01,
|
||||
SPDK_SCSI_ASCQ_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED = 0x02,
|
||||
SPDK_SCSI_ASCQ_NO_ACCESS_RIGHTS = 0x02,
|
||||
SPDK_SCSI_ASCQ_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED = 0x03,
|
||||
SPDK_SCSI_ASCQ_POWER_LOSS_EXPECTED = 0x08,
|
||||
SPDK_SCSI_ASCQ_INVALID_LU_IDENTIFIER = 0x09,
|
||||
};
|
||||
|
||||
enum spdk_spc_opcode {
|
||||
/* SPC3 related */
|
||||
SPDK_SPC_ACCESS_CONTROL_IN = 0x86,
|
||||
|
@ -602,16 +602,18 @@ nvme_ctrlr_initialize_blockdevs(struct spdk_nvme_ctrlr *ctrlr, int bdev_per_ns,
|
||||
static void
|
||||
queued_done(void *ref, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
struct nvme_blockio *bio = ref;
|
||||
struct spdk_bdev_io *bdev_io = spdk_bdev_io_from_ctx((struct nvme_blockio *)ref);
|
||||
enum spdk_bdev_io_status status;
|
||||
|
||||
if (spdk_nvme_cpl_is_error(cpl)) {
|
||||
status = SPDK_BDEV_IO_STATUS_FAILED;
|
||||
bdev_io->error.nvme.sct = cpl->status.sct;
|
||||
bdev_io->error.nvme.sc = cpl->status.sc;
|
||||
status = SPDK_BDEV_IO_STATUS_NVME_ERROR;
|
||||
} else {
|
||||
status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(bio), status);
|
||||
spdk_bdev_io_complete(bdev_io, status);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
CFLAGS += $(ENV_CFLAGS)
|
||||
C_SRCS = dev.c lun.c lun_db.c port.c scsi.c scsi_bdev.c scsi_rpc.c task.c
|
||||
C_SRCS = dev.c lun.c lun_db.c port.c scsi.c scsi_bdev.c scsi_nvme.c scsi_rpc.c task.c
|
||||
LIBNAME = scsi
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk
|
||||
|
@ -66,14 +66,19 @@ spdk_scsi_lun_clear_all(struct spdk_scsi_lun *lun)
|
||||
|
||||
TAILQ_FOREACH_SAFE(task, &lun->tasks, scsi_link, task_tmp) {
|
||||
TAILQ_REMOVE(&lun->tasks, task, scsi_link);
|
||||
spdk_scsi_task_set_check_condition(task, SPDK_SCSI_SENSE_ABORTED_COMMAND, 0, 0);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ABORTED_COMMAND,
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
spdk_scsi_lun_complete_task(lun, task);
|
||||
}
|
||||
|
||||
TAILQ_FOREACH_SAFE(task, &lun->pending_tasks, scsi_link, task_tmp) {
|
||||
TAILQ_REMOVE(&lun->pending_tasks, task, scsi_link);
|
||||
spdk_scsi_task_set_check_condition(task, SPDK_SCSI_SENSE_ABORTED_COMMAND,
|
||||
0, 0);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ABORTED_COMMAND,
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
spdk_scsi_lun_complete_task(lun, task);
|
||||
}
|
||||
}
|
||||
@ -200,8 +205,10 @@ complete_task_with_no_lun(struct spdk_scsi_task *task)
|
||||
task->status = SPDK_SCSI_STATUS_GOOD;
|
||||
} else {
|
||||
/* LOGICAL UNIT NOT SUPPORTED */
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST, 0x25, 0x00);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
|
||||
SPDK_SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
task->data_transferred = 0;
|
||||
}
|
||||
spdk_scsi_lun_complete_task(NULL, task);
|
||||
|
@ -175,9 +175,10 @@ spdk_bdev_scsi_inquiry(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
|
||||
evpd = inq->evpd & 0x1;
|
||||
|
||||
if (!evpd && pc) {
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
|
||||
0x24, 0x0);
|
||||
SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -246,9 +247,10 @@ spdk_bdev_scsi_inquiry(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
|
||||
len += sizeof(struct spdk_scsi_desig_desc) + 4;
|
||||
len += sizeof(struct spdk_scsi_desig_desc) + 4;
|
||||
if (sizeof(struct spdk_scsi_vpd_page) + len > task->alloc_len) {
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
|
||||
0x24, 0x0);
|
||||
SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -361,9 +363,10 @@ spdk_bdev_scsi_inquiry(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
|
||||
|
||||
/* should not exceed the data_in buffer length */
|
||||
if (sizeof(struct spdk_scsi_vpd_page) + len > alloc_len) {
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
|
||||
0x24, 0x0);
|
||||
SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
return -1;
|
||||
}
|
||||
to_be16(vpage->alloc_len, len);
|
||||
@ -770,9 +773,10 @@ spdk_bdev_scsi_inquiry(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
|
||||
|
||||
inq_error:
|
||||
task->data_transferred = 0;
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_NO_SENSE,
|
||||
0x0, 0x0);
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1279,16 +1283,23 @@ spdk_bdev_scsi_task_complete(spdk_event_t event)
|
||||
enum spdk_bdev_io_status status = bdev_io->status;
|
||||
|
||||
if (task->type == SPDK_SCSI_TASK_TYPE_CMD) {
|
||||
if (status != SPDK_BDEV_IO_STATUS_SUCCESS) {
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
SPDK_SCSI_SENSE_ABORTED_COMMAND, 0, 0);
|
||||
}
|
||||
int sc, sk, asc, ascq;
|
||||
|
||||
/* If status was not set to CHECK_CONDITION yet, then we can set
|
||||
* status to GOOD.
|
||||
*/
|
||||
if (task->status != SPDK_SCSI_STATUS_CHECK_CONDITION) {
|
||||
switch (bdev_io->status) {
|
||||
case SPDK_BDEV_IO_STATUS_SUCCESS:
|
||||
task->status = SPDK_SCSI_STATUS_GOOD;
|
||||
break;
|
||||
case SPDK_BDEV_IO_STATUS_NVME_ERROR:
|
||||
spdk_scsi_nvme_translate(bdev_io, &sc, &sk, &asc, &ascq);
|
||||
spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
|
||||
break;
|
||||
default:
|
||||
sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
sk = SPDK_SCSI_SENSE_ABORTED_COMMAND;
|
||||
asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
||||
ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
spdk_scsi_task_set_status(task, sc, sk, asc, ascq);
|
||||
break;
|
||||
}
|
||||
|
||||
/* command completed. remove from outstanding task list */
|
||||
@ -1427,7 +1438,10 @@ spdk_bdev_scsi_sync(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
|
||||
|
||||
if (lba >= maxlba || llen > maxlba || lba > (maxlba - llen)) {
|
||||
SPDK_ERRLOG("end of media\n");
|
||||
spdk_scsi_task_set_check_condition(task, SPDK_SCSI_SENSE_NO_SENSE, 0x0, 0x0);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_NO_SENSE,
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
return SPDK_SCSI_TASK_COMPLETE;
|
||||
}
|
||||
|
||||
@ -1436,7 +1450,10 @@ spdk_bdev_scsi_sync(struct spdk_bdev *bdev, struct spdk_scsi_task *task,
|
||||
|
||||
if (!task->blockdev_io) {
|
||||
SPDK_ERRLOG("spdk_bdev_flush() failed\n");
|
||||
spdk_scsi_task_set_check_condition(task, SPDK_SCSI_SENSE_NO_SENSE, 0x0, 0x0);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_NO_SENSE,
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
return SPDK_SCSI_TASK_COMPLETE;
|
||||
}
|
||||
task->data_transferred = 0;
|
||||
@ -1457,13 +1474,19 @@ spdk_bdev_scsi_readwrite(struct spdk_bdev *bdev,
|
||||
rc = spdk_bdev_scsi_write(bdev, task, lba, xfer_len);
|
||||
} else {
|
||||
SPDK_ERRLOG("Incorrect data direction\n");
|
||||
spdk_scsi_task_set_check_condition(task, SPDK_SCSI_SENSE_NO_SENSE, 0x0, 0x0);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_NO_SENSE,
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
return SPDK_SCSI_TASK_COMPLETE;
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
SPDK_ERRLOG("disk op (rw) failed\n");
|
||||
spdk_scsi_task_set_check_condition(task, SPDK_SCSI_SENSE_NO_SENSE, 0x0, 0x0);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_NO_SENSE,
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
|
||||
return SPDK_SCSI_TASK_COMPLETE;
|
||||
} else {
|
||||
@ -1497,9 +1520,10 @@ spdk_bdev_scsi_unmap(struct spdk_bdev *bdev,
|
||||
if (bdesc_count > bdev->max_unmap_bdesc_count) {
|
||||
SPDK_ERRLOG("Error - supported unmap block descriptor count limit"
|
||||
" is %u\n", bdev->max_unmap_bdesc_count);
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_NO_SENSE,
|
||||
0x0, 0x0);
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
return SPDK_SCSI_TASK_COMPLETE;
|
||||
}
|
||||
|
||||
@ -1509,9 +1533,10 @@ spdk_bdev_scsi_unmap(struct spdk_bdev *bdev,
|
||||
|
||||
if (!task->blockdev_io) {
|
||||
SPDK_ERRLOG("SCSI Unmapping failed\n");
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_NO_SENSE,
|
||||
0x0, 0x0);
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
return SPDK_SCSI_TASK_COMPLETE;
|
||||
}
|
||||
|
||||
@ -1659,15 +1684,20 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
|
||||
alloc_len = from_be32(&cdb[6]);
|
||||
if (alloc_len < 16) {
|
||||
/* INVALID FIELD IN CDB */
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST, 0x24, 0x00);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
|
||||
SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
break;
|
||||
}
|
||||
|
||||
spdk_scsi_task_alloc_data(task, alloc_len, &data);
|
||||
data_len = spdk_bdev_scsi_report_luns(task->lun, sel, data, task->alloc_len);
|
||||
if (data_len < 0) {
|
||||
spdk_scsi_task_set_check_condition(task, SPDK_SCSI_SENSE_NO_SENSE, 0x0, 0x0);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_NO_SENSE,
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1696,14 +1726,18 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
|
||||
} else if (cdb[0] == SPDK_SPC_MODE_SELECT_6 && pllen < 4) {
|
||||
/* MODE_SELECT(6) must have at least a 4 byte header. */
|
||||
/* INVALID FIELD IN CDB */
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST, 0x24, 0x00);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
|
||||
SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
break;
|
||||
} else if (cdb[0] == SPDK_SPC_MODE_SELECT_10 && pllen < 8) {
|
||||
/* MODE_SELECT(10) must have at least an 8 byte header. */
|
||||
/* INVALID FIELD IN CDB */
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST, 0x24, 0x00);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
|
||||
SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1723,9 +1757,10 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
|
||||
&data[md + bdlen],
|
||||
pllen - (md + bdlen));
|
||||
if (data_len != 0) {
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_NO_SENSE,
|
||||
0x0, 0x0);
|
||||
SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1771,8 +1806,10 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
|
||||
|
||||
if (data_len < 0) {
|
||||
/* INVALID FIELD IN CDB */
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST, 0x24, 0x00);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
|
||||
SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1787,8 +1824,10 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
|
||||
desc = cdb[1] & 0x1;
|
||||
if (desc != 0) {
|
||||
/* INVALID FIELD IN CDB */
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST, 0x24, 0x00);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
|
||||
SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1819,8 +1858,10 @@ spdk_bdev_scsi_process_primary(struct spdk_bdev *bdev,
|
||||
}
|
||||
|
||||
/* INVALID COMMAND OPERATION CODE */
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
|
||||
SPDK_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
break;
|
||||
|
||||
case SPDK_SPC_TEST_UNIT_READY:
|
||||
@ -1851,9 +1892,10 @@ spdk_bdev_scsi_execute(struct spdk_bdev *bdev, struct spdk_scsi_task *task)
|
||||
if ((rc = spdk_bdev_scsi_process_primary(bdev, task)) == SPDK_SCSI_TASK_UNKNOWN) {
|
||||
SPDK_TRACELOG(SPDK_TRACE_SCSI, "unsupported SCSI OP=0x%x\n", task->cdb[0]);
|
||||
/* INVALID COMMAND OPERATION CODE */
|
||||
spdk_scsi_task_set_check_condition(task,
|
||||
spdk_scsi_task_set_status(task, SPDK_SCSI_STATUS_CHECK_CONDITION,
|
||||
SPDK_SCSI_SENSE_ILLEGAL_REQUEST,
|
||||
0x20, 0x00);
|
||||
SPDK_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
|
||||
SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
return SPDK_SCSI_TASK_COMPLETE;
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +99,8 @@ struct spdk_scsi_dev *spdk_scsi_dev_get_list(void);
|
||||
int spdk_bdev_scsi_execute(struct spdk_bdev *bdev, struct spdk_scsi_task *task);
|
||||
int spdk_bdev_scsi_reset(struct spdk_bdev *bdev, struct spdk_scsi_task *task);
|
||||
|
||||
void spdk_scsi_nvme_translate(struct spdk_bdev_io *bdev_io, int *sc, int *sk, int *asc, int *ascq);
|
||||
|
||||
struct spdk_scsi_parameters {
|
||||
uint32_t max_unmap_lba_count;
|
||||
uint32_t max_unmap_block_descriptor_count;
|
||||
|
261
lib/scsi/scsi_nvme.c
Normal file
261
lib/scsi/scsi_nvme.c
Normal file
@ -0,0 +1,261 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) 2016 FUJITSU LIMITED, All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "scsi_internal.h"
|
||||
#include "spdk/nvme_spec.h"
|
||||
|
||||
void
|
||||
spdk_scsi_nvme_translate(struct spdk_bdev_io *bdev_io, int *sc, int *sk,
|
||||
int *asc, int *ascq)
|
||||
{
|
||||
int nvme_sct = bdev_io->error.nvme.sct;
|
||||
int nvme_sc = bdev_io->error.nvme.sc;
|
||||
|
||||
switch (nvme_sct) {
|
||||
case SPDK_NVME_SCT_GENERIC:
|
||||
switch (nvme_sc) {
|
||||
case SPDK_NVME_SC_SUCCESS:
|
||||
*sc = SPDK_SCSI_STATUS_GOOD;
|
||||
*sk = SPDK_SCSI_SENSE_NO_SENSE;
|
||||
*asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_INVALID_OPCODE:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
|
||||
*asc = SPDK_SCSI_ASC_INVALID_COMMAND_OPERATION_CODE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_INVALID_FIELD:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
|
||||
*asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_DATA_TRANSFER_ERROR:
|
||||
case SPDK_NVME_SC_CAPACITY_EXCEEDED:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_MEDIUM_ERROR;
|
||||
*asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_ABORTED_POWER_LOSS:
|
||||
*sc = SPDK_SCSI_STATUS_TASK_ABORTED;
|
||||
*sk = SPDK_SCSI_SENSE_ABORTED_COMMAND;
|
||||
*asc = SPDK_SCSI_ASC_WARNING;
|
||||
*ascq = SPDK_SCSI_ASCQ_POWER_LOSS_EXPECTED;
|
||||
break;
|
||||
case SPDK_NVME_SC_INTERNAL_DEVICE_ERROR:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_HARDWARE_ERROR;
|
||||
*asc = SPDK_SCSI_ASC_INTERNAL_TARGET_FAILURE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_ABORTED_BY_REQUEST:
|
||||
case SPDK_NVME_SC_ABORTED_SQ_DELETION:
|
||||
case SPDK_NVME_SC_ABORTED_FAILED_FUSED:
|
||||
case SPDK_NVME_SC_ABORTED_MISSING_FUSED:
|
||||
*sc = SPDK_SCSI_STATUS_TASK_ABORTED;
|
||||
*sk = SPDK_SCSI_SENSE_ABORTED_COMMAND;
|
||||
*asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
|
||||
*asc = SPDK_SCSI_ASC_ACCESS_DENIED;
|
||||
*ascq = SPDK_SCSI_ASCQ_INVALID_LU_IDENTIFIER;
|
||||
break;
|
||||
case SPDK_NVME_SC_LBA_OUT_OF_RANGE:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
|
||||
*asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_NAMESPACE_NOT_READY:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_NOT_READY;
|
||||
*asc = SPDK_SCSI_ASC_LOGICAL_UNIT_NOT_READY;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_RESERVATION_CONFLICT:
|
||||
*sc = SPDK_SCSI_STATUS_RESERVATION_CONFLICT;
|
||||
*sk = SPDK_SCSI_SENSE_NO_SENSE;
|
||||
*asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_COMMAND_ID_CONFLICT:
|
||||
case SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR:
|
||||
case SPDK_NVME_SC_INVALID_SGL_SEG_DESCRIPTOR:
|
||||
case SPDK_NVME_SC_INVALID_NUM_SGL_DESCIRPTORS:
|
||||
case SPDK_NVME_SC_DATA_SGL_LENGTH_INVALID:
|
||||
case SPDK_NVME_SC_METADATA_SGL_LENGTH_INVALID:
|
||||
case SPDK_NVME_SC_SGL_DESCRIPTOR_TYPE_INVALID:
|
||||
case SPDK_NVME_SC_INVALID_CONTROLLER_MEM_BUF:
|
||||
case SPDK_NVME_SC_INVALID_PRP_OFFSET:
|
||||
case SPDK_NVME_SC_ATOMIC_WRITE_UNIT_EXCEEDED:
|
||||
case SPDK_NVME_SC_INVALID_SGL_OFFSET:
|
||||
case SPDK_NVME_SC_INVALID_SGL_SUBTYPE:
|
||||
case SPDK_NVME_SC_HOSTID_INCONSISTENT_FORMAT:
|
||||
case SPDK_NVME_SC_KEEP_ALIVE_EXPIRED:
|
||||
case SPDK_NVME_SC_KEEP_ALIVE_INVALID:
|
||||
case SPDK_NVME_SC_FORMAT_IN_PROGRESS:
|
||||
default:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
|
||||
*asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SPDK_NVME_SCT_COMMAND_SPECIFIC:
|
||||
switch (nvme_sc) {
|
||||
case SPDK_NVME_SC_COMPLETION_QUEUE_INVALID:
|
||||
case SPDK_NVME_SC_ABORT_COMMAND_LIMIT_EXCEEDED:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
|
||||
*asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_INVALID_FORMAT:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
|
||||
*asc = SPDK_SCSI_ASC_FORMAT_COMMAND_FAILED;
|
||||
*ascq = SPDK_SCSI_ASCQ_FORMAT_COMMAND_FAILED;
|
||||
break;
|
||||
case SPDK_NVME_SC_CONFLICTING_ATTRIBUTES:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
|
||||
*asc = SPDK_SCSI_ASC_INVALID_FIELD_IN_CDB;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_ATTEMPTED_WRITE_TO_RO_PAGE:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_DATA_PROTECT;
|
||||
*asc = SPDK_SCSI_ASC_WRITE_PROTECTED;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_INVALID_QUEUE_IDENTIFIER:
|
||||
case SPDK_NVME_SC_MAXIMUM_QUEUE_SIZE_EXCEEDED:
|
||||
case SPDK_NVME_SC_ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED:
|
||||
case SPDK_NVME_SC_INVALID_FIRMWARE_SLOT:
|
||||
case SPDK_NVME_SC_INVALID_FIRMWARE_IMAGE:
|
||||
case SPDK_NVME_SC_INVALID_INTERRUPT_VECTOR:
|
||||
case SPDK_NVME_SC_INVALID_LOG_PAGE:
|
||||
case SPDK_NVME_SC_FIRMWARE_REQ_CONVENTIONAL_RESET:
|
||||
case SPDK_NVME_SC_INVALID_QUEUE_DELETION:
|
||||
case SPDK_NVME_SC_FEATURE_ID_NOT_SAVEABLE:
|
||||
case SPDK_NVME_SC_FEATURE_NOT_CHANGEABLE:
|
||||
case SPDK_NVME_SC_FEATURE_NOT_NAMESPACE_SPECIFIC:
|
||||
case SPDK_NVME_SC_FIRMWARE_REQ_NVM_RESET:
|
||||
case SPDK_NVME_SC_FIRMWARE_REQ_RESET:
|
||||
case SPDK_NVME_SC_FIRMWARE_REQ_MAX_TIME_VIOLATION:
|
||||
case SPDK_NVME_SC_FIRMWARE_ACTIVATION_PROHIBITED:
|
||||
case SPDK_NVME_SC_OVERLAPPING_RANGE:
|
||||
case SPDK_NVME_SC_NAMESPACE_INSUFFICIENT_CAPACITY:
|
||||
case SPDK_NVME_SC_NAMESPACE_ID_UNAVAILABLE:
|
||||
case SPDK_NVME_SC_NAMESPACE_ALREADY_ATTACHED:
|
||||
case SPDK_NVME_SC_NAMESPACE_IS_PRIVATE:
|
||||
case SPDK_NVME_SC_NAMESPACE_NOT_ATTACHED:
|
||||
case SPDK_NVME_SC_THINPROVISIONING_NOT_SUPPORTED:
|
||||
case SPDK_NVME_SC_CONTROLLER_LIST_INVALID:
|
||||
case SPDK_NVME_SC_INVALID_PROTECTION_INFO:
|
||||
default:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
|
||||
*asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SPDK_NVME_SCT_MEDIA_ERROR:
|
||||
switch (nvme_sc) {
|
||||
case SPDK_NVME_SC_WRITE_FAULTS:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_MEDIUM_ERROR;
|
||||
*asc = SPDK_SCSI_ASC_PERIPHERAL_DEVICE_WRITE_FAULT;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_UNRECOVERED_READ_ERROR:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_MEDIUM_ERROR;
|
||||
*asc = SPDK_SCSI_ASC_UNRECOVERED_READ_ERROR;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_GUARD_CHECK_ERROR:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_MEDIUM_ERROR;
|
||||
*asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
|
||||
*ascq = SPDK_SCSI_ASCQ_LOGICAL_BLOCK_GUARD_CHECK_FAILED;
|
||||
break;
|
||||
case SPDK_NVME_SC_APPLICATION_TAG_CHECK_ERROR:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_MEDIUM_ERROR;
|
||||
*asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED;
|
||||
*ascq = SPDK_SCSI_ASCQ_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED;
|
||||
break;
|
||||
case SPDK_NVME_SC_REFERENCE_TAG_CHECK_ERROR:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_MEDIUM_ERROR;
|
||||
*asc = SPDK_SCSI_ASC_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
|
||||
*ascq = SPDK_SCSI_ASCQ_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED;
|
||||
break;
|
||||
case SPDK_NVME_SC_COMPARE_FAILURE:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_MISCOMPARE;
|
||||
*asc = SPDK_SCSI_ASC_MISCOMPARE_DURING_VERIFY_OPERATION;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
case SPDK_NVME_SC_ACCESS_DENIED:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_DATA_PROTECT;
|
||||
*asc = SPDK_SCSI_ASC_ACCESS_DENIED;
|
||||
*ascq = SPDK_SCSI_ASCQ_NO_ACCESS_RIGHTS;
|
||||
break;
|
||||
case SPDK_NVME_SC_DEALLOCATED_OR_UNWRITTEN_BLOCK:
|
||||
default:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
|
||||
*asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SPDK_NVME_SCT_VENDOR_SPECIFIC:
|
||||
default:
|
||||
*sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
*sk = SPDK_SCSI_SENSE_ILLEGAL_REQUEST;
|
||||
*asc = SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE;
|
||||
*ascq = SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
|
||||
break;
|
||||
}
|
||||
}
|
@ -178,8 +178,9 @@ spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc, in
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_task_set_check_condition(struct spdk_scsi_task *task, int sk, int asc, int ascq)
|
||||
spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
|
||||
int asc, int ascq)
|
||||
{
|
||||
spdk_scsi_task_build_sense_data(task, sk, asc, ascq);
|
||||
task->status = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
task->status = sc;
|
||||
}
|
||||
|
@ -154,6 +154,6 @@ spdk_scsi_dev_print(struct spdk_scsi_dev *dev)
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_task_set_check_condition(struct spdk_scsi_task *task, int sk, int asc, int ascq)
|
||||
spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk, int asc, int ascq)
|
||||
{
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
DIRS-y = dev init lun scsi_bdev
|
||||
DIRS-y = dev init lun scsi_bdev scsi_nvme
|
||||
|
||||
.PHONY: all clean $(DIRS-y)
|
||||
|
||||
|
@ -82,10 +82,11 @@ spdk_scsi_task_put(struct spdk_scsi_task *task)
|
||||
free(task);
|
||||
}
|
||||
|
||||
void spdk_scsi_task_set_check_condition(struct spdk_scsi_task *task, int sk,
|
||||
void
|
||||
spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
|
||||
int asc, int ascq)
|
||||
{
|
||||
task->status = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
task->status = sc;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -12,5 +12,6 @@ $valgrind $testdir/dev/dev_ut
|
||||
$testdir/init/init_ut
|
||||
$valgrind $testdir/lun/lun_ut
|
||||
$testdir/scsi_bdev/scsi_bdev_ut
|
||||
$valgrind $testdir/scsi_nvme/scsi_nvme_ut
|
||||
|
||||
timing_exit scsi
|
||||
|
@ -54,10 +54,11 @@ spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *ta
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_task_set_check_condition(struct spdk_scsi_task *task, int sk, int asc, int ascq)
|
||||
spdk_scsi_task_set_status(struct spdk_scsi_task *task, int sc, int sk,
|
||||
int asc, int ascq)
|
||||
{
|
||||
spdk_scsi_task_build_sense_data(task, sk, asc, ascq);
|
||||
task->status = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||
task->status = sc;
|
||||
}
|
||||
|
||||
void
|
||||
@ -119,6 +120,12 @@ spdk_scsi_task_build_sense_data(struct spdk_scsi_task *task, int sk, int asc, in
|
||||
task->sense_data_len = 20;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_scsi_nvme_translate(struct spdk_bdev_io *bdev_io, int *sc, int *sk,
|
||||
int *asc, int *ascq)
|
||||
{
|
||||
}
|
||||
|
||||
struct spdk_bdev_io *
|
||||
spdk_bdev_read(struct spdk_bdev *bdev, struct spdk_io_channel *ch,
|
||||
void *buf, uint64_t offset, uint64_t nbytes,
|
||||
@ -459,6 +466,37 @@ inquiry_overflow_test(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This test is to verify specific error translation from bdev to scsi.
|
||||
*/
|
||||
static void
|
||||
task_complete_test(void)
|
||||
{
|
||||
struct spdk_event event;
|
||||
struct spdk_scsi_task task = {};
|
||||
struct spdk_bdev_io bdev_io = {};
|
||||
struct spdk_scsi_lun lun;
|
||||
|
||||
TAILQ_INIT(&lun.tasks);
|
||||
TAILQ_INSERT_TAIL(&lun.tasks, &task, scsi_link);
|
||||
task.lun = &lun;
|
||||
|
||||
event.arg1 = &task;
|
||||
event.arg2 = &bdev_io;
|
||||
|
||||
task.type = SPDK_SCSI_TASK_TYPE_CMD;
|
||||
bdev_io.status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
||||
spdk_bdev_scsi_task_complete(&event);
|
||||
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_GOOD);
|
||||
|
||||
bdev_io.status = SPDK_BDEV_IO_STATUS_FAILED;
|
||||
spdk_bdev_scsi_task_complete(&event);
|
||||
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||
CU_ASSERT_EQUAL(task.sense_data[4], SPDK_SCSI_SENSE_ABORTED_COMMAND);
|
||||
CU_ASSERT_EQUAL(task.sense_data[14], SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE);
|
||||
CU_ASSERT_EQUAL(task.sense_data[15], SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@ -483,6 +521,7 @@ main(int argc, char **argv)
|
||||
|| CU_add_test(suite, "inquiry evpd test", inquiry_evpd_test) == NULL
|
||||
|| CU_add_test(suite, "inquiry standard test", inquiry_standard_test) == NULL
|
||||
|| CU_add_test(suite, "inquiry overflow test", inquiry_overflow_test) == NULL
|
||||
|| CU_add_test(suite, "task complete test", task_complete_test) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
1
test/lib/scsi/scsi_nvme/.gitignore
vendored
Normal file
1
test/lib/scsi/scsi_nvme/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
scsi_nvme_ut
|
55
test/lib/scsi/scsi_nvme/Makefile
Normal file
55
test/lib/scsi/scsi_nvme/Makefile
Normal file
@ -0,0 +1,55 @@
|
||||
#
|
||||
# BSD LICENSE
|
||||
#
|
||||
# Copyright (c) 2016 FUJITSU LIMITED, All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of the copyright holder nor the names of its
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..)
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||
|
||||
SPDK_LIBS += $(SPDK_ROOT_DIR)/lib/log/libspdk_log.a \
|
||||
$(SPDK_ROOT_DIR)/lib/cunit/libspdk_cunit.a
|
||||
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/test
|
||||
CFLAGS += -I$(SPDK_ROOT_DIR)/lib/scsi
|
||||
LIBS += $(SPDK_LIBS)
|
||||
LIBS += -lcunit
|
||||
|
||||
APP = scsi_nvme_ut
|
||||
C_SRCS = scsi_nvme_ut.c
|
||||
|
||||
all: $(APP)
|
||||
|
||||
$(APP): $(OBJS) $(SPDK_LIBS)
|
||||
$(LINK_C)
|
||||
|
||||
clean:
|
||||
$(CLEAN_C) $(APP)
|
||||
|
||||
include $(SPDK_ROOT_DIR)/mk/spdk.deps.mk
|
142
test/lib/scsi/scsi_nvme/scsi_nvme_ut.c
Normal file
142
test/lib/scsi/scsi_nvme/scsi_nvme_ut.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) 2016 FUJITSU LIMITED, All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "spdk_cunit.h"
|
||||
|
||||
#include "scsi_nvme.c"
|
||||
|
||||
static int
|
||||
null_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
null_clean(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_nvme_translate_test(void)
|
||||
{
|
||||
struct spdk_bdev_io bdev_io;
|
||||
int sc, sk, asc, ascq;
|
||||
|
||||
/* SPDK_NVME_SCT_GENERIC */
|
||||
bdev_io.error.nvme.sct = SPDK_NVME_SCT_GENERIC;
|
||||
bdev_io.error.nvme.sc = SPDK_NVME_SC_ABORTED_POWER_LOSS;
|
||||
spdk_scsi_nvme_translate(&bdev_io, &sc, &sk, &asc, &ascq);
|
||||
CU_ASSERT_EQUAL(sc, SPDK_SCSI_STATUS_TASK_ABORTED);
|
||||
CU_ASSERT_EQUAL(sk, SPDK_SCSI_SENSE_ABORTED_COMMAND);
|
||||
CU_ASSERT_EQUAL(asc, SPDK_SCSI_ASC_WARNING);
|
||||
CU_ASSERT_EQUAL(ascq, SPDK_SCSI_ASCQ_POWER_LOSS_EXPECTED);
|
||||
|
||||
bdev_io.error.nvme.sc = SPDK_NVME_SC_INVALID_NUM_SGL_DESCIRPTORS;
|
||||
spdk_scsi_nvme_translate(&bdev_io, &sc, &sk, &asc, &ascq);
|
||||
CU_ASSERT_EQUAL(sc, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||
CU_ASSERT_EQUAL(sk, SPDK_SCSI_SENSE_ILLEGAL_REQUEST);
|
||||
CU_ASSERT_EQUAL(asc, SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE);
|
||||
CU_ASSERT_EQUAL(ascq, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
|
||||
/* SPDK_NVME_SCT_COMMAND_SPECIFIC */
|
||||
bdev_io.error.nvme.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
|
||||
bdev_io.error.nvme.sc = SPDK_NVME_SC_INVALID_FORMAT;
|
||||
spdk_scsi_nvme_translate(&bdev_io, &sc, &sk, &asc, &ascq);
|
||||
CU_ASSERT_EQUAL(sc, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||
CU_ASSERT_EQUAL(sk, SPDK_SCSI_SENSE_ILLEGAL_REQUEST);
|
||||
CU_ASSERT_EQUAL(asc, SPDK_SCSI_ASC_FORMAT_COMMAND_FAILED);
|
||||
CU_ASSERT_EQUAL(ascq, SPDK_SCSI_ASCQ_FORMAT_COMMAND_FAILED);
|
||||
|
||||
bdev_io.error.nvme.sc = SPDK_NVME_SC_OVERLAPPING_RANGE;
|
||||
spdk_scsi_nvme_translate(&bdev_io, &sc, &sk, &asc, &ascq);
|
||||
CU_ASSERT_EQUAL(sc, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||
CU_ASSERT_EQUAL(sk, SPDK_SCSI_SENSE_ILLEGAL_REQUEST);
|
||||
CU_ASSERT_EQUAL(asc, SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE);
|
||||
CU_ASSERT_EQUAL(ascq, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
|
||||
/* SPDK_NVME_SCT_MEDIA_ERROR */
|
||||
bdev_io.error.nvme.sct = SPDK_NVME_SCT_MEDIA_ERROR;
|
||||
bdev_io.error.nvme.sc = SPDK_NVME_SC_GUARD_CHECK_ERROR;
|
||||
spdk_scsi_nvme_translate(&bdev_io, &sc, &sk, &asc, &ascq);
|
||||
CU_ASSERT_EQUAL(sc, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||
CU_ASSERT_EQUAL(sk, SPDK_SCSI_SENSE_MEDIUM_ERROR);
|
||||
CU_ASSERT_EQUAL(asc, SPDK_SCSI_ASC_LOGICAL_BLOCK_GUARD_CHECK_FAILED);
|
||||
CU_ASSERT_EQUAL(ascq, SPDK_SCSI_ASCQ_LOGICAL_BLOCK_GUARD_CHECK_FAILED);
|
||||
|
||||
bdev_io.error.nvme.sc = SPDK_NVME_SC_DEALLOCATED_OR_UNWRITTEN_BLOCK;
|
||||
spdk_scsi_nvme_translate(&bdev_io, &sc, &sk, &asc, &ascq);
|
||||
CU_ASSERT_EQUAL(sc, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||
CU_ASSERT_EQUAL(sk, SPDK_SCSI_SENSE_ILLEGAL_REQUEST);
|
||||
CU_ASSERT_EQUAL(asc, SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE);
|
||||
CU_ASSERT_EQUAL(ascq, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
|
||||
/* SPDK_NVME_SCT_VENDOR_SPECIFIC */
|
||||
bdev_io.error.nvme.sct = SPDK_NVME_SCT_VENDOR_SPECIFIC;
|
||||
bdev_io.error.nvme.sc = 0xff;
|
||||
spdk_scsi_nvme_translate(&bdev_io, &sc, &sk, &asc, &ascq);
|
||||
CU_ASSERT_EQUAL(sc, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||
CU_ASSERT_EQUAL(sk, SPDK_SCSI_SENSE_ILLEGAL_REQUEST);
|
||||
CU_ASSERT_EQUAL(asc, SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE);
|
||||
CU_ASSERT_EQUAL(ascq, SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
unsigned int num_failures;
|
||||
|
||||
if (CU_initialize_registry() != CUE_SUCCESS) {
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
suite = CU_add_suite("scsi_nvme_suite", null_init, null_clean);
|
||||
if (suite == NULL) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
if (
|
||||
CU_add_test(suite, "scsi_nvme - translate nvme error to scsi error",
|
||||
scsi_nvme_translate_test) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
num_failures = CU_get_number_of_failures();
|
||||
CU_cleanup_registry();
|
||||
return num_failures;
|
||||
}
|
@ -27,6 +27,7 @@ test/lib/nvmf/subsystem/subsystem_ut
|
||||
test/lib/scsi/dev/dev_ut
|
||||
test/lib/scsi/lun/lun_ut
|
||||
test/lib/scsi/scsi_bdev/scsi_bdev_ut
|
||||
test/lib/scsi/scsi_nvme/scsi_nvme_ut
|
||||
|
||||
test/lib/util/bit_array/bit_array_ut
|
||||
test/lib/util/io_channel/io_channel_ut
|
||||
|
Loading…
Reference in New Issue
Block a user