Re: [PATCH v3 3/3] io_uring: don't get completion_lock in io_poll_rewait()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



hi,

On 10/25/21 06:38, Xiaoguang Wang wrote:
In current implementation, if there are not available events,
io_poll_rewait() just gets completion_lock, and unlocks it in
io_poll_task_func() or io_async_task_func(), which isn't necessary.

Change this logic to let io_poll_task_func() or io_async_task_func()
get the completion_lock lock.

Signed-off-by: Xiaoguang Wang <xiaoguang.wang@xxxxxxxxxxxxxxxxx>
---
  fs/io_uring.c | 58 ++++++++++++++++++++++++++--------------------------------
  1 file changed, 26 insertions(+), 32 deletions(-)

diff --git a/fs/io_uring.c b/fs/io_uring.c
index e4c779dac953..41ff8fdafe55 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -5248,10 +5248,7 @@ static inline int __io_async_wake(struct io_kiocb *req, struct io_poll_iocb *pol
  }
    static bool io_poll_rewait(struct io_kiocb *req, struct io_poll_iocb *poll)
-    __acquires(&req->ctx->completion_lock)
  {
-    struct io_ring_ctx *ctx = req->ctx;
-
      /* req->task == current here, checking PF_EXITING is safe */
      if (unlikely(req->task->flags & PF_EXITING))
          WRITE_ONCE(poll->canceled, true);
@@ -5262,7 +5259,6 @@ static bool io_poll_rewait(struct io_kiocb *req, struct io_poll_iocb *poll)
          req->result = vfs_poll(req->file, &pt) & poll->events;
      }
  -    spin_lock(&ctx->completion_lock);

Don't remember poll sync too well but this was synchronising with the
final section of __io_arm_poll_handler(), and I'm afraid it may go
completely loose with races.
Yeah, I understand your concerns, and the final section of __io_arm_poll_handler() sees
very complicated, it maybe need better cleanup.

After checking my patch and __io_arm_poll_handler() again, I think the race which maybe
introduced in my patch is that:
  1)  __io_arm_poll_handler() calls list_del_init(&poll->wait.entry) under completion_lock.
  2) io_poll_rewait calls add_wait_queue() without completion_lock.

But __io_arm_poll_handler() only calls list_del_init(&poll->wait.entry)  when mask isn't zero. and io_poll_rewait() only calls add_wait_queue when no real event happens(mask is zero).
So 1) and 2) should not happen at the same time, seems that there's no race.

Regards,
Xiaoguang Wang



      if (!req->result && !READ_ONCE(poll->canceled)) {
          if (req->opcode == IORING_OP_POLL_ADD)
              WRITE_ONCE(poll->active, true);




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux