render / rpms / libvirt

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