|
|
d759b5 |
From 9bf517748d9fed50a0bee163625f119b25fdb0ea Mon Sep 17 00:00:00 2001
|
|
|
d759b5 |
Message-Id: <9bf517748d9fed50a0bee163625f119b25fdb0ea@dist-git>
|
|
|
d759b5 |
From: Laine Stump <laine@redhat.com>
|
|
|
d759b5 |
Date: Thu, 26 Sep 2019 18:05:26 -0400
|
|
|
d759b5 |
Subject: [PATCH] conf: utility function to update entry in def->nets array
|
|
|
d759b5 |
|
|
|
d759b5 |
A virDomainNetDef object in a domain's nets array might contain a
|
|
|
d759b5 |
virDomainHostdevDef, and when this is the case, the domain's hostdevs
|
|
|
d759b5 |
array will also have a pointer to this embedded hostdev (this is done
|
|
|
d759b5 |
so that internal functions that need to perform some operation on all
|
|
|
d759b5 |
hostdevs won't leave out the type='hostdev' network interfaces).
|
|
|
d759b5 |
|
|
|
d759b5 |
When a network device was updated with virDomainUpdateDeviceFlags(),
|
|
|
d759b5 |
we were replacing the entry in the nets array (and free'ing the
|
|
|
d759b5 |
original) but forgetting about the pointer in the hostdevs array
|
|
|
d759b5 |
(which would then point to the now-free'd hostdev contained in the old
|
|
|
d759b5 |
net object.) This often resulted in a libvirtd crash.
|
|
|
d759b5 |
|
|
|
d759b5 |
The solution is to add a function, virDomainNetUpdate(), called by
|
|
|
d759b5 |
qemuDomainUpdateDeviceConfig(), that updates the hostdevs array
|
|
|
d759b5 |
appropriately along with the nets array.
|
|
|
d759b5 |
|
|
|
d759b5 |
Resolves: https://bugzilla.redhat.com/1558934
|
|
|
d759b5 |
|
|
|
d759b5 |
Signed-off-by: Laine Stump <laine@redhat.com>
|
|
|
d759b5 |
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
|
|
|
d759b5 |
(cherry picked from commit 7e490cdad6364c82b326d5d9251826c757e8f77b)
|
|
|
d759b5 |
Message-Id: <20190926220526.12970-1-laine@redhat.com>
|
|
|
d759b5 |
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
d759b5 |
---
|
|
|
d759b5 |
src/conf/domain_conf.c | 41 ++++++++++++++++++++++++++++++++++++++++
|
|
|
d759b5 |
src/conf/domain_conf.h | 1 +
|
|
|
d759b5 |
src/libvirt_private.syms | 1 +
|
|
|
d759b5 |
src/lxc/lxc_driver.c | 6 ++++--
|
|
|
d759b5 |
src/qemu/qemu_driver.c | 6 ++++--
|
|
|
d759b5 |
5 files changed, 51 insertions(+), 4 deletions(-)
|
|
|
d759b5 |
|
|
|
d759b5 |
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
|
|
d759b5 |
index 0352fad245..60f426df04 100644
|
|
|
d759b5 |
--- a/src/conf/domain_conf.c
|
|
|
d759b5 |
+++ b/src/conf/domain_conf.c
|
|
|
d759b5 |
@@ -17119,6 +17119,47 @@ virDomainNetRemove(virDomainDefPtr def, size_t i)
|
|
|
d759b5 |
return net;
|
|
|
d759b5 |
}
|
|
|
d759b5 |
|
|
|
d759b5 |
+
|
|
|
d759b5 |
+int
|
|
|
d759b5 |
+virDomainNetUpdate(virDomainDefPtr def,
|
|
|
d759b5 |
+ size_t netidx,
|
|
|
d759b5 |
+ virDomainNetDefPtr newnet)
|
|
|
d759b5 |
+{
|
|
|
d759b5 |
+ size_t hostdevidx;
|
|
|
d759b5 |
+ virDomainNetDefPtr oldnet = def->nets[netidx];
|
|
|
d759b5 |
+ virDomainHostdevDefPtr oldhostdev = virDomainNetGetActualHostdev(oldnet);
|
|
|
d759b5 |
+ virDomainHostdevDefPtr newhostdev = virDomainNetGetActualHostdev(newnet);
|
|
|
d759b5 |
+
|
|
|
d759b5 |
+ /*
|
|
|
d759b5 |
+ * if newnet or oldnet has a valid hostdev*, we need to update the
|
|
|
d759b5 |
+ * hostdevs list
|
|
|
d759b5 |
+ */
|
|
|
d759b5 |
+ if (oldhostdev) {
|
|
|
d759b5 |
+ for (hostdevidx = 0; hostdevidx < def->nhostdevs; hostdevidx++) {
|
|
|
d759b5 |
+ if (def->hostdevs[hostdevidx] == oldhostdev)
|
|
|
d759b5 |
+ break;
|
|
|
d759b5 |
+ }
|
|
|
d759b5 |
+ }
|
|
|
d759b5 |
+
|
|
|
d759b5 |
+ if (oldhostdev && hostdevidx < def->nhostdevs) {
|
|
|
d759b5 |
+ if (newhostdev) {
|
|
|
d759b5 |
+ /* update existing entry in def->hostdevs */
|
|
|
d759b5 |
+ def->hostdevs[hostdevidx] = newhostdev;
|
|
|
d759b5 |
+ } else {
|
|
|
d759b5 |
+ /* delete oldhostdev from def->hostdevs */
|
|
|
d759b5 |
+ virDomainHostdevRemove(def, hostdevidx);
|
|
|
d759b5 |
+ }
|
|
|
d759b5 |
+ } else if (newhostdev) {
|
|
|
d759b5 |
+ /* add newhostdev to end of def->hostdevs */
|
|
|
d759b5 |
+ if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, newhostdev) < 0)
|
|
|
d759b5 |
+ return -1;
|
|
|
d759b5 |
+ }
|
|
|
d759b5 |
+
|
|
|
d759b5 |
+ def->nets[netidx] = newnet;
|
|
|
d759b5 |
+ return 0;
|
|
|
d759b5 |
+}
|
|
|
d759b5 |
+
|
|
|
d759b5 |
+
|
|
|
d759b5 |
int virDomainControllerInsert(virDomainDefPtr def,
|
|
|
d759b5 |
virDomainControllerDefPtr controller)
|
|
|
d759b5 |
{
|
|
|
d759b5 |
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
|
|
|
d759b5 |
index 1c4556cecd..ef8f061ae2 100644
|
|
|
d759b5 |
--- a/src/conf/domain_conf.h
|
|
|
d759b5 |
+++ b/src/conf/domain_conf.h
|
|
|
d759b5 |
@@ -3168,6 +3168,7 @@ virDomainNetDefPtr virDomainNetFind(virDomainDefPtr def, const char *device);
|
|
|
d759b5 |
virDomainNetDefPtr virDomainNetFindByName(virDomainDefPtr def, const char *ifname);
|
|
|
d759b5 |
bool virDomainHasNet(virDomainDefPtr def, virDomainNetDefPtr net);
|
|
|
d759b5 |
int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net);
|
|
|
d759b5 |
+int virDomainNetUpdate(virDomainDefPtr def, size_t netidx, virDomainNetDefPtr newnet);
|
|
|
d759b5 |
virDomainNetDefPtr virDomainNetRemove(virDomainDefPtr def, size_t i);
|
|
|
d759b5 |
void virDomainNetRemoveHostdev(virDomainDefPtr def, virDomainNetDefPtr net);
|
|
|
d759b5 |
|
|
|
d759b5 |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
d759b5 |
index 9b5e1350f0..b213e5764b 100644
|
|
|
d759b5 |
--- a/src/libvirt_private.syms
|
|
|
d759b5 |
+++ b/src/libvirt_private.syms
|
|
|
d759b5 |
@@ -476,6 +476,7 @@ virDomainNetSetDeviceImpl;
|
|
|
d759b5 |
virDomainNetTypeFromString;
|
|
|
d759b5 |
virDomainNetTypeSharesHostView;
|
|
|
d759b5 |
virDomainNetTypeToString;
|
|
|
d759b5 |
+virDomainNetUpdate;
|
|
|
d759b5 |
virDomainNostateReasonTypeFromString;
|
|
|
d759b5 |
virDomainNostateReasonTypeToString;
|
|
|
d759b5 |
virDomainObjAssignDef;
|
|
|
d759b5 |
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
|
|
|
d759b5 |
index 5978183e7f..0f2ef47bb5 100644
|
|
|
d759b5 |
--- a/src/lxc/lxc_driver.c
|
|
|
d759b5 |
+++ b/src/lxc/lxc_driver.c
|
|
|
d759b5 |
@@ -3526,8 +3526,10 @@ lxcDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
|
|
|
d759b5 |
false) < 0)
|
|
|
d759b5 |
return -1;
|
|
|
d759b5 |
|
|
|
d759b5 |
- virDomainNetDefFree(vmdef->nets[idx]);
|
|
|
d759b5 |
- vmdef->nets[idx] = net;
|
|
|
d759b5 |
+ if (virDomainNetUpdate(vmdef, idx, net) < 0)
|
|
|
d759b5 |
+ return -1;
|
|
|
d759b5 |
+
|
|
|
d759b5 |
+ virDomainNetDefFree(oldDev.data.net);
|
|
|
d759b5 |
dev->data.net = NULL;
|
|
|
d759b5 |
ret = 0;
|
|
|
d759b5 |
|
|
|
d759b5 |
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
|
|
d759b5 |
index d95c97928d..2852b96edd 100644
|
|
|
d759b5 |
--- a/src/qemu/qemu_driver.c
|
|
|
d759b5 |
+++ b/src/qemu/qemu_driver.c
|
|
|
d759b5 |
@@ -8341,8 +8341,10 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef,
|
|
|
d759b5 |
false) < 0)
|
|
|
d759b5 |
return -1;
|
|
|
d759b5 |
|
|
|
d759b5 |
- virDomainNetDefFree(vmdef->nets[pos]);
|
|
|
d759b5 |
- vmdef->nets[pos] = net;
|
|
|
d759b5 |
+ if (virDomainNetUpdate(vmdef, pos, net))
|
|
|
d759b5 |
+ return -1;
|
|
|
d759b5 |
+
|
|
|
d759b5 |
+ virDomainNetDefFree(oldDev.data.net);
|
|
|
d759b5 |
dev->data.net = NULL;
|
|
|
d759b5 |
break;
|
|
|
d759b5 |
|
|
|
d759b5 |
--
|
|
|
d759b5 |
2.23.0
|
|
|
d759b5 |
|