Suppose there are three IOs here, and their order is as follows:

Submit:
        [1] IO_LINK
            |
            |---  [2] IO_LINK | IO_DRAIN
                      |
                      |- [3] NORMAL_IO

In theory, they all need to be inserted into the Link-list, but flag
IO_DRAIN we have, io[2] and io[3] will be inserted into the defer_list,
and finally, io[3] and io[2] will be processed at the same time.

Now, it is directly forbidden to pass these two flags at the same time.

Fixes: 9e645e1105c ("io_uring: add support for sqe links")
Signed-off-by: Jackie Liu <liuyu...@kylinos.cn>
---
 fs/io_uring.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index d542f1c..05ee628 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -2074,10 +2074,13 @@ static void io_submit_sqe(struct io_ring_ctx *ctx, 
struct sqe_submit *s,
 {
        struct io_uring_sqe *sqe_copy;
        struct io_kiocb *req;
+       unsigned int flags;
        int ret;
 
+       flags = READ_ONCE(s->sqe->flags);
        /* enforce forwards compatibility on users */
-       if (unlikely(s->sqe->flags & ~SQE_VALID_FLAGS)) {
+       if (unlikely((flags & ~SQE_VALID_FLAGS) ||
+                    (flags & (IOSQE_IO_DRAIN | IOSQE_IO_LINK)))) {
                ret = -EINVAL;
                goto err;
        }
@@ -2093,6 +2096,8 @@ static void io_submit_sqe(struct io_ring_ctx *ctx, struct 
sqe_submit *s,
 err_req:
                io_free_req(req);
 err:
+               if (*link)
+                       io_fail_links(*link);
                io_cqring_add_event(ctx, s->sqe->user_data, ret);
                return;
        }
-- 
2.7.4



Reply via email to