Detect and quarantine wedged vGPU VFs - #435
Open
yummybomb wants to merge 3 commits into
Open
Conversation
yummybomb
force-pushed
the
hypeship/vgpu-wedge-quarantine
branch
from
August 20, 2026 19:12
d312338 to
7d54fb9
Compare
yummybomb
marked this pull request as ready for review
August 20, 2026 19:33
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7d54fb9. Configure here.
Detection moves from host-side matching of the raw NVRM kernel line to an explicit guest-to-host report: the guest agent watches /dev/kmsg for the driver's RmInitAdapter failure and emits a HYPEMAN-GPU-INIT-FAILED marker over the established sentinel-marker channel, which the controller convicts on. The raw kernel line is no longer matched, so detection now requires the guest agent; images without it do not report. Quarantine hardening in the same pass: - The conviction brake pauses instead of drops: a suppressed conviction leaves the tail open and the agent's re-emission retries it once the window clears. - A match on an already-quarantined VF is not a new conviction: no brake accounting, no metric, no wedge-count inflation on controller restarts. - Tails reset when the instance acquires a new assignment, so a finished tail from a previous boot or VF cannot suppress scanning the next one. - A vf-health state file that fails to load refuses mutations (and retries the load) instead of letting the next conviction clobber every previously persisted quarantine. - Oversized unterminated log lines are skipped instead of re-buffered on every scan. - The controller idles on hosts without the vendor VFIO framework. GPU.md: DCGM quiesce is now an ordered step of the recovery sequence, and clearing vf-health.json documents the immediate-restart requirement.
Review fixes on the quarantine layer: - start now archives the previous boot's serial log before persisting the new vGPU assignment. The sentinel keys its tail on the assignment epoch, so the old ordering let a scan replay the previous boot's wedge report against the freshly assigned VF. A failed archive is fatal for GPU instances instead of a warning. - placement and profile availability refuse to run when the VF health state file exists but cannot be loaded, instead of treating the empty in-memory set as healthy and returning every quarantined VF to rotation. The load is retried on each attempt, so a repaired file self-heals. - a conviction whose persist fails is rolled back from memory: keeping it made the next report look like a repeat conviction, ending retries with nothing on disk. - the marker pattern requires the full shape through the quoted NVRM payload; a truncated or payload-less marker echoed by an exec command no longer matches. - unreadable instance metadata in the sentinel target listing logs a warning instead of silently shrinking detection coverage. - GPU.md recovery runbook unwound a circularity: placement excludes quarantined VFs and there is no VF-pin API, so the entry is cleared before the verification boot; the sentinel re-quarantines automatically if the cycle did not cure the VF.
yummybomb
force-pushed
the
hypeship/vendor-vfio-vgpu
branch
from
August 20, 2026 20:17
7fdf159 to
869c259
Compare
yummybomb
force-pushed
the
hypeship/vgpu-wedge-quarantine
branch
from
August 20, 2026 20:17
7d54fb9 to
9a90223
Compare
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.

Summary
Killing the process holding a vendor VFIO VF during guest driver init (~8s window) silently corrupts the VF: every later boot on it fails while sysfs, NVML, and the vGPU plugin all look healthy. #321 removed hypeman's own kill triggers; this layer detects the wedges external kills (OOM, operator, deploy restarts) still cause, and takes the VF out of placement.
Detection — guest agent report, no lifecycle change. On a wedged VF the guest driver is present, trying, and failing: its kernel loops
NVRM: ... RmInitAdapter failed!in the guest kernel log. The guest agent watches/dev/kmsgfor that line and reports it as aHYPEMAN-GPU-INIT-FAILEDmarker — the same guest→host channel as the existingHYPEMAN-*markers, landing in the instance'slogs/app.log. A newVGPUSentinelControllertails that file for every instance holding a vendor VFIO assignment and convicts on the marker; the full marker shape is required since a bare token could appear in echoed exec command lines. The agent only watches when an NVIDIA PCI function is present, throttles re-emission to one per 30s, and matches the full kernel-line shape, never the driver-build-specific(0x22:0x65:884)tuple. A no-driver image never produces the kernel line and can never be convicted. An image that skips the guest agent does not report — v1 accepts that coverage bound; the raw kernel line still reachesapp.logfor manual diagnosis.Quarantine. Convictions persist to
<data-dir>/gpu/vf-health.json(keyed by VF address, survives restarts) under the placement lock. One wedge produces one record no matter how many victim boots or controller restarts report it. The store fails closed on an unreadable state file: mutations are refused, and vGPU placement and advertised availability are disabled (with load retried on each attempt) rather than treating the empty in-memory set as healthy and returning quarantined VFs to rotation. A conviction whose persist fails is rolled back from memory so the next report retries it instead of reading as a repeat. Start archives the previous boot's serial log before persisting a new assignment (fatal on failure for GPU instances), so a scan can never replay the prior boot's report against a freshly assigned VF. A conviction burst (>3 in 15m) pauses auto-conviction so a systemic non-wedge init failure (e.g. a driver-mismatch rollout) can't quarantine the fleet; a paused conviction retries on the agent's next re-emission and lands once the window clears.Placement.
Observability. Conviction logs at error level;
hypeman_instances_vgpu_sentinel_convictions_total(result=convicted|suppressed) andhypeman_instances_vgpu_quarantined_vfsgauge. The controller idles on hosts without the vendor VFIO framework.GPU.md documents the new behavior and the manual recovery flow (DCGM quiesce → SR-IOV cycle → restart services → verification boot → clear the VF's entry in
vf-health.json→ restart hypeman immediately).Out of scope (follow-up layer)
An operator force-cycle endpoint (DCGM quiesce →
sriov-manage -d/-e→ verification boot → clear quarantine). Until then recovery stays the documented manual runbook.Testing
go test -race ./lib/devices ./lib/paths ./lib/providers ./lib/system/guest_agentand the vGPU-relatedlib/instancestests pass locally;go vetclean. The fulllib/instancessuite fails only on environment-dependent VM/network tests, identically on the unmodified base.app.log) and the recovery sequence were validated on real L40S hardware by deliberately wedging VFs; the guest-agent watcher and the controller have not yet run against a live wedge end-to-end — that run should happen on the dev GPU host before this merges.Note
Medium Risk
Changes vGPU placement, advertised GPU capacity, and guest-agent reporting. A false conviction or store-load failure can shrink GPU inventory until operators clear
vf-health.jsonand restart.Overview
Automatically detects wedged vendor VFIO vGPU VFs (guest
RmInitAdaptertimeout with healthy sysfs) and takes them out of placement until an operator SR-IOV-cycles the parent GPU.The guest agent watches
/dev/kmsgon NVIDIA guests and emits aHYPEMAN-GPU-INIT-FAILEDmarker. A newVGPUSentinelControllertails instanceapp.logfor that marker, persists quarantines ingpu/vf-health.json(fail-closed on a corrupt store), and pauses auto-conviction if more than 3 hits land in 15 minutes.Placement skips quarantined VFs, demotes their parent GPU to overflow-only, randomizes VF pick within a card (so one undetected wedge is not every first create), and excludes quarantined VFs from advertised availability. GPU instance start now fails if the previous boot log cannot be archived, so a stale marker cannot convict a new VF. Recovery remains a documented DCGM-quiesce + SR-IOV cycle + clear-file + restart; there is no operator API yet.
Reviewed by Cursor Bugbot for commit 9a90223. Bugbot is set up for automated code reviews on this repo. Configure here.