]> www.infradead.org Git - users/hch/misc.git/commitdiff
io_uring: check if we need to reschedule during overflow flush
authorJens Axboe <axboe@kernel.dk>
Fri, 20 Sep 2024 08:51:20 +0000 (02:51 -0600)
committerJens Axboe <axboe@kernel.dk>
Fri, 20 Sep 2024 08:51:20 +0000 (02:51 -0600)
In terms of normal application usage, this list will always be empty.
And if an application does overflow a bit, it'll have a few entries.
However, nothing obviously prevents syzbot from running a test case
that generates a ton of overflow entries, and then flushing them can
take quite a while.

Check for needing to reschedule while flushing, and drop our locks and
do so if necessary. There's no state to maintain here as overflows
always prune from head-of-list, hence it's fine to drop and reacquire
the locks at the end of the loop.

Link: https://lore.kernel.org/io-uring/66ed061d.050a0220.29194.0053.GAE@google.com/
Reported-by: syzbot+5fca234bd7eb378ff78e@syzkaller.appspotmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/io_uring.c

index d306f566a944ca7b35518845dc7c45a381513b7c..4199fbe6ce13ff2eba5a44ce2614c967fe027c16 100644 (file)
@@ -624,6 +624,21 @@ static void __io_cqring_overflow_flush(struct io_ring_ctx *ctx, bool dying)
                }
                list_del(&ocqe->list);
                kfree(ocqe);
+
+               /*
+                * For silly syzbot cases that deliberately overflow by huge
+                * amounts, check if we need to resched and drop and
+                * reacquire the locks if so. Nothing real would ever hit this.
+                * Ideally we'd have a non-posting unlock for this, but hard
+                * to care for a non-real case.
+                */
+               if (need_resched()) {
+                       io_cq_unlock_post(ctx);
+                       mutex_unlock(&ctx->uring_lock);
+                       cond_resched();
+                       mutex_lock(&ctx->uring_lock);
+                       io_cq_lock(ctx);
+               }
        }
 
        if (list_empty(&ctx->cq_overflow_list)) {