summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2019-08-22 07:19:11 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-08-29 09:30:27 +0300
commit28ad328e672bc799452e8481ef35fa58654f682f (patch)
treeec3aab8450c020443fc3fff64fa6b9916a3240ae
parent7fe55f17deee0def02df3f604c13d78e94db6e04 (diff)
downloadlinux-28ad328e672bc799452e8481ef35fa58654f682f.tar.xz
io_uring: add need_resched() check in inner poll loop
[ Upstream commit 08f5439f1df25a6cf6cf4c72cf6c13025599ce67 ] The outer poll loop checks for whether we need to reschedule, and returns to userspace if we do. However, it's possible to get stuck in the inner loop as well, if the CPU we are running on needs to reschedule to finish the IO work. Add the need_resched() check in the inner loop as well. This fixes a potential hang if the kernel is configured with CONFIG_PREEMPT_VOLUNTARY=y. Reported-by: Sagi Grimberg <sagi@grimberg.me> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Tested-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--fs/io_uring.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 83e3cede1122..03cd8f5bba85 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -716,7 +716,7 @@ static int io_do_iopoll(struct io_ring_ctx *ctx, unsigned int *nr_events,
static int io_iopoll_getevents(struct io_ring_ctx *ctx, unsigned int *nr_events,
long min)
{
- while (!list_empty(&ctx->poll_list)) {
+ while (!list_empty(&ctx->poll_list) && !need_resched()) {
int ret;
ret = io_do_iopoll(ctx, nr_events, min);
@@ -743,6 +743,12 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
unsigned int nr_events = 0;
io_iopoll_getevents(ctx, &nr_events, 1);
+
+ /*
+ * Ensure we allow local-to-the-cpu processing to take place,
+ * in this case we need to ensure that we reap all events.
+ */
+ cond_resched();
}
mutex_unlock(&ctx->uring_lock);
}