History

io_uring: check if we need to reschedule during overflow flush

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.

Jens Axboe committed 2 years ago

Commit eac2ca21 parent eed138d1 file · +15 −0Browse files

Unified · Split

io_uring/io_uring.c+15−0
@@ -624,6 +624,21 @@ static void __io_cqring_overflow_flush(struct io_ring_ctx *ctx, bool dying) · 623 unmodified lines
624624 }
625625 list_del(&ocqe->list);
626626 kfree(ocqe);
627+
628+ /*
629+ * For silly syzbot cases that deliberately overflow by huge
630+ * amounts, check if we need to resched and drop and
631+ * reacquire the locks if so. Nothing real would ever hit this.
632+ * Ideally we'd have a non-posting unlock for this, but hard
633+ * to care for a non-real case.
634+ */
635+ if (need_resched()) {
636+ io_cq_unlock_post(ctx);
637+ mutex_unlock(&ctx->uring_lock);
638+ cond_resched();
639+ mutex_lock(&ctx->uring_lock);
640+ io_cq_lock(ctx);
641+ }
627642 }
628643
629644 if (list_empty(&ctx->cq_overflow_list)) {