Integrate vendor VFIO vGPUs into the instance lifecycle - #321
Merged
yummybomb merged 85 commits intoSep 2, 2026
Conversation
yummybomb
force-pushed
the
hypeship/vendor-vfio-vgpu
branch
from
July 28, 2026 21:32
199b1d1 to
a93d009
Compare
yummybomb
force-pushed
the
hypeship/vendor-vfio-vgpu
branch
4 times, most recently
from
July 29, 2026 15:15
d893fce to
de4742a
Compare
yummybomb
force-pushed
the
hypeship/vendor-vfio-vgpu
branch
from
July 29, 2026 16:09
de4742a to
18e047f
Compare
Contributor
Author
|
Trimmed over-engineering after an architectural review against the parent task (host kernel 6.8 / Ubuntu 24.04 support). Most of the removed weight came from earlier review-round additions rather than the original design: |
yummybomb
marked this pull request as ready for review
August 5, 2026 19:47
yummybomb
force-pushed
the
hypeship/vendor-vfio-vgpu
branch
from
August 5, 2026 19:57
7ef1f8d to
bf21162
Compare
yummybomb
force-pushed
the
hypeship/vendor-vfio-vgpu
branch
from
August 5, 2026 20:24
bf21162 to
83c53ea
Compare
yummybomb
force-pushed
the
hypeship/vendor-vfio-vgpu
branch
from
August 5, 2026 20:39
83c53ea to
79eef07
Compare
yummybomb
force-pushed
the
hypeship/vendor-vfio-vgpu
branch
from
August 6, 2026 17:08
ab2b0e8 to
19b9602
Compare
yummybomb
force-pushed
the
hypeship/vendor-vfio-vgpu
branch
from
August 6, 2026 19:06
d92201d to
f177335
Compare
yummybomb
changed the base branch from
hypeship/generalize-vgpu-device
to
hypeship/vendor-vfio-backend
August 6, 2026 19:08
yummybomb
force-pushed
the
hypeship/vendor-vfio-vgpu
branch
from
August 6, 2026 19:26
f177335 to
1d875f2
Compare
yummybomb
force-pushed
the
hypeship/vendor-vfio-vgpu
branch
from
August 6, 2026 19:40
1d875f2 to
23fb2f5
Compare
- Retry the vendor VFIO reconcile sweep with a bounded delay when the startup instance listing fails, instead of disabling orphan recovery until the next process restart. One pending retry at a time. - Schedule the in-process orphaned-release retry when a rollback's retention record cannot be saved (create and start), instead of leaking the VF until restart. The retry scans claims without a self-exclusion because a restarted instance may hold the same VF. - Reject snapshot restore into a vGPU retention stub, matching start, fork, and snapshot. - Give passthrough PCI instances the same SIGTERM grace as vGPU instances on stop/delete, matching the QEMU-side vfioTermGraceFor. - Render the vgpu_cleanup_pending API detail from the error itself instead of duplicating its prose; use the manager clock in the claim scan; collapse the create-rollback retention branch. - Move ReconcileVGPUs off the Manager interface to a startup type assertion and unexport listInstancesForReconcile and hypervisorMayBeAlive.
Record the owning instance and assignment time for each vendor VFIO VF so a reconcile sweep can run while instances are being created: recently assigned VFs get a grace period before they are eligible (mirroring orphanedMdevGracePeriod), and owned VFs are destroyed with their recorded owner ID instead of failing the ownership check.
Run the fail-closed vGPU reconcile once at startup and every minute after, skipping hosts without a vGPU framework. Each pass retries releases for assignments whose owner is no longer live (re-verified under the instance lock) and then sweeps device-level leftovers with no live metadata claim. This deletes the per-path orphan retry goroutines - whose path-keyed dedup could drop cleanup for a newer assignment reusing the same VF - the CAS/timer retry in ReconcileVGPUs, the stopped-instance release special case in StopInstance, the retention fallbacks that scheduled background retries, and the orphan-abandoned metric.
An assignment could lose its persisted hypervisor PID while its VM stays alive - a post-boot metadata save failure or a hypeman crash before the save. The liveness checks gated the socket-ownership scan on a non-nil PID, so once the startup grace expired the reconciler considered such an assignment stale and could remove an mdev out from under the live VM (DestroyMdev has no in-use guard). Run the socket-ownership scan unconditionally: a live VMM always holds its control-socket listener, and a missing listener still resolves to not-alive, so genuinely stopped instances are released as before. The claim scan in releaseStoredVGPUExcluding gets the same treatment.
The five-minute fresh-assignment protection existed three times: the instances startup grace, the mdev orphan grace, and the vendor VFIO sweep grace. Define it once in lib/devices and alias the instances constant to it.
A wedged or leaked VF presents as reduced GPU capacity while /resources still reports full capacity, and reconcile, stale-release, and retention failures were visible only as log lines. Count failed reconcile stages, failed stale releases, and retained assignments (by operation and whether the retention record persisted) so sustained failure can alert.
When rollback release fails and the subsequent retention save also fails, the assignment save from earlier in start may still hold the claim on disk. Check for that surviving claim before reporting the retention as unpersisted, so the API does not emit vgpu_unretained_instance for an assignment that is still durably attributed.
A dirty VF's leftover type consumes framebuffer, which can remove the requested profile from every creatable_vgpu_types list before the selector's repair path can resolve it. When selection fails, reset allocated VFs that no instance claims (in-use-gated, under the allocation lock) and retry once. Also move the claim-path tests behind a linux build tag: they depend on GetDeviceSysfsPath, which returns an empty string on darwin.
Selection treats an unclaimed allocated VF as repairable, but configure no-ops when the leftover type already matches the requested profile, skipping the open-VFIO-handle check and the reset. A claim removed after a failed reset could then hand the VF's stale device instance to a new VMM while the previous holder still had it open. Reset the selected VF at claim time when it is dirty, regardless of type, under the allocation lock and gated on the in-use check inside destroy. A refused reset fails the allocation without leaving a claim.
- Fall back to mdev when framework changes between unlocked and locked discovery in claimVGPU, instead of returning a hard error (TOCTOU) - Scope SIGTERM-before-SIGKILL grace to vendor VFIO framework only, not all instances with a GPU profile (mdev does not need it) - Log a warning when StartVGPUReconciler type assertion fails silently - Remove dead setStoredVGPUDevice call for vendor VFIO in createInstance - Extract vgpuCleanupGuard to deduplicate liveness + claim checks shared between cleanupCreateVGPU and cleanupStartVGPU - Mention dirty VF repair in the zero-creatable-profiles error message Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three changes from the code review of the vendor VFIO vGPU lifecycle: 1. Capture VFs from the pre-lock discovery call and only refresh VFs (not re-check framework) under the allocation lock. The framework cannot change between the two calls, so the second check and the fallback to createVGPUDevice were dead code. 2. Replace the linear VF scan in the dirty-VF repair path with a direct vfByAddress lookup — the code was scanning for a single known address. 3. Add a lock-ordering comment to cleanupStartVGPU documenting that the caller holds the instance lock before this function acquires vgpuAllocationMu. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Within a GPU the allocator now selects clean VFs before dirty ones, and a dirty VF whose reset is refused is dropped from the candidates instead of failing the claim. Log at error level when a failed create retains its instance data because the vGPU claim could not be released, apply the SIGTERM grace on the same vGPU predicate in the instance kill paths as in the QEMU layer, and cover the unknown-load GPU ordering.
sjmiller609
approved these changes
Sep 1, 2026
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit fb132cd. Configure here.
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
Top layer of the vendor VFIO vGPU stack (
generalize-vgpu-device#322 ←hypervisor-liveness#363 ←vendor-vfio-backend#364 ← this). The backend itself is in #364; this layer wires it into the instance lifecycle using claim-first allocation:GPUDevicePathin instance metadata is the authoritative VF claim, persisted before any hardware is touched.ConfigureVGPUthen no-ops when the VF already has the requested type and keeps a reset-and-recreate backstop for a type mismatch. When the leftover type consumes enough framebuffer that the requested profile disappears from every creatable list, the allocator resets unclaimed dirty VFs and retries selection once. This replaces the periodic vendor VFIO device sweep.GPUAssignedAt,GPURetainedForCleanup, delete-only retention records,vgpu_cleanup_pendingerrors, the assignment grace period, the in-memory owners map, and the live-claim release guard.gpu.device_path, the assignment identity on vendor VFIO hosts wheremdev_uuidis empty.The key invariant: cleanup never resets a VF after removing its claim, and all recovery routes through the allocator, which rechecks current metadata and VFIO liveness.
Testing
go build ./...,go vet ./...cleango test ./lib/devices/and thelib/instancesvGPU/reconcile suites pass;go test -racepasses for the new concurrency and crash-recovery tests (concurrent claims select distinct VFs; a crash between claim and configure is reconciled at startup; dirty-VF repair with and without open VFIO handles, including a dirty VF that suppresses the profile from all creatable lists; release order under failed resets; clean-first VF selection with fallback when a dirty VF refuses reset; GPU ordering with unknown load). Claim-path tests are linux-tagged since they depend on sysfs paths; cleanup/release/selector tests remain cross-platformlib/instances/cmd/api/apisuites have pre-existing environment failures (image pulls, network privileges) that reproduce identically on the unmodified baseNote
High Risk
Changes GPU allocation, release ordering, and hypervisor kill semantics on production hosts; incorrect liveness or claim handling could leak VFs or wedge hardware.
Overview
Vendor VFIO vGPUs are wired into create/start/stop/delete using metadata-first VF claims: the allocator persists
GPUDevicePathunder a global lock, then configures the VF (mdev creation stays on the existing path). Least-loaded GPU selection, clean-VF preference, dirty-VF repair at claim time, and removal of the in-memory owner map and periodic vendor VFIO device sweep move recovery into allocation and reconcile.Reconciliation replaces startup-only mdev cleanup with
StartVGPUReconciler(initial pass + ~1 minute): stale metadata claims are released when the VMM is confirmed dead; mdev sweeps skip UUIDs owned by running instances. New metrics cover reconcile and stale-release failures.VF safety: QEMU and instance teardown SIGTERM before SIGKILL when VFIO/vGPU is attached (
VFIOTermGrace), with docs on SIGKILL-during-init wedge risk. Instance API responses addgpu.device_pathwhen set; integration tests allow vendor VFIO hosts.Reviewed by Cursor Bugbot for commit fb132cd. Bugbot is set up for automated code reviews on this repo. Configure here.