__io_u_log_error expects a positive value of io_u->error parsing it with strerror() expecting it to be an errno. io_uring_cmd (cmd_type=nvme), for example, has returned errno value as a positive value and device-specific CQE status type and code as well. Commit 78831c6b35c5 ("io_uring: Fix the flip to negative of CQE status") has put the abs() to the cqe->res, and it caused confusions between the actual CQE stauts and the system error value (errno). Now we have Commit 2a13699a89dc ("io_uring: Add .errdetails to parse CQ status"), meaning that io_uring_cmd ioengines will parse the actual value of io_u->error value as CQE status value, so we should know if the value is for CQE status or errno. This patch added a flag IO_U_F_DEVICE_ERROR to io_u to represent if io_u->error has device-specific error value, otherwise it's errno. Signed-off-by: Minwoo Im <minwoo.im.dev@xxxxxxxxx> --- engines/io_uring.c | 22 ++++++++++++++++------ io_u.c | 9 ++++++--- io_u.h | 1 + 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/engines/io_uring.c b/engines/io_uring.c index 96a042a88820..1ab9a1765e38 100644 --- a/engines/io_uring.c +++ b/engines/io_uring.c @@ -528,12 +528,9 @@ static struct io_u *fio_ioring_cmd_event(struct thread_data *td, int event) cqe = &ld->cq_ring.cqes[index]; io_u = (struct io_u *) (uintptr_t) cqe->user_data; - if (cqe->res != 0) { - io_u->error = abs(cqe->res); - return io_u; - } else { - io_u->error = 0; - } + io_u->error = cqe->res; + if (io_u->error != 0) + goto ret; if (o->cmd_type == FIO_URING_CMD_NVME) { data = FILE_ENG_DATA(io_u->file); @@ -544,6 +541,16 @@ static struct io_u *fio_ioring_cmd_event(struct thread_data *td, int event) } } +ret: + /* + * If IO_U_F_DEVICE_ERROR is not set, io_u->error will be parsed as an + * errno, otherwise device-specific error value (status value in CQE). + */ + if ((int)io_u->error > 0) + io_u_set(td, io_u, IO_U_F_DEVICE_ERROR); + else + io_u_clear(td, io_u, IO_U_F_DEVICE_ERROR); + io_u->error = abs(io_u->error); return io_u; } @@ -557,6 +564,9 @@ static char *fio_ioring_cmd_errdetails(struct thread_data *td, #define MAXMSGCHUNK 128 char *msg, msgchunk[MAXMSGCHUNK]; + if (!(io_u->flags & IO_U_F_DEVICE_ERROR)) + return NULL; + msg = calloc(1, MAXERRDETAIL); strcpy(msg, "io_uring_cmd: "); diff --git a/io_u.c b/io_u.c index c49cd4df0237..b699169d79b5 100644 --- a/io_u.c +++ b/io_u.c @@ -1956,7 +1956,8 @@ static void __io_u_log_error(struct thread_data *td, struct io_u *io_u) log_err("fio: io_u error%s%s: %s: %s offset=%llu, buflen=%llu\n", io_u->file ? " on file " : "", io_u->file ? io_u->file->file_name : "", - strerror(io_u->error), + (io_u->flags & IO_U_F_DEVICE_ERROR) ? + "Device-specific error" : strerror(io_u->error), io_ddir_name(io_u->ddir), io_u->offset, io_u->xfer_buflen); @@ -1965,8 +1966,10 @@ static void __io_u_log_error(struct thread_data *td, struct io_u *io_u) if (td->io_ops->errdetails) { char *err = td->io_ops->errdetails(td, io_u); - log_err("fio: %s\n", err); - free(err); + if (err) { + log_err("fio: %s\n", err); + free(err); + } } if (!td->error) diff --git a/io_u.h b/io_u.h index ab93d50f967e..20afad667ee1 100644 --- a/io_u.h +++ b/io_u.h @@ -22,6 +22,7 @@ enum { IO_U_F_BARRIER = 1 << 6, IO_U_F_VER_LIST = 1 << 7, IO_U_F_PATTERN_DONE = 1 << 8, + IO_U_F_DEVICE_ERROR = 1 << 9, }; /* -- 2.34.1