summaryrefslogtreecommitdiffstats
path: root/kernel/main.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-21 11:30:46 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-09-21 11:30:46 -0400
commit79d86fe350eaa520cda91b3832d30b085d9bcd6f (patch)
treef655089c62cff430c6bc1e34e8c14b4ccab41c0c /kernel/main.c
parentad1f7a6a3cd262cc084673ec5cf0c561328ec7c7 (diff)
downloadopen-iov-79d86fe350eaa520cda91b3832d30b085d9bcd6f.tar.gz
open-iov-79d86fe350eaa520cda91b3832d30b085d9bcd6f.zip
kernel: Add get_available mdev callback (fix leaked available_instances)
The mdev core's shared parent->available_instances counter leaks whenever an mdev remove path fails to complete (as happened during the now-fixed remove crash): creates then fail with -EUSERS while sysfs reports 0 available instances with zero mdevs present. Implement mdev_driver.get_available to compute availability from the driver's own authoritative device list instead of the core counter. Handles the 'nvidia-' prefixed sysfs type names when looking up per-type max_instances (falls back to 1).
Diffstat (limited to 'kernel/main.c')
-rw-r--r--kernel/main.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/kernel/main.c b/kernel/main.c
index 8ba7083..c96357b 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -65,11 +65,43 @@ struct nv_vgpu_type_info g_vgpu_type_infos[16];
int g_num_vgpu_types = 0;
static DEFINE_MUTEX(g_vgpu_type_lock);
+/*
+ * get_available - report available instances for an mdev type.
+ *
+ * The mdev core's shared parent->available_instances counter can drift
+ * (e.g. if a remove path ever fails to complete). Compute availability
+ * from our own authoritative device list instead.
+ */
+static unsigned int nv_vgpu_get_available(struct mdev_type *mtype)
+{
+ struct nv_vgpu_type_info *info;
+ struct nv_vgpu_device *vgpu;
+ const char *name = mtype->sysfs_name;
+ unsigned int active = 0, max = 1;
+
+ /* Type dirs may carry an extra "nvidia-" prefix vs our type names */
+ if (str_has_prefix(name, "nvidia-"))
+ name += strlen("nvidia-");
+ info = nv_vgpu_find_type_info(name);
+ if (info && info->max_instances)
+ max = info->max_instances;
+
+ mutex_lock(&nv_vgpu_driver.lock);
+ list_for_each_entry(vgpu, &nv_vgpu_driver.devices, list) {
+ if (vgpu->mdev && vgpu->mdev->type == mtype)
+ active++;
+ }
+ mutex_unlock(&nv_vgpu_driver.lock);
+
+ return active >= max ? 0 : max - active;
+}
+
struct mdev_driver nv_vgpu_mdev_driver = {
.device_api = VFIO_DEVICE_API_PCI_STRING,
.max_instances = 8,
.probe = nv_vgpu_mdev_create,
.remove = nv_vgpu_mdev_remove,
+ .get_available = nv_vgpu_get_available,
.driver = {
.name = "nvidia-vgpu-vfio-mdev",
},