bdev: add members for SCSI sense information in spdk_bdev_io (#59)
Custom bdev modules can return any SCSI status and SCSI sense information to a host by this patch. This is usefull when a custome bdev module detect an error in the module and need to return meaningful information to a host.
This commit is contained in:
parent
1ffec5d53a
commit
6583441f54
@ -137,6 +137,7 @@ struct spdk_bdev_fn_table {
|
|||||||
|
|
||||||
/** Blockdev I/O completion status */
|
/** Blockdev I/O completion status */
|
||||||
enum spdk_bdev_io_status {
|
enum spdk_bdev_io_status {
|
||||||
|
SPDK_BDEV_IO_STATUS_SCSI_ERROR = -3,
|
||||||
SPDK_BDEV_IO_STATUS_NVME_ERROR = -2,
|
SPDK_BDEV_IO_STATUS_NVME_ERROR = -2,
|
||||||
SPDK_BDEV_IO_STATUS_FAILED = -1,
|
SPDK_BDEV_IO_STATUS_FAILED = -1,
|
||||||
SPDK_BDEV_IO_STATUS_PENDING = 0,
|
SPDK_BDEV_IO_STATUS_PENDING = 0,
|
||||||
@ -252,6 +253,17 @@ struct spdk_bdev_io {
|
|||||||
/** NVMe status code */
|
/** NVMe status code */
|
||||||
int sc;
|
int sc;
|
||||||
} nvme;
|
} nvme;
|
||||||
|
/** Only valid when status is SPDK_BDEV_IO_STATUS_SCSI_ERROR */
|
||||||
|
struct {
|
||||||
|
/** SCSI status code */
|
||||||
|
enum spdk_scsi_status sc;
|
||||||
|
/** SCSI sense key */
|
||||||
|
enum spdk_scsi_sense sk;
|
||||||
|
/** SCSI additional sense code */
|
||||||
|
uint8_t asc;
|
||||||
|
/** SCSI additional sense code qualifier */
|
||||||
|
uint8_t ascq;
|
||||||
|
} scsi;
|
||||||
} error;
|
} error;
|
||||||
|
|
||||||
/** User function that will be called when this completes */
|
/** User function that will be called when this completes */
|
||||||
@ -321,4 +333,6 @@ int spdk_bdev_free_io(struct spdk_bdev_io *bdev_io);
|
|||||||
int spdk_bdev_reset(struct spdk_bdev *bdev, enum spdk_bdev_reset_type,
|
int spdk_bdev_reset(struct spdk_bdev *bdev, enum spdk_bdev_reset_type,
|
||||||
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
spdk_bdev_io_completion_cb cb, void *cb_arg);
|
||||||
struct spdk_io_channel *spdk_bdev_get_io_channel(struct spdk_bdev *bdev, uint32_t priority);
|
struct spdk_io_channel *spdk_bdev_get_io_channel(struct spdk_bdev *bdev, uint32_t priority);
|
||||||
|
void spdk_bdev_io_set_scsi_error(struct spdk_bdev_io *bdev_io, enum spdk_scsi_status sc,
|
||||||
|
enum spdk_scsi_sense sk, uint8_t asc, uint8_t ascq);
|
||||||
#endif /* SPDK_BDEV_H_ */
|
#endif /* SPDK_BDEV_H_ */
|
||||||
|
@ -836,6 +836,17 @@ spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status sta
|
|||||||
spdk_event_call(bdev_io->cb_event);
|
spdk_event_call(bdev_io->cb_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spdk_bdev_io_set_scsi_error(struct spdk_bdev_io *bdev_io, enum spdk_scsi_status sc,
|
||||||
|
enum spdk_scsi_sense sk, uint8_t asc, uint8_t ascq)
|
||||||
|
{
|
||||||
|
bdev_io->status = SPDK_BDEV_IO_STATUS_SCSI_ERROR;
|
||||||
|
bdev_io->error.scsi.sc = sc;
|
||||||
|
bdev_io->error.scsi.sk = sk;
|
||||||
|
bdev_io->error.scsi.asc = asc;
|
||||||
|
bdev_io->error.scsi.ascq = ascq;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
spdk_bdev_register(struct spdk_bdev *bdev)
|
spdk_bdev_register(struct spdk_bdev *bdev)
|
||||||
{
|
{
|
||||||
|
@ -1283,23 +1283,29 @@ spdk_bdev_scsi_task_complete(spdk_event_t event)
|
|||||||
enum spdk_bdev_io_status status = bdev_io->status;
|
enum spdk_bdev_io_status status = bdev_io->status;
|
||||||
|
|
||||||
if (task->type == SPDK_SCSI_TASK_TYPE_CMD) {
|
if (task->type == SPDK_SCSI_TASK_TYPE_CMD) {
|
||||||
int sc, sk, asc, ascq;
|
if (status == SPDK_BDEV_IO_STATUS_SUCCESS) {
|
||||||
|
|
||||||
switch (bdev_io->status) {
|
|
||||||
case SPDK_BDEV_IO_STATUS_SUCCESS:
|
|
||||||
task->status = SPDK_SCSI_STATUS_GOOD;
|
task->status = SPDK_SCSI_STATUS_GOOD;
|
||||||
break;
|
} else {
|
||||||
case SPDK_BDEV_IO_STATUS_NVME_ERROR:
|
int sc, sk, asc, ascq;
|
||||||
spdk_scsi_nvme_translate(bdev_io, &sc, &sk, &asc, &ascq);
|
|
||||||
|
switch (status) {
|
||||||
|
case SPDK_BDEV_IO_STATUS_NVME_ERROR:
|
||||||
|
spdk_scsi_nvme_translate(bdev_io, &sc, &sk, &asc, &ascq);
|
||||||
|
break;
|
||||||
|
case SPDK_BDEV_IO_STATUS_SCSI_ERROR:
|
||||||
|
sc = bdev_io->error.scsi.sc;
|
||||||
|
sk = bdev_io->error.scsi.sk;
|
||||||
|
asc = bdev_io->error.scsi.asc;
|
||||||
|
ascq = bdev_io->error.scsi.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;
|
||||||
|
break;
|
||||||
|
}
|
||||||
spdk_scsi_task_set_status(task, 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 */
|
/* command completed. remove from outstanding task list */
|
||||||
|
@ -483,10 +483,21 @@ task_complete_test(void)
|
|||||||
spdk_bdev_scsi_task_complete(&event);
|
spdk_bdev_scsi_task_complete(&event);
|
||||||
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_GOOD);
|
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_GOOD);
|
||||||
|
|
||||||
|
bdev_io.status = SPDK_BDEV_IO_STATUS_SCSI_ERROR;
|
||||||
|
bdev_io.error.scsi.sc = SPDK_SCSI_STATUS_CHECK_CONDITION;
|
||||||
|
bdev_io.error.scsi.sk = SPDK_SCSI_SENSE_HARDWARE_ERROR;
|
||||||
|
bdev_io.error.scsi.asc = SPDK_SCSI_ASC_WARNING;
|
||||||
|
bdev_io.error.scsi.ascq = SPDK_SCSI_ASCQ_POWER_LOSS_EXPECTED;
|
||||||
|
spdk_bdev_scsi_task_complete(&event);
|
||||||
|
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||||
|
CU_ASSERT_EQUAL(task.sense_data[2] & 0xf, SPDK_SCSI_SENSE_HARDWARE_ERROR);
|
||||||
|
CU_ASSERT_EQUAL(task.sense_data[12], SPDK_SCSI_ASC_WARNING);
|
||||||
|
CU_ASSERT_EQUAL(task.sense_data[13], SPDK_SCSI_ASCQ_POWER_LOSS_EXPECTED);
|
||||||
|
|
||||||
bdev_io.status = SPDK_BDEV_IO_STATUS_FAILED;
|
bdev_io.status = SPDK_BDEV_IO_STATUS_FAILED;
|
||||||
spdk_bdev_scsi_task_complete(&event);
|
spdk_bdev_scsi_task_complete(&event);
|
||||||
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
CU_ASSERT_EQUAL(task.status, SPDK_SCSI_STATUS_CHECK_CONDITION);
|
||||||
CU_ASSERT_EQUAL(task.sense_data[2], SPDK_SCSI_SENSE_ABORTED_COMMAND);
|
CU_ASSERT_EQUAL(task.sense_data[2] & 0xf, SPDK_SCSI_SENSE_ABORTED_COMMAND);
|
||||||
CU_ASSERT_EQUAL(task.sense_data[12], SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE);
|
CU_ASSERT_EQUAL(task.sense_data[12], SPDK_SCSI_ASC_NO_ADDITIONAL_SENSE);
|
||||||
CU_ASSERT_EQUAL(task.sense_data[13], SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
CU_ASSERT_EQUAL(task.sense_data[13], SPDK_SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user