BackgroundProcess::run() blocks on blocking_background when
background_should_run() returns false. When the loop wakes up —
typically because arm_blocking_io_and_wake() kicked it — the loop
re-checks background_should_run(). If that still returns false
(e.g. the cleaner has no pending work), the loop goes straight back
to sleep.
But the wake may also have been triggered by a change in the space-
availability condition (should_block_io) — and there is no path that
re-evaluates blocked user IO when background_should_run is false. The
blocked IO has no future trigger to re-check, and stays stuck until
the next unrelated wake-up happens to come at the right moment, or
never.
Add a maybe_wake_blocked_io() call right after the wake. It's a no-op
when nothing is blocked, and unblocks IO that the space condition has
already cleared otherwise.
Observed in sustained random-write benches that wedged with IO blocked
indefinitely while the cleaner sat idle (should_run=false).
Signed-off-by: Shai Fultheim <shai.fultheim@gmail.com>
assert(!blocking_background);
blocking_background = seastar::promise<>();
co_await blocking_background->get_future();
+ // After waking (typically because arm_blocking_io_and_wake() kicked us),
+ // give any blocked user IO a chance to proceed. Without this call the
+ // loop would go straight back to sleep if background_should_run() is
+ // still false, but the space condition (should_block_io) may already be
+ // satisfied, leaving blocked IO stuck with no future trigger to re-check.
+ maybe_wake_blocked_io();
}
}
log_state("run(exit)");