render / rpms / libvirt

Forked from rpms/libvirt 11 months ago
Clone
ab145e
From 9e97e35031572e0f6ace32e2fb094f0f358f0391 Mon Sep 17 00:00:00 2001
ab145e
Message-Id: <9e97e35031572e0f6ace32e2fb094f0f358f0391@dist-git>
ab145e
From: Thomas Huth <thuth@redhat.com>
ab145e
Date: Tue, 11 May 2021 14:10:28 +0200
ab145e
Subject: [PATCH] hostdev: mdev: Lookup mdevs by sysfs path rather than mdev
ab145e
 struct
ab145e
MIME-Version: 1.0
ab145e
Content-Type: text/plain; charset=UTF-8
ab145e
Content-Transfer-Encoding: 8bit
ab145e
ab145e
The lookup didn't do anything apart from comparing the sysfs paths
ab145e
anyway since that's what makes each mdev unique.
ab145e
The most ridiculous usage of the old logic was in
ab145e
virHostdevReAttachMediatedDevices where in order to drop an mdev
ab145e
hostdev from the list of active devices we first had to create a new
ab145e
mdev and use it in the lookup call. Why couldn't we have used the
ab145e
hostdev directly? Because the hostdev and mdev structures are
ab145e
incompatible.
ab145e
ab145e
The way mdevs are currently removed is via a write to a specific sysfs
ab145e
attribute. If you do it while the machine which has the mdev assigned
ab145e
is running, the write call may block (with a new enough kernel, with
ab145e
older kernels it would return a write error!) until the device
ab145e
is no longer in use which is when the QEMU process exits.
ab145e
ab145e
The interesting part here comes afterwards when we're cleaning up and
ab145e
call virHostdevReAttachMediatedDevices. The domain doesn't exist
ab145e
anymore, so the list of active hostdevs needs to be updated and the
ab145e
respective hostdevs removed from the list, but remember we had to
ab145e
create an mdev object in the memory in order to find it in the list
ab145e
first which will fail because the write to sysfs had already removed
ab145e
the mdev instance from the host system.
ab145e
And so the next time you try to start the same domain you'll get:
ab145e
ab145e
"Requested operation is not valid: mediated device <path> is in use by
ab145e
driver QEMU, domain <name>"
ab145e
ab145e
Fixes: https://gitlab.com/libvirt/libvirt/-/issues/119
ab145e
ab145e
Signed-off-by: Erik Skultety <eskultet@redhat.com>
ab145e
Reviewed-by: Ján Tomko <jtomko@redhat.com>
ab145e
(cherry picked from commit 49cb59778a4e6c2d04bb9383a9d97fbbc83f9fce)
ab145e
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1940449
ab145e
Signed-off-by: Thomas Huth <thuth@redhat.com>
ab145e
Message-Id: <20210511121028.304070-3-thuth@redhat.com>
ab145e
Reviewed-by: Erik Skultety <eskultet@redhat.com>
ab145e
---
ab145e
 src/util/virhostdev.c | 10 ++++------
ab145e
 src/util/virmdev.c    | 16 ++++++++--------
ab145e
 src/util/virmdev.h    |  4 ++--
ab145e
 3 files changed, 14 insertions(+), 16 deletions(-)
