Skip to content

Commit d92201d

Browse files
committed
Remove verbose vGPU comments
1 parent e61e5a3 commit d92201d

14 files changed

Lines changed: 8 additions & 117 deletions

File tree

cmd/api/main.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,6 @@ func configureUFFDGraduationController(cfg *config.Config, instanceManager insta
159159
}, logger), nil
160160
}
161161

162-
// liveInstanceVGPUDevicePaths returns the stored vGPU device paths of
163-
// instances whose hypervisor process is still alive. Vendor VFIO
164-
// reconciliation skips these VFs so it cannot clear an assignment out from
165-
// under a VM that survived a hypeman restart but has not opened the VFIO
166-
// device yet.
167162
func liveInstanceVGPUDevicePaths(ctx context.Context, instanceManager instances.Manager) (map[string]struct{}, error) {
168163
allInstances, err := instanceManager.ListInstancesForReconcile(ctx)
169164
if err != nil {
@@ -372,17 +367,13 @@ func run() error {
372367
return fmt.Errorf("reconcile device state: %w", err)
373368
}
374369

375-
// Reconcile vGPU devices (clears orphaned vGPUs from previous runs)
376370
logger.Info("Reconciling vGPU devices...")
377371
protected, err := liveInstanceVGPUDevicePaths(app.Ctx, app.InstanceManager)
378372
if err != nil {
379-
// Without the instance inventory we cannot tell live vendor VFIO
380-
// assignments from orphans, so skip that framework's reconciliation.
381373
logger.Warn("failed to list instances for vGPU reconcile protection; skipping vendor VFIO reconciliation", "error", err)
382374
protected = nil
383375
}
384376
if err := devices.ReconcileVGPUs(app.Ctx, protected); err != nil {
385-
// Log but don't fail - vGPU cleanup is best-effort
386377
logger.Warn("failed to reconcile vGPU devices", "error", err)
387378
}
388379

integration/vgpu_test.go

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,7 @@ import (
2323
"github.com/stretchr/testify/require"
2424
)
2525

26-
// TestVGPU is an integration test that verifies vGPU (SR-IOV) support works
27-
// on the host's framework: mdev or NVIDIA's vendor-specific VFIO.
28-
//
29-
// This test automatically detects vGPU availability and skips if:
30-
// - No vGPU framework (mdev or vendor VFIO) is discovered
31-
// - No vGPU profiles are available
32-
// - Not running as root (required for sysfs vGPU assignment)
33-
// - KVM is not available
34-
//
35-
// To run manually:
36-
//
37-
// sudo go test -v -run TestVGPU -timeout 5m ./integration/...
38-
//
39-
// Note: This test verifies vGPU assignment, release on stop, reacquisition on
40-
// start, and PCI device visibility inside the VM.
41-
// It does NOT test nvidia-smi or CUDA functionality since that requires NVIDIA
42-
// guest drivers pre-installed in the image.
26+
// TestVGPU verifies vGPU support through mdev or vendor VFIO.
4327
func TestVGPU(t *testing.T) {
4428
t.Parallel()
4529
if testing.Short() {
@@ -163,7 +147,6 @@ func TestVGPU(t *testing.T) {
163147
instanceID = inst.Id
164148
t.Logf("Instance created: %s", inst.Id)
165149

166-
// Verify the assignment matches the host's framework
167150
require.NotEmpty(t, inst.GPUDevicePath, "Instance should have a vGPU device path assigned")
168151
switch inst.GPUFramework {
169152
case devices.VGPUFrameworkMdev:
@@ -193,7 +176,6 @@ func TestVGPU(t *testing.T) {
193176
assert.Less(t, availableAfter, availableBefore, "available instances should decrease after creating VM")
194177
})
195178

196-
// Step 6: Verify the assignment exists in sysfs
197179
t.Run("VGPUAssignedInSysfs", func(t *testing.T) {
198180
assertVGPUAssigned(t, inst.GPUFramework, inst.GPUDevicePath)
199181
})
@@ -243,7 +225,6 @@ func TestVGPU(t *testing.T) {
243225
t.Logf("Instance GPU: profile=%s, framework=%s, device=%s", actualInst.GPUProfile, actualInst.GPUFramework, actualInst.GPUDevicePath)
244226
})
245227

246-
// Step 10: Stop releases the assignment
247228
t.Log("Step 10: Stopping instance to release the vGPU...")
248229
_, err = instanceManager.StopInstance(ctx, inst.Id)
249230
require.NoError(t, err, "stop should succeed")
@@ -255,7 +236,6 @@ func TestVGPU(t *testing.T) {
255236
assertVGPUReleased(t, inst.GPUFramework, inst.GPUDevicePath)
256237
})
257238

258-
// Step 11: Start reacquires an assignment
259239
t.Log("Step 11: Starting instance to reacquire a vGPU...")
260240
started, err := instanceManager.StartInstance(ctx, inst.Id, instances.StartInstanceRequest{})
261241
require.NoError(t, err, "start should succeed")
@@ -269,8 +249,6 @@ func TestVGPU(t *testing.T) {
269249
t.Log("✅ vGPU test PASSED!")
270250
}
271251

272-
// assertVGPUAssigned verifies in sysfs that the device at path carries a live
273-
// vGPU assignment for the given framework.
274252
func assertVGPUAssigned(t *testing.T, framework devices.VGPUFramework, devicePath string) {
275253
t.Helper()
276254
switch framework {
@@ -286,8 +264,6 @@ func assertVGPUAssigned(t *testing.T, framework devices.VGPUFramework, devicePat
286264
}
287265
}
288266

289-
// assertVGPUReleased verifies in sysfs that the device at path no longer
290-
// carries a vGPU assignment.
291267
func assertVGPUReleased(t *testing.T, framework devices.VGPUFramework, devicePath string) {
292268
t.Helper()
293269
switch framework {
@@ -316,7 +292,6 @@ func checkVGPUTestPrerequisites() (string, string) {
316292
return "vGPU test requires root (sudo) for mdev creation", ""
317293
}
318294

319-
// Check for a vGPU framework (SR-IOV VFs present)
320295
framework, _, err := devices.DiscoverVGPU()
321296
if err != nil {
322297
return "vGPU test failed to discover vGPU framework: " + err.Error(), ""

lib/devices/mdev_linux.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,6 @@ func getCachedProfiles(firstVF string) []profileMetadata {
8989
return cachedProfiles
9090
}
9191

92-
// discoverMdevVFs returns all SR-IOV Virtual Functions available for mdev vGPU.
93-
// These are discovered by scanning /sys/class/mdev_bus/ which contains
94-
// VFs that can host mdev devices.
9592
func discoverMdevVFs() ([]VirtualFunction, error) {
9693
entries, err := os.ReadDir(mdevBusPath)
9794
if err != nil {
@@ -133,8 +130,6 @@ func discoverMdevVFs() ([]VirtualFunction, error) {
133130
return vfs, nil
134131
}
135132

136-
// listMdevGPUProfilesWithVFs returns available vGPU profiles with availability
137-
// counts, discovered from the first VF's mdev_supported_types directory.
138133
func listMdevGPUProfilesWithVFs(vfs []VirtualFunction) ([]GPUProfile, error) {
139134
if len(vfs) == 0 {
140135
return nil, nil

lib/devices/types.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const (
6969

7070
// GPUModePassthrough indicates whole GPU VFIO passthrough
7171
GPUModePassthrough GPUMode = "passthrough"
72-
// GPUModeVGPU indicates an mdev or vendor VFIO vGPU host
72+
// GPUModeVGPU indicates vGPU mode
7373
GPUModeVGPU GPUMode = "vgpu"
7474
// GPUModeNone indicates no GPU available
7575
GPUModeNone GPUMode = "none"
@@ -88,8 +88,6 @@ type VGPUAssignment struct {
8888
Framework VGPUFramework
8989
DevicePath string
9090
MdevUUID string
91-
// InstanceID guards vendor VFIO releases: a release is skipped when the
92-
// VF's in-process owner is a different instance.
9391
InstanceID string
9492
}
9593

lib/devices/vendor_vfio_linux.go

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ type vendorVFIOSysfs struct {
2525
pciDevicesPath string
2626
procPath string
2727
vfioDevicesPath string
28-
owners map[string]string // assignments created by this process
28+
owners map[string]string
2929
}
3030

3131
var (
@@ -135,15 +135,9 @@ func (s vendorVFIOSysfs) create(ctx context.Context, profileName, instanceID str
135135
}
136136
}
137137
if !found {
138-
// A VF with an assigned vGPU reports nothing creatable, and a VF on a
139-
// framebuffer-exhausted GPU reports only the header, so a host at full
140-
// capacity has an empty catalog. Report that as capacity, not config.
141138
if len(metadata) == 0 && len(vfs) > 0 {
142139
return nil, fmt.Errorf("no creatable vGPU profiles on any VF, GPUs may be at capacity: profile %q", profileName)
143140
}
144-
// The creatable catalog is capacity-dependent: a valid larger profile
145-
// disappears once no GPU can fit it while smaller ones remain, so an
146-
// absent profile is indistinguishable from an unknown one.
147141
return nil, fmt.Errorf("profile %q is not creatable on any VF (unknown profile or insufficient capacity)", profileName)
148142
}
149143

@@ -184,17 +178,10 @@ func (s vendorVFIOSysfs) create(ctx context.Context, profileName, instanceID str
184178
}, nil
185179
}
186180

187-
// destroy releases the vGPU assignment on vfAddress. In-process ownership
188-
// prevents stale instance metadata from releasing a VF before its new QEMU
189-
// process opens the device. Open VFIO handles protect assignments recovered
190-
// after a hypeman restart.
191181
func (s vendorVFIOSysfs) destroy(ctx context.Context, vfAddress, instanceID string) error {
192182
return s.destroyWithOpenPaths(ctx, vfAddress, instanceID, nil)
193183
}
194184

195-
// destroyWithOpenPaths is destroy with an optional pre-scanned set of open
196-
// VFIO handles, so reconcile can share one /proc scan across all releases.
197-
// A nil openPaths triggers a fresh scan.
198185
func (s vendorVFIOSysfs) destroyWithOpenPaths(ctx context.Context, vfAddress, instanceID string, openPaths map[string]struct{}) error {
199186
vendorVFIOMu.Lock()
200187
defer vendorVFIOMu.Unlock()
@@ -268,9 +255,6 @@ func (s vendorVFIOSysfs) reconcile(ctx context.Context, protectedDevicePaths map
268255
return fmt.Errorf("scan open VFIO handles: %w", err)
269256
}
270257
}
271-
// destroyWithOpenPaths repeats this probe under the lock; the
272-
// pre-check only keeps live VMs from being logged below as failed
273-
// destroys.
274258
inUse, err := s.vfioDeviceInUse(vf.PCIAddress, openPaths)
275259
if err != nil {
276260
log.WarnContext(ctx, "failed to check vendor VFIO vGPU usage", "vf", vf.PCIAddress, "error", err)
@@ -287,9 +271,6 @@ func (s vendorVFIOSysfs) reconcile(ctx context.Context, protectedDevicePaths map
287271
}
288272

289273
func (s vendorVFIOSysfs) selectLeastLoadedVF(vfs []VirtualFunction, metadata []profileMetadata, profileType string) (string, error) {
290-
// metadata only covers currently creatable types, so an allocated type no
291-
// longer creatable anywhere weighs 0 and its GPU can look less loaded than
292-
// it is. The driver's creatable lists still bound placement correctness.
293274
framebufferByType := make(map[string]int, len(metadata))
294275
for _, profile := range metadata {
295276
framebufferByType[profile.TypeName] = profile.FramebufferMB
@@ -374,8 +355,6 @@ func (s vendorVFIOSysfs) vfioDeviceInUse(vfAddress string, openPaths map[string]
374355
}
375356
}
376357

377-
// QEMU holds the legacy /dev/vfio/<group> node unless iommufd is
378-
// configured, so check the VF's iommu group alongside the iommufd cdevs.
379358
target, err := os.Readlink(filepath.Join(s.pciDevicesPath, vfAddress, "iommu_group"))
380359
if os.IsNotExist(err) {
381360
return false, nil
@@ -397,8 +376,6 @@ func (s vendorVFIOSysfs) vfioDeviceInUse(vfAddress string, openPaths map[string]
397376
return false, nil
398377
}
399378

400-
// openVFIOPaths returns every path under the VFIO device root that any
401-
// process holds open, from a single /proc scan shared by all VF checks.
402379
func (s vendorVFIOSysfs) openVFIOPaths() (map[string]struct{}, error) {
403380
processes, err := os.ReadDir(s.procPath)
404381
if err != nil {
@@ -434,11 +411,6 @@ func (s vendorVFIOSysfs) openVFIOPaths() (map[string]struct{}, error) {
434411
return open, nil
435412
}
436413

437-
// parseCreatableVGPUTypes reads the table the NVIDIA driver emits, with a
438-
// header row and the type ID first:
439-
//
440-
// ID : vGPU Name
441-
// 1147 : NVIDIA L40S-1Q
442414
func parseCreatableVGPUTypes(value string) ([]profileMetadata, error) {
443415
profiles := make([]profileMetadata, 0)
444416
for lineNumber, line := range strings.Split(value, "\n") {

lib/devices/vendor_vfio_linux_test.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,6 @@ func TestVendorVFIODestroyReleasesUnboundVF(t *testing.T) {
124124
}
125125
}
126126

127-
// At full capacity every VF reports an empty or header-only creatable list,
128-
// so the catalog is empty and create must report capacity, not a bad profile.
129127
func TestVendorVFIOCreateReportsCapacityWhenAllGPUsFull(t *testing.T) {
130128
t.Parallel()
131129

@@ -145,8 +143,6 @@ func TestVendorVFIOCreateReportsCapacityWhenAllGPUsFull(t *testing.T) {
145143
assert.ErrorContains(t, err, "GPUs may be at capacity")
146144
}
147145

148-
// A partially loaded host drops larger profiles from the creatable lists
149-
// while smaller ones remain, so a missing profile cannot be proven invalid.
150146
func TestVendorVFIOCreateReportsAmbiguousMissingProfile(t *testing.T) {
151147
t.Parallel()
152148

@@ -284,7 +280,6 @@ func TestVendorVFIOReconcilePreservesVFWhenProcFDLinkScanFails(t *testing.T) {
284280
assertFileValue(t, filepath.Join(sysfs.pciDevicesPath, vfAddress, "nvidia", "current_vgpu_type"), "1148")
285281
}
286282

287-
// A GPU with no framebuffer left prints the header and nothing else.
288283
func TestParseCreatableVGPUTypesHeaderOnly(t *testing.T) {
289284
t.Parallel()
290285

lib/devices/vgpu_linux.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ import (
88
"path/filepath"
99
)
1010

11-
// DiscoverVGPU returns the host's active vGPU framework and its virtual
12-
// functions from a single sysfs scan. Detection is not cached because VFs
13-
// appear only after SR-IOV enablement, which can happen after hypeman starts.
11+
// DiscoverVGPU returns the host's active vGPU framework and virtual functions.
1412
func DiscoverVGPU() (VGPUFramework, []VirtualFunction, error) {
1513
return discoverVGPUWith(discoverMdevVFs, hostVendorVFIO.discoverVFs)
1614
}
@@ -42,8 +40,7 @@ func ListGPUProfiles() ([]GPUProfile, error) {
4240
return ListGPUProfilesWithVFs(framework, vfs)
4341
}
4442

45-
// ListGPUProfilesWithVFs returns available profiles for VFs already
46-
// discovered under the given framework, avoiding a re-scan.
43+
// ListGPUProfilesWithVFs returns available profiles for discovered VFs.
4744
func ListGPUProfilesWithVFs(framework VGPUFramework, vfs []VirtualFunction) ([]GPUProfile, error) {
4845
switch framework {
4946
case VGPUFrameworkMdev:
@@ -83,8 +80,6 @@ func CreateVGPU(ctx context.Context, profileName, instanceID string) (*VGPUDevic
8380

8481
func DestroyVGPU(ctx context.Context, assignment VGPUAssignment) error {
8582
framework := assignment.Framework
86-
// Metadata written before GPUFramework existed carries only the mdev
87-
// UUID, so treat it as an mdev assignment.
8883
if framework == VGPUFrameworkNone && assignment.MdevUUID != "" {
8984
framework = VGPUFrameworkMdev
9085
}
@@ -105,12 +100,7 @@ func DestroyVGPU(ctx context.Context, assignment VGPUAssignment) error {
105100
}
106101
}
107102

108-
// ReconcileVGPUs releases orphaned vGPU assignments. Vendor VFIO VFs whose
109-
// stored device path is in protectedDevicePaths are skipped because a live
110-
// instance holds the assignment, even if no process has opened the VFIO
111-
// device yet (e.g. a VM still booting after a hypeman restart). A nil map
112-
// means the protected paths are unavailable, so vendor VFIO reconciliation
113-
// is skipped; mdev reconciliation does not need them and still runs.
103+
// ReconcileVGPUs releases orphaned vGPU assignments.
114104
func ReconcileVGPUs(ctx context.Context, protectedDevicePaths map[string]struct{}) error {
115105
framework, _, err := DiscoverVGPU()
116106
if err != nil {

lib/instances/delete.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,6 @@ func (m *manager) killHypervisor(ctx context.Context, inst *Instance) error {
225225
break
226226
}
227227
if err != nil {
228-
// After a hypeman restart the hypervisor is not our child, so
229-
// Wait4 returns ECHILD. Wait until it has actually exited.
230228
if killErr := syscall.Kill(pid, 0); killErr == syscall.ESRCH {
231229
log.DebugContext(ctx, "hypervisor process killed", "instance_id", inst.Id, "pid", pid)
232230
break

lib/instances/lifecycle_noop_test.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,6 @@ func TestDeleteRetainsMetadataWhenVGPUReleaseFails(t *testing.T) {
167167
assert.Equal(t, "/sys/bus/pci/devices/0000:82:00.4", stored.GPUDevicePath)
168168
}
169169

170-
// A stale assignment (release succeeded but the save did not) can reference a
171-
// device that has since been reassigned. Releasing it must not touch the
172-
// device out from under the live instance that owns it now; the stale
173-
// metadata is dropped instead, so the delete completes.
174170
func TestDeleteDropsStaleVGPUClaimedByLiveInstance(t *testing.T) {
175171
now := time.Now().UTC()
176172
m, id := newLifecycleNoopManagerWithInstance(t, StateStopped, now)

lib/instances/manager.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,8 +697,7 @@ func (m *manager) UpdateInstance(ctx context.Context, id string, req UpdateInsta
697697
return inst, err
698698
}
699699

700-
// ListInstancesForReconcile returns every instance and fails if any metadata
701-
// file cannot be loaded, so callers never reconcile against a partial inventory.
700+
// ListInstancesForReconcile returns every instance or an invalid metadata error.
702701
func (m *manager) ListInstancesForReconcile(ctx context.Context) ([]Instance, error) {
703702
return m.loadInstances(ctx, false)
704703
}

0 commit comments

Comments
 (0)