summaryrefslogtreecommitdiff
path: root/src/node_device
diff options
context:
space:
mode:
authorJonathon Jongsma <jjongsma@redhat.com>2021-02-02 16:21:21 -0600
committerJonathon Jongsma <jjongsma@redhat.com>2021-04-07 15:24:20 -0500
commitf25b13b6e5927da3b7e0546986a8d3f9a9fefe1b (patch)
tree6aa735618921a79260e233d7a29137167d7709c6 /src/node_device
parent62a73c525ce514bb2dc1c560cb598da19c17611f (diff)
downloadlibvirt-f25b13b6e5927da3b7e0546986a8d3f9a9fefe1b.tar.gz
nodedev: fix hang when destroying an mdev in use
Calling `mdevctl stop` for a mediated device that is in use by an active domain will block until that vm exits (or the vm closes the device). Since the nodedev driver cannot query the hypervisor driver to see whether any active domains are using the device, we resort to a workaround that relies on the fact that a vfio group can only be opened by one user at a time. If we get an EBUSY error when attempting to open the group file, we assume the device is in use and refuse to try to destroy that device. Signed-off-by: Jonathon Jongsma <jjongsma@redhat.com> Reviewed-by: Erik Skultety <eskultet@redhat.com>
Diffstat (limited to 'src/node_device')
-rw-r--r--src/node_device/node_device_driver.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
index 3c79c3aa42..01e189b73a 100644
--- a/src/node_device/node_device_driver.c
+++ b/src/node_device/node_device_driver.c
@@ -1181,8 +1181,27 @@ nodeDeviceDestroy(virNodeDevicePtr device)
ret = 0;
} else if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV)) {
+ /* If this mediated device is in use by a vm, attempting to stop it
+ * will block until the vm closes the device. The nodedev driver
+ * cannot query the hypervisor driver to determine whether the device
+ * is in use by any active domains, since that would introduce circular
+ * dependencies between daemons and add a risk of deadlocks. So we need
+ * to resort to a workaround. vfio only allows the group for a device
+ * to be opened by one user at a time. So if we get EBUSY when opening
+ * the group, we infer that the device is in use and therefore we
+ * shouldn't try to remove the device. */
+ g_autofree char *vfiogroup =
+ virMediatedDeviceGetIOMMUGroupDev(def->caps->data.mdev.uuid);
+ VIR_AUTOCLOSE fd = open(vfiogroup, O_RDONLY);
g_autofree char *errmsg = NULL;
+ if (fd < 0 && errno == EBUSY) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to destroy '%s': device in use"),
+ def->name);
+ goto cleanup;
+ }
+
if (virMdevctlStop(def, &errmsg) < 0) {
if (errmsg)
virReportError(VIR_ERR_INTERNAL_ERROR,