Skip to content

Commit 78801e7

Browse files
committed
Report vendor VFIO availability per parent GPU and thread instance ownership through releases
1 parent a7548e5 commit 78801e7

5 files changed

Lines changed: 33 additions & 3 deletions

File tree

lib/devices/vendor_vfio_linux.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,13 @@ func (s vendorVFIOSysfs) discoverVFs() ([]VirtualFunction, error) {
8181
return vfs, nil
8282
}
8383

84+
// listProfiles aggregates creatable profiles per parent GPU. Free VFs on the
85+
// same GPU share its framebuffer, so counting each advertising VF overreports
86+
// availability. The driver only guarantees that a GPU still advertising a
87+
// type can fit one more instance of it, so report that per-GPU lower bound.
8488
func (s vendorVFIOSysfs) listProfiles(vfs []VirtualFunction) ([]GPUProfile, error) {
8589
profilesByType := make(map[string]profileMetadata)
86-
availability := make(map[string]int)
90+
creatableGPUs := make(map[string]map[string]struct{})
8791
for _, vf := range vfs {
8892
creatable, err := s.readCreatableProfiles(vf.PCIAddress)
8993
if err != nil {
@@ -92,7 +96,14 @@ func (s vendorVFIOSysfs) listProfiles(vfs []VirtualFunction) ([]GPUProfile, erro
9296
for _, profile := range creatable {
9397
profilesByType[profile.TypeName] = profile
9498
if !vf.Allocated {
95-
availability[profile.TypeName]++
99+
gpu := vf.ParentGPU
100+
if gpu == "" {
101+
gpu = vf.PCIAddress
102+
}
103+
if creatableGPUs[profile.TypeName] == nil {
104+
creatableGPUs[profile.TypeName] = make(map[string]struct{})
105+
}
106+
creatableGPUs[profile.TypeName][gpu] = struct{}{}
96107
}
97108
}
98109
}
@@ -108,7 +119,7 @@ func (s vendorVFIOSysfs) listProfiles(vfs []VirtualFunction) ([]GPUProfile, erro
108119
profiles = append(profiles, GPUProfile{
109120
Name: profile.Name,
110121
FramebufferMB: profile.FramebufferMB,
111-
Available: availability[profile.TypeName],
122+
Available: len(creatableGPUs[profile.TypeName]),
112123
})
113124
}
114125
return profiles, nil

lib/devices/vendor_vfio_linux_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,22 @@ func TestVendorVFIODestroyRetainsAssignmentWhenOneVFIOPathIsMissing(t *testing.T
184184
}
185185
}
186186

187+
func TestVendorVFIOListProfilesCountsPerGPUNotPerVF(t *testing.T) {
188+
t.Parallel()
189+
190+
sysfs := newTestVendorVFIOSysfs(t)
191+
sysfs.addVF(t, "0000:82:00.0", "0000:82:00.4", "42", "0", testCreatableTypes)
192+
sysfs.addVF(t, "0000:82:00.0", "0000:82:00.5", "43", "0", testCreatableTypes)
193+
sysfs.addVF(t, "0000:e3:00.0", "0000:e3:00.4", "44", "0", testCreatableTypes)
194+
195+
vfs, err := sysfs.discoverVFs()
196+
require.NoError(t, err)
197+
profiles, err := sysfs.listProfiles(vfs)
198+
require.NoError(t, err)
199+
assert.Equal(t, 2, profileAvailability(profiles, "NVIDIA L40S-48Q"),
200+
"free VFs share their parent GPU's capacity, so availability is per GPU")
201+
}
202+
187203
func TestVendorVFIOCreateReportsCapacityWhenAllGPUsFull(t *testing.T) {
188204
t.Parallel()
189205

lib/instances/create.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ func (m *manager) createInstance(
302302
Framework: gpuDevice.Framework,
303303
DevicePath: gpuDevice.SysfsPath,
304304
MdevUUID: gpuDevice.MdevUUID,
305+
InstanceID: id,
305306
}
306307
if err := devices.DestroyVGPU(ctx, assignment); err != nil {
307308
log.WarnContext(ctx, "failed to destroy vGPU on cleanup", "instance_id", id, "error", err)

lib/instances/start.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ func (m *manager) startInstance(
174174
Framework: device.Framework,
175175
DevicePath: device.SysfsPath,
176176
MdevUUID: device.MdevUUID,
177+
InstanceID: id,
177178
}
178179
if err := devices.DestroyVGPU(ctx, assignment); err != nil {
179180
log.WarnContext(ctx, "failed to destroy vGPU on cleanup", "instance_id", id, "error", err)

lib/instances/vgpu.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func releaseStoredVGPU(ctx context.Context, stored *StoredMetadata) error {
2727
Framework: stored.GPUFramework,
2828
DevicePath: path,
2929
MdevUUID: stored.GPUMdevUUID,
30+
InstanceID: stored.Id,
3031
}
3132
if err := devices.DestroyVGPU(ctx, assignment); err != nil {
3233
return err

0 commit comments

Comments
 (0)