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);