Repository navigation
Report the host's disk health with Ready and Paused - #1190
Merged
epompeii merged 1 commit intoOct 10, 2026
Merged
Conversation
At every probe the runner reads its md arrays (array_state, degraded, sync_action), and at most hourly each NVMe controller's SMART / health log through the admin passthrough, which needs CAP_SYS_ADMIN; a runner that is not root reports md alone and its controllers with no log. Warning is spare at or below twice its threshold, more than 80 percent used, the temperature bit, or any media error; failing is any other critical warning bit, spare below its threshold, or a degraded array. Nothing pauses on health.
epompeii
added this pull request to stack #1188
October 9, 2026 23:01
Contributor
|
| Project | Bencher |
| Branch | u/ep/runner-protocol/health-report |
| 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.10%)Baseline: 5.19 µs | 5.88 µs (88.13%) |
| Adapter::Magic (JSON) | 📈 view plot 🚷 view threshold | 5.02 µs(+0.42%)Baseline: 5.00 µs | 5.58 µs (90.03%) |
| Adapter::Magic (Rust) | 📈 view plot 🚷 view threshold | 24.54 µs(-8.41%)Baseline: 26.80 µs | 31.51 µs (77.89%) |
| Adapter::Rust | 📈 view plot 🚷 view threshold | 4.49 µs(-2.09%)Baseline: 4.58 µs | 5.96 µs (75.26%) |
| Adapter::RustBench | 📈 view plot 🚷 view threshold | 4.46 µs(-2.66%)Baseline: 4.58 µs | 5.96 µs (74.76%) |
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 the runner send its host's disk health with every
readyandpaused, in thehealthfield that #1125 stores, so admins see it on the runner endpoints and #1130 mails them when it is news.array_state,degraded, andsync_action, read with the RAID pause's own read. An array with no sync thread, such as raid0, readsidle. A degraded array is adegradedfinding that isfailing./sys/class/nvme, with its model, its serial, and the SMART / health log fields that set a finding: critical warning, temperature, spare and its threshold, percentage used, and media errors. The page is read with Get Log Page (log0x02, all namespaces, 512 bytes) through the kernel's admin passthrough,NVME_IOCTL_ADMIN_CMD, on a read-only open of/dev/<controller>. The read is cached for an hour, and only the probe reads it, so never during a Job.warning: spare at or below twice its threshold, percentage used over 80, the temperature critical warning bit, or any media and data integrity error;failing: any other critical warning bit, spare below its threshold, or a degraded array;okwith none.CAP_SYS_ADMIN. It lists each controller with no log, warns once withNVMe health not read, so it is reported unreadable, and still reports md.okwith empty lists.AdminCommandis the kernel'sstruct nvme_admin_cmd, pinned at 72 bytes by a const assertion.nixgains itsioctlfeature, which adds no package toCargo.lock.Across versions:
health, since the runner messages accept unknown fields.pausedneeds a server with Let a runner pause on its channel without taking a job #1122, as in the layers below.Why
A degraded array or a failing NVMe drive on a runner host is silent until the next disk fails too. The server half stores health and mails admins on news; this is what sends it.
md costs a few sysfs reads, so it is read at every probe. Each NVMe read is an admin command to the drive, so it runs at most hourly, and only between Jobs.
The temperature bit is a warning, not failing, because it clears by itself. Media errors warn while their count is nonzero, rather than when it rises, which would read
okagain at the next hourly read.Health is reported, never a pause. An idle degraded array barely moves a benchmark, and the mail reaches whoever can replace the disk. Health still rides on
paused, because the rebuild after a disk is replaced is a pause, and that is when health matters most.Verification
a_page_parses_little_endian_at_its_offsetsanda_media_error_count_past_u64_saturates: swapped temperature bytes, media errors read big-endian or from the wrong counter, spare read from the threshold byte, and a 128-bit count that wraps.a_healthy_page_has_no_findingsandeach_critical_warning_bit_but_temperature_is_failing, over bits 0 and 2 to 7: a rule that fires on a healthy page, any one critical bit missed, and the temperature bit failing or ignored.spare_at_twice_its_threshold_warns_and_below_it_fails,percentage_used_over_80_warns, andany_media_error_warns: either spare boundary or the endurance boundary moved by one, and media errors ignored or failing.an_unreadable_log_still_lists_the_controller: an unreadable controller dropped, and a log read from another device.a_degraded_array_is_failingandthe_worst_finding_sets_the_state: a degraded array that reads healthy, every array failing, and the state taken from the first finding rather than the worst.nvme_is_read_at_most_hourly, on an injected clock and reader: read once at the start, served from the cache 1 s before the hour, and read again at the hour. Kills a read every probe, and one never repeated.an_unreadable_nvme_still_reports_mdandevery_probe_reports_md_health: a runner that is not root reporting nothing, and a probe that sends no health, or none with the RAID pause off.the_probes_health_rides_on_ready_and_paused: health dropped from either message.linux/nvme_ioctl.hgivessizeof(struct nvme_admin_cmd)72,NVME_IOCTL_ADMIN_CMD0xc0484e41, andaddr,data_len, andcdw10at offsets 24, 36, and 40, which the Rust struct andioctl_readwrite!(b'N', 0x41)match.nvme-looptarget, backed by a file, stood in for a drive:nvme smart-log's values for that controller.EACCES, the controller is listed with no log, and md is still reported.0x600f, which the fixture pages cannot show.runner upran against a local API, with a RAID1 over two loop devices:okwithmd0clean, 0 degraded,idle.mdadm --failon one member: the next report readfailing, withmd0degradedfailing, and the runner stillready. A Job submitted then ran.mdadm --removeand--add: the runner paused for therecoversync with health stillfailing. Once the recovery finished, the pause ended, and the next report readreadyandok.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, 100 of 100, and clippy passes for the whole workspace as CI runs it, on the top of this stack.