Repository navigation
Pause the runner between Jobs while an md array syncs - #1185
Merged
Merged
Conversation
Before each Ready, the runner probes its md arrays. While any runs a resync, recovery, check, repair, or reshape, it sends Paused instead, waits for NoJob or Update as after Ready, and probes again. A Job sent to a paused runner is failed unrun. While paused, a reconnect first waits out one poll, so a server that closes on Paused sees no more connects than polls. --no-raid-pause keeps taking Jobs through a sync.
epompeii
marked this pull request as ready for review
October 9, 2026 22:34
epompeii
added this pull request to stack #1188
October 9, 2026 22:34
Contributor
|
| Project | Bencher |
| Branch | u/ep/runner-protocol/raid-pause |
| Testbed | intel-v1 |
Click to view all benchmark results
| Benchmark | Latency | Benchmark Result microseconds (µs) (Result Δ%) | Upper Boundary microseconds (µs) (Limit %) |
|---|---|---|---|
| Adapter::Json | 📈 view plot 🚷 view threshold | 5.18 µs(+0.22%)Baseline: 5.17 µs | 5.97 µs (86.79%) |
| Adapter::Magic (JSON) | 📈 view plot 🚷 view threshold | 5.02 µs(+0.74%)Baseline: 4.99 µs | 5.65 µs (88.91%) |
| Adapter::Magic (Rust) | 📈 view plot 🚷 view threshold | 24.11 µs(-10.21%)Baseline: 26.85 µs | 31.22 µs (77.23%) |
| Adapter::Rust | 📈 view plot 🚷 view threshold | 4.48 µs(-1.55%)Baseline: 4.55 µs | 6.14 µs (72.98%) |
| Adapter::RustBench | 📈 view plot 🚷 view threshold | 4.50 µs(-0.97%)Baseline: 4.55 µs | 6.14 µs (73.36%) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Make
runner upprobe its host's md arrays before eachready, and sendpausedinstead while any array syncs, so no Job starts on disks that a resync, recovery, or scrub keeps busy. This is the runner half ofpaused(#1122).ready, never during a Job. It readssync_action,sync_completed, andsync_speedfor each/sys/block/md*entry with anmd/directory.sync_actionisresync,recover,check,repair, orreshapeandsync_completedis notnone, which covers a running sync (N / M) and one queued behind another array (delayed).idle,frozen, an action this runner does not know, an array with no sync thread such as raid0, and a host with no arrays never pause.pausedcarries oneraidreason per busy array, with its action, progress, and speed, plussinceand everyreadyfield.sinceis when the pause began by the runner's clock, and it holds for the whole pause, whatever its reasons become.pausedthe runner waits forno_joborupdateexactly as afterready, then probes again. The server holds the poll, so a paused runner stays connected, still updates itself, and takes Jobs again within one poll of the sync ending.The runner was paused for a RAID sync on md0, so it ran no Job, through the usual terminal message, ACK, and retry, and norunning.Paused for a RAID syncrecord per busy array when a pause begins (array,action,percent,speed_kib),Pause endedwhen it ends, andHolding off the reconnect while pausedwithhold_secs. A pause whose reasons change mid-pause is not logged again.--no-raid-pauseonrunner upkeeps taking Jobs through a sync. The pause is on by default, andraid_pauseis in theRunner startingrecord.runner upreference documents the flag in all 9 languages, and the changelog gains a line.With #1125 and #1130 on the server, the pause shows on the admin runner endpoints, and a pause past 12 hours mails the server admins.
Across versions:
no_jobon the same channel.paused, so it closes the channel. The runner then reconnects no faster than once per poll, so such a server sees no more connects than polls, and no self-update reaches the runner until its pause ends. The firstreadyafter the pause takes Jobs as before.Why
A sync reads or writes the whole array, and a Job measured during one measures the disks' contention as much as the benchmark. Probing only between Jobs leaves a running Job alone: a sync that starts mid-Job does not stop it, and the next Job waits.
sync_actionalone is not enough. It readsrecoverwhile a recovery is needed but cannot run, such as on a degraded array with no spare, which would pause the runner until someone adds a disk. A running or queued sync thread is what keeps the disks busy, sosync_completedhas to say one exists.Holding the poll on the server, rather than sleeping on the runner, reuses the timers
readyalready has, so the runner needs no sleep of its own for the pause.The reconnect hold is for a server without
paused. Without it, a runner whose channel closes on everypausedreconnects every 5 to 10 s, about 480 times an hour, and trips a runner connect limit of 256 an hour after about half an hour; connects then fail even after the pause ends, until the hour drains. With the hold, a runner reconnects at most about3600 / (poll + 7.5)times an hour: about 58 at the default 55 s poll. A poll under about 7 s would still pass 256 an hour against such a server.The server never claims a Job for a paused runner, so a Job that arrives anyway is failed rather than measured on busy disks.
Verification
a_running_sync_of_each_kind_pauses: a busy set that misses an action, or countsfrozen,idle, or an unknown action as busy.a_sync_action_with_no_sync_thread_does_not_pause: busy onsync_actionalone (recoverwithsync_completednone).a_queued_sync_pauses_with_no_progress:delayednot busy.a_pause_reason_carries_the_progress_and_speed: swapped or dropped progress and speed, and an array named after anything but its block device.a_host_with_no_arrays_never_pausesandan_array_with_no_sync_thread_is_listed_but_never_busy: a disk with nomd/read as an array, a host with noblockdirectory failing, and raid0 dropped or busy.a_busy_probe_pauses_and_a_clear_one_sends_ready: the probe's reasons ignored, apausedwithoutready's fields (the server's update check needs the runner metadata), and ano_jobthat does not probe again.a_pause_keeps_its_start_and_is_logged_once_each_way: asincethat restarts each probe or outlives the pause, and a start or end logged every poll.a_paused_runner_still_updatesanda_job_after_a_pause_fails_without_running: a pause that ignoresupdate, and a paused runner that runs a Job.reconnects_hold_off_a_poll_only_while_paused, at a 55 s poll, drives every path that can reconnect while paused: the channel closed, a refused connect, a receive timeout, a failed self-update, a Job failed unrun whose result is lost with the connection, and each of the 3 ways its resend can fail at the next connect. Removing the hold at any one of those 8 sites fails it, and so do a fixed 30 s hold and a hold that outlives the pause. The ninth reconnect site, a connection lost during a Job, cannot be reached while paused.a_paused_reconnect_holds_off_for_the_whole_holdanda_stop_ends_a_hold_within_one_slicerun the hold through the driver's effect: a hold that does not sleep, and one a stop cannot end.no_raid_pause_takes_jobs_through_a_syncandthe_raid_pause_is_on_unless_turned_off: the flag ignored by the probe, inverted, or off by default.runner upat a 5 s poll ran against a local API, with a RAID1 over two 2 GiB loop devices:echo check > sync_actionpaused the runner within 4 s, withPaused for a RAID sync(md0,check), and the server storedpausedwith theraidreason, its progress, and its speed.pendingat each of 12 checks over 60 s.echo idleended the pause at the next probe, 1 s later, and the Job was claimed that second and processed 2 s after.runner upat a 20 s poll was held paused by a maintenance marker from the next layer in this stack; the hold does not depend on the reason.pausedclosed the channel, and the runner loggedHolding off the reconnect while pausedwithhold_secs20.runner upin 0.50 s.runner_opstests pass, 86 of 86,cargo test-runner scenarios --build-onlypasses,Cargo.lockis unchanged, and clippy passes with-D warningsfor Linux x86_64, Linux aarch64, and macOS on the runner, its CLI,test_runner, andrunner_ops. The scenario suite passes as root, 99 of 99, and clippy passes for the whole workspace as CI runs it, on the top of this stack.