bdev: add function to return aio's errno
This helps user to locate whether bdev_io fails in spdk bdev layer or inside Linux AIO. SPDK_BDEV_IO_STATUS_AIO_ERROR indicates bdev_io fails due to Linux AIO or its lower layer's failure. New functions spdk_bdev_io_complete_aio_status and spdk_bdev_io_get_aio_status can be used to report out the errno from Linux AIO. Change-Id: I32640e4a0459cca057278c02ea5a7522f3408a02 Signed-off-by: Liu Xiaodong <xiaodong.liu@intel.com> Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/5690 Community-CI: Broadcom CI Community-CI: Mellanox Build Bot Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
bf10299893
commit
021ff6edff
@ -15,6 +15,11 @@ examine process. Along with corresponding `bdev_wait_for_examine` RPC, which
|
|||||||
is now always called during `spdk_bdev_subsystem_config_json` making sure
|
is now always called during `spdk_bdev_subsystem_config_json` making sure
|
||||||
every bdev is ready to be used.
|
every bdev is ready to be used.
|
||||||
|
|
||||||
|
A new API `spdk_bdev_io_get_aio_status` was added for getting the status of
|
||||||
|
bdev_io as Linux AIO errno. Also `spdk_bdev_io_complete_aio_status` function
|
||||||
|
and `SPDK_BDEV_IO_STATUS_AIO_ERROR` were added for bdev module to complete
|
||||||
|
a bdev_io with Linux AIO errno.
|
||||||
|
|
||||||
### blob
|
### blob
|
||||||
|
|
||||||
An `opts_size` element was added in the `spdk_bs_opts` structure to solve the
|
An `opts_size` element was added in the `spdk_bs_opts` structure to solve the
|
||||||
|
@ -1678,6 +1678,14 @@ void spdk_bdev_io_get_nvme_fused_status(const struct spdk_bdev_io *bdev_io, uint
|
|||||||
void spdk_bdev_io_get_scsi_status(const struct spdk_bdev_io *bdev_io,
|
void spdk_bdev_io_get_scsi_status(const struct spdk_bdev_io *bdev_io,
|
||||||
int *sc, int *sk, int *asc, int *ascq);
|
int *sc, int *sk, int *asc, int *ascq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the status of bdev_io as aio errno.
|
||||||
|
*
|
||||||
|
* \param bdev_io I/O to get the status from.
|
||||||
|
* \param aio_result Negative errno returned from AIO.
|
||||||
|
*/
|
||||||
|
void spdk_bdev_io_get_aio_status(const struct spdk_bdev_io *bdev_io, int *aio_result);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the iovec describing the data buffer of a bdev_io.
|
* Get the iovec describing the data buffer of a bdev_io.
|
||||||
*
|
*
|
||||||
|
@ -226,6 +226,7 @@ struct spdk_bdev_fn_table {
|
|||||||
|
|
||||||
/** bdev I/O completion status */
|
/** bdev I/O completion status */
|
||||||
enum spdk_bdev_io_status {
|
enum spdk_bdev_io_status {
|
||||||
|
SPDK_BDEV_IO_STATUS_AIO_ERROR = -8,
|
||||||
SPDK_BDEV_IO_STATUS_ABORTED = -7,
|
SPDK_BDEV_IO_STATUS_ABORTED = -7,
|
||||||
SPDK_BDEV_IO_STATUS_FIRST_FUSED_FAILED = -6,
|
SPDK_BDEV_IO_STATUS_FIRST_FUSED_FAILED = -6,
|
||||||
SPDK_BDEV_IO_STATUS_MISCOMPARE = -5,
|
SPDK_BDEV_IO_STATUS_MISCOMPARE = -5,
|
||||||
@ -643,6 +644,8 @@ struct spdk_bdev_io {
|
|||||||
/** SCSI additional sense code qualifier */
|
/** SCSI additional sense code qualifier */
|
||||||
uint8_t ascq;
|
uint8_t ascq;
|
||||||
} scsi;
|
} scsi;
|
||||||
|
/** Only valid when status is SPDK_BDEV_IO_STATUS_AIO_ERROR */
|
||||||
|
int aio_result;
|
||||||
} error;
|
} error;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -934,6 +937,14 @@ void spdk_bdev_io_complete_nvme_status(struct spdk_bdev_io *bdev_io, uint32_t cd
|
|||||||
void spdk_bdev_io_complete_scsi_status(struct spdk_bdev_io *bdev_io, enum spdk_scsi_status sc,
|
void spdk_bdev_io_complete_scsi_status(struct spdk_bdev_io *bdev_io, enum spdk_scsi_status sc,
|
||||||
enum spdk_scsi_sense sk, uint8_t asc, uint8_t ascq);
|
enum spdk_scsi_sense sk, uint8_t asc, uint8_t ascq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Complete a bdev_io with AIO errno.
|
||||||
|
*
|
||||||
|
* \param bdev_io I/O to complete.
|
||||||
|
* \param aio_result Negative errno returned from AIO.
|
||||||
|
*/
|
||||||
|
void spdk_bdev_io_complete_aio_status(struct spdk_bdev_io *bdev_io, int aio_result);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a thread that given bdev_io was submitted on.
|
* Get a thread that given bdev_io was submitted on.
|
||||||
*
|
*
|
||||||
|
@ -5278,6 +5278,34 @@ spdk_bdev_io_get_scsi_status(const struct spdk_bdev_io *bdev_io,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spdk_bdev_io_complete_aio_status(struct spdk_bdev_io *bdev_io, int aio_result)
|
||||||
|
{
|
||||||
|
if (aio_result == 0) {
|
||||||
|
bdev_io->internal.status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
||||||
|
} else {
|
||||||
|
bdev_io->internal.status = SPDK_BDEV_IO_STATUS_AIO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
bdev_io->internal.error.aio_result = aio_result;
|
||||||
|
|
||||||
|
spdk_bdev_io_complete(bdev_io, bdev_io->internal.status);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
spdk_bdev_io_get_aio_status(const struct spdk_bdev_io *bdev_io, int *aio_result)
|
||||||
|
{
|
||||||
|
assert(aio_result != NULL);
|
||||||
|
|
||||||
|
if (bdev_io->internal.status == SPDK_BDEV_IO_STATUS_AIO_ERROR) {
|
||||||
|
*aio_result = bdev_io->internal.error.aio_result;
|
||||||
|
} else if (bdev_io->internal.status == SPDK_BDEV_IO_STATUS_SUCCESS) {
|
||||||
|
*aio_result = 0;
|
||||||
|
} else {
|
||||||
|
*aio_result = -EIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
spdk_bdev_io_complete_nvme_status(struct spdk_bdev_io *bdev_io, uint32_t cdw0, int sct, int sc)
|
spdk_bdev_io_complete_nvme_status(struct spdk_bdev_io *bdev_io, uint32_t cdw0, int sct, int sc)
|
||||||
{
|
{
|
||||||
|
@ -87,6 +87,7 @@
|
|||||||
spdk_bdev_io_get_nvme_status;
|
spdk_bdev_io_get_nvme_status;
|
||||||
spdk_bdev_io_get_nvme_fused_status;
|
spdk_bdev_io_get_nvme_fused_status;
|
||||||
spdk_bdev_io_get_scsi_status;
|
spdk_bdev_io_get_scsi_status;
|
||||||
|
spdk_bdev_io_get_aio_status;
|
||||||
spdk_bdev_io_get_iovec;
|
spdk_bdev_io_get_iovec;
|
||||||
spdk_bdev_io_get_md_buf;
|
spdk_bdev_io_get_md_buf;
|
||||||
spdk_bdev_io_get_cb_arg;
|
spdk_bdev_io_get_cb_arg;
|
||||||
@ -116,6 +117,7 @@
|
|||||||
spdk_bdev_io_complete;
|
spdk_bdev_io_complete;
|
||||||
spdk_bdev_io_complete_nvme_status;
|
spdk_bdev_io_complete_nvme_status;
|
||||||
spdk_bdev_io_complete_scsi_status;
|
spdk_bdev_io_complete_scsi_status;
|
||||||
|
spdk_bdev_io_complete_aio_status;
|
||||||
spdk_bdev_io_get_thread;
|
spdk_bdev_io_get_thread;
|
||||||
spdk_bdev_io_get_io_channel;
|
spdk_bdev_io_get_io_channel;
|
||||||
spdk_bdev_notify_blockcnt_change;
|
spdk_bdev_notify_blockcnt_change;
|
||||||
|
@ -191,7 +191,7 @@ bdev_aio_readv(struct file_disk *fdisk, struct spdk_io_channel *ch,
|
|||||||
if (rc == -EAGAIN) {
|
if (rc == -EAGAIN) {
|
||||||
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_NOMEM);
|
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_NOMEM);
|
||||||
} else {
|
} else {
|
||||||
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_FAILED);
|
spdk_bdev_io_complete_aio_status(spdk_bdev_io_from_ctx(aio_task), rc);
|
||||||
SPDK_ERRLOG("%s: io_submit returned %d\n", __func__, rc);
|
SPDK_ERRLOG("%s: io_submit returned %d\n", __func__, rc);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@ -225,7 +225,7 @@ bdev_aio_writev(struct file_disk *fdisk, struct spdk_io_channel *ch,
|
|||||||
if (rc == -EAGAIN) {
|
if (rc == -EAGAIN) {
|
||||||
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_NOMEM);
|
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_NOMEM);
|
||||||
} else {
|
} else {
|
||||||
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_FAILED);
|
spdk_bdev_io_complete_aio_status(spdk_bdev_io_from_ctx(aio_task), rc);
|
||||||
SPDK_ERRLOG("%s: io_submit returned %d\n", __func__, rc);
|
SPDK_ERRLOG("%s: io_submit returned %d\n", __func__, rc);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@ -239,8 +239,11 @@ bdev_aio_flush(struct file_disk *fdisk, struct bdev_aio_task *aio_task)
|
|||||||
{
|
{
|
||||||
int rc = fsync(fdisk->fd);
|
int rc = fsync(fdisk->fd);
|
||||||
|
|
||||||
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task),
|
if (rc == 0) {
|
||||||
rc == 0 ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED);
|
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_SUCCESS);
|
||||||
|
} else {
|
||||||
|
spdk_bdev_io_complete_aio_status(spdk_bdev_io_from_ctx(aio_task), -errno);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -326,9 +329,9 @@ static int
|
|||||||
bdev_aio_io_channel_poll(struct bdev_aio_io_channel *io_ch)
|
bdev_aio_io_channel_poll(struct bdev_aio_io_channel *io_ch)
|
||||||
{
|
{
|
||||||
int nr, i = 0;
|
int nr, i = 0;
|
||||||
enum spdk_bdev_io_status status;
|
|
||||||
struct bdev_aio_task *aio_task;
|
struct bdev_aio_task *aio_task;
|
||||||
struct io_event events[SPDK_AIO_QUEUE_DEPTH];
|
struct io_event events[SPDK_AIO_QUEUE_DEPTH];
|
||||||
|
uint64_t io_result;
|
||||||
|
|
||||||
nr = bdev_user_io_getevents(io_ch->io_ctx, SPDK_AIO_QUEUE_DEPTH, events);
|
nr = bdev_user_io_getevents(io_ch->io_ctx, SPDK_AIO_QUEUE_DEPTH, events);
|
||||||
|
|
||||||
@ -336,16 +339,23 @@ bdev_aio_io_channel_poll(struct bdev_aio_io_channel *io_ch)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_AIO_ERRNO 256
|
||||||
for (i = 0; i < nr; i++) {
|
for (i = 0; i < nr; i++) {
|
||||||
aio_task = events[i].data;
|
aio_task = events[i].data;
|
||||||
if (events[i].res != aio_task->len) {
|
|
||||||
status = SPDK_BDEV_IO_STATUS_FAILED;
|
|
||||||
} else {
|
|
||||||
status = SPDK_BDEV_IO_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
aio_task->ch->io_inflight--;
|
aio_task->ch->io_inflight--;
|
||||||
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), status);
|
io_result = events[i].res;
|
||||||
|
if (io_result == aio_task->len) {
|
||||||
|
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_SUCCESS);
|
||||||
|
} else if (io_result < MAX_AIO_ERRNO) {
|
||||||
|
/* Linux AIO will return its errno to io_event.res */
|
||||||
|
int aio_errno = io_result;
|
||||||
|
|
||||||
|
spdk_bdev_io_complete_aio_status(spdk_bdev_io_from_ctx(aio_task), -aio_errno);
|
||||||
|
} else {
|
||||||
|
SPDK_ERRLOG("failed to complete aio: requested len is %lu, but completed len is %lu.\n",
|
||||||
|
aio_task->len, io_result);
|
||||||
|
spdk_bdev_io_complete(spdk_bdev_io_from_ctx(aio_task), SPDK_BDEV_IO_STATUS_FAILED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nr;
|
return nr;
|
||||||
|
Loading…
Reference in New Issue
Block a user