diff options
author | Muchun Song <songmuchun@bytedance.com> | 2020-10-07 06:16:33 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-10-14 11:32:57 +0300 |
commit | 75524f753318f61bcf974a3062973aff3a40394d (patch) | |
tree | 009b65d2dfc607c353554f877f591a9a51186d9c /fs/io_uring.c | |
parent | d9e81b2fb3724a0e4cc658a78b8905aabdb3ff44 (diff) | |
download | linux-75524f753318f61bcf974a3062973aff3a40394d.tar.xz |
io_uring: Fix missing smp_mb() in io_cancel_async_work()
The store to req->flags and load req->work_task should not be
reordering in io_cancel_async_work(). We should make sure that
either we store REQ_F_CANCE flag to req->flags or we see the
req->work_task setted in io_sq_wq_submit_work().
Fixes: 1c4404efcf2c ("io_uring: make sure async workqueue is canceled on exit")
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/io_uring.c')
-rw-r--r-- | fs/io_uring.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c index 33bd3ebdd3ef..27770af20d24 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2247,6 +2247,12 @@ restart: if (!ret) { req->work_task = current; + + /* + * Pairs with the smp_store_mb() (B) in + * io_cancel_async_work(). + */ + smp_mb(); /* A */ if (req->flags & REQ_F_CANCEL) { ret = -ECANCELED; goto end_req; @@ -3725,7 +3731,15 @@ static void io_cancel_async_work(struct io_ring_ctx *ctx, req = list_first_entry(&ctx->task_list, struct io_kiocb, task_list); list_del_init(&req->task_list); - req->flags |= REQ_F_CANCEL; + + /* + * The below executes an smp_mb(), which matches with the + * smp_mb() (A) in io_sq_wq_submit_work() such that either + * we store REQ_F_CANCEL flag to req->flags or we see the + * req->work_task setted in io_sq_wq_submit_work(). + */ + smp_store_mb(req->flags, req->flags | REQ_F_CANCEL); /* B */ + if (req->work_task && (!files || req->files == files)) send_sig(SIGINT, req->work_task, 1); } |