ab145e
ab145e
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
ab145e
index b7050e99e4..392e94307c 100644
ab145e
--- a/src/util/virhostdev.c
ab145e
+++ b/src/util/virhostdev.c
ab145e
@@ -2025,7 +2025,7 @@ virHostdevReAttachMediatedDevices(virHostdevManagerPtr mgr,
ab145e
 
ab145e
     virObjectLock(mgr->activeMediatedHostdevs);
ab145e
     for (i = 0; i < nhostdevs; i++) {
ab145e
-        g_autoptr(virMediatedDevice) mdev = NULL;
ab145e
+        g_autofree char *sysfspath = NULL;
ab145e
         virMediatedDevicePtr tmp;
ab145e
         virDomainHostdevSubsysMediatedDevPtr mdevsrc;
ab145e
         virDomainHostdevDefPtr hostdev = hostdevs[i];
ab145e
@@ -2034,14 +2034,12 @@ virHostdevReAttachMediatedDevices(virHostdevManagerPtr mgr,
ab145e
             continue;
ab145e
 
ab145e
         mdevsrc = &hostdev->source.subsys.u.mdev;
ab145e
-
ab145e
-        if (!(mdev = virMediatedDeviceNew(mdevsrc->uuidstr,
ab145e
-                                          mdevsrc->model)))
ab145e
-            continue;
ab145e
+        sysfspath = virMediatedDeviceGetSysfsPath(mdevsrc->uuidstr);
ab145e
 
ab145e
         /* Remove from the list only mdevs assigned to @drv_name/@dom_name */
ab145e
 
ab145e
-        tmp = virMediatedDeviceListFind(mgr->activeMediatedHostdevs, mdev);
ab145e
+        tmp = virMediatedDeviceListFind(mgr->activeMediatedHostdevs,
ab145e
+                                        sysfspath);
ab145e
 
ab145e
         /* skip inactive devices */
ab145e
         if (!tmp)
ab145e
diff --git a/src/util/virmdev.c b/src/util/virmdev.c
ab145e
index c2499c0a20..bae4a7d2c1 100644
ab145e
--- a/src/util/virmdev.c
ab145e
+++ b/src/util/virmdev.c
ab145e
@@ -312,7 +312,7 @@ int
ab145e
 virMediatedDeviceListAdd(virMediatedDeviceListPtr list,
ab145e
                          virMediatedDevicePtr *dev)
ab145e
 {
ab145e
-    if (virMediatedDeviceListFind(list, *dev)) {
ab145e
+    if (virMediatedDeviceListFind(list, (*dev)->path)) {
ab145e
         virReportError(VIR_ERR_INTERNAL_ERROR,
ab145e
                        _("device %s is already in use"), (*dev)->path);
ab145e
         return -1;
ab145e
@@ -358,7 +358,7 @@ virMediatedDevicePtr
ab145e
 virMediatedDeviceListSteal(virMediatedDeviceListPtr list,
ab145e
                            virMediatedDevicePtr dev)
ab145e
 {
ab145e
-    int idx = virMediatedDeviceListFindIndex(list, dev);
ab145e
+    int idx = virMediatedDeviceListFindIndex(list, dev->path);
ab145e
 
ab145e
     return virMediatedDeviceListStealIndex(list, idx);
ab145e
 }
ab145e
@@ -374,13 +374,13 @@ virMediatedDeviceListDel(virMediatedDeviceListPtr list,
ab145e
 
ab145e
 int
ab145e
 virMediatedDeviceListFindIndex(virMediatedDeviceListPtr list,
ab145e
-                               virMediatedDevicePtr dev)
ab145e
+                               const char *sysfspath)
ab145e
 {
ab145e
     size_t i;
ab145e
 
ab145e
     for (i = 0; i < list->count; i++) {
ab145e
-        virMediatedDevicePtr other = list->devs[i];
ab145e
-        if (STREQ(other->path, dev->path))
ab145e
+        virMediatedDevicePtr dev = list->devs[i];
ab145e
+        if (STREQ(sysfspath, dev->path))
ab145e
             return i;
ab145e
     }
ab145e
     return -1;
ab145e
@@ -389,11 +389,11 @@ virMediatedDeviceListFindIndex(virMediatedDeviceListPtr list,
ab145e
 
ab145e
 virMediatedDevicePtr
ab145e
 virMediatedDeviceListFind(virMediatedDeviceListPtr list,
ab145e
-                          virMediatedDevicePtr dev)
ab145e
+                          const char *sysfspath)
ab145e
 {
ab145e
     int idx;
ab145e
 
ab145e
-    if ((idx = virMediatedDeviceListFindIndex(list, dev)) >= 0)
ab145e
+    if ((idx = virMediatedDeviceListFindIndex(list, sysfspath)) >= 0)
ab145e
         return list->devs[idx];
ab145e
     else
ab145e
         return NULL;
ab145e
@@ -407,7 +407,7 @@ virMediatedDeviceIsUsed(virMediatedDevicePtr dev,
ab145e
     const char *drvname, *domname;
ab145e
     virMediatedDevicePtr tmp = NULL;
ab145e
 
ab145e
-    if ((tmp = virMediatedDeviceListFind(list, dev))) {
ab145e
+    if ((tmp = virMediatedDeviceListFind(list, dev->path))) {
ab145e
         virMediatedDeviceGetUsedBy(tmp, &drvname, &domname);
ab145e
         virReportError(VIR_ERR_OPERATION_INVALID,
ab145e
                        _("mediated device %s is in use by "
ab145e
diff --git a/src/util/virmdev.h b/src/util/virmdev.h
ab145e
index e0905a3f6e..3022ab9948 100644
ab145e
--- a/src/util/virmdev.h
ab145e
+++ b/src/util/virmdev.h
ab145e
@@ -120,11 +120,11 @@ virMediatedDeviceListDel(virMediatedDeviceListPtr list,
ab145e
 
ab145e
 virMediatedDevicePtr
ab145e
 virMediatedDeviceListFind(virMediatedDeviceListPtr list,
ab145e
-                          virMediatedDevicePtr dev);
ab145e
+                          const char *sysfspath);
ab145e
 
ab145e
 int
ab145e
 virMediatedDeviceListFindIndex(virMediatedDeviceListPtr list,
ab145e
-                               virMediatedDevicePtr dev);
ab145e
+                               const char *sysfspath);
ab145e
 
ab145e
 int
ab145e
 virMediatedDeviceListMarkDevices(virMediatedDeviceListPtr dst,
ab145e
-- 
ab145e
2.31.1
ab145e