io_uring: Add IO_U_F_DEVICE_ERROR to identify error types
authorMinwoo Im <minwoo.im.dev@gmail.com>
Thu, 26 Sep 2024 00:41:34 +0000 (09:41 +0900)
committerJens Axboe <axboe@kernel.dk>
Thu, 26 Sep 2024 17:32:50 +0000 (11:32 -0600)
__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@gmail.com>
Link: https://lore.kernel.org/r/20240926004134.26004-1-minwoo.im.dev@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
engines/io_uring.c
io_u.c
io_u.h

index 96a042a88820b801481c737cbd931b646d2a6d49..1ab9a1765e381cb9cf168150056ca423b193ae92 100644 (file)
@@ -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 c49cd4df0237be5e1c25412d20390a0703eda04b..b699169d79b59ac45f58b5dae6604dc841cc024b 100644 (file)
--- 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 ab93d50f967e78547961e7650b2921f53f64f6b9..20afad667ee18679aac634145e9e440ee39c3ece 100644 (file)
--- 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,
 };
 
 /*