Enable building for ppc64le

This commit is contained in:
Eduard Abdullin 2025-05-23 13:07:18 +00:00 committed by root
commit bc6466474b
21 changed files with 2396 additions and 170 deletions

View File

@ -0,0 +1,53 @@
From 514588d016d1e105f987d821331a578a34ccdf49 Mon Sep 17 00:00:00 2001
Message-ID: <514588d016d1e105f987d821331a578a34ccdf49.1745925135.git.jdenemar@redhat.com>
From: Martin Kletzander <mkletzan@redhat.com>
Date: Tue, 25 Feb 2025 15:36:03 +0100
Subject: [PATCH] Add load average information type into virDomainGetGuestInfo
The public API part.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit c52c449fd40c7263896d5f17129207b815c3a09c)
https://issues.redhat.com/browse/RHEL-88449
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
---
include/libvirt/libvirt-domain.h | 1 +
src/libvirt-domain.c | 8 ++++++++
2 files changed, 9 insertions(+)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index f026ce197c..c04b696f03 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -6425,6 +6425,7 @@ typedef enum {
VIR_DOMAIN_GUEST_INFO_FILESYSTEM = (1 << 4), /* return filesystem information (Since: 5.7.0) */
VIR_DOMAIN_GUEST_INFO_DISKS = (1 << 5), /* return disks information (Since: 7.0.0) */
VIR_DOMAIN_GUEST_INFO_INTERFACES = (1 << 6), /* return interfaces information (Since: 7.10.0) */
+ VIR_DOMAIN_GUEST_INFO_LOAD = (1 << 7), /* return load averages (Since: 11.2.0) */
} virDomainGuestInfoTypes;
int virDomainGetGuestInfo(virDomainPtr domain,
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 7c6b93963c..24752a9888 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -13292,6 +13292,14 @@ virDomainSetVcpu(virDomainPtr domain,
* "if.<num>.addr.<num1>.addr" - the IP address of addr <num1>
* "if.<num>.addr.<num1>.prefix" - the prefix of IP address of addr <num1>
*
+ * VIR_DOMAIN_GUEST_INFO_LOAD:
+ * Returns load (the number of processes in the runqueue or waiting for disk
+ * I/O) as double values:
+ *
+ * "load.1m" - load averaged over 1 minute
+ * "load.5m" - load averaged over 5 minutes
+ * "load.15m" - load averaged over 15 minutes
+ *
* Using 0 for @types returns all information groups supported by the given
* hypervisor.
*
--
2.49.0

View File

@ -0,0 +1,106 @@
From a52da24e19808954454be38945953a2a81c078e9 Mon Sep 17 00:00:00 2001
Message-ID: <a52da24e19808954454be38945953a2a81c078e9.1744361503.git.jdenemar@redhat.com>
From: Laine Stump <laine@redhat.com>
Date: Thu, 6 Mar 2025 19:19:12 -0500
Subject: [PATCH] conf: parse interface/source/@dev for all interface types
(with backend type='passt')
The original implementation of the passt backend for vhost-user
interfaces erroneously forgot to parse:
<source dev='blah'/>
for interface type='vhostuser', so it wasn't being added to the passt
commandline, and also wasn't being saved to the domain config. Now we
parse it whenever the <backend> type='passt', no matter what the
interface type, and then throw an error during validation if
source/@dev was specified for interface type = 'user|vhostuser' and
backend type != 'passt'.
Fixes: 1e9054b9c79d721a55f413c2983c5370044f8f60
Resolves: https://issues.redhat.com/browse/RHEL-82539
Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit 4c979edaa545c8425f7a856c06ebc0de939d4b9f)
https://issues.redhat.com/browse/RHEL-84689
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/conf/domain_conf.c | 8 +++++---
src/conf/domain_validate.c | 8 +++++++-
.../qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml | 2 ++
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 095b9bbaa2..94e26bf82a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -9900,9 +9900,6 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
break;
case VIR_DOMAIN_NET_TYPE_USER:
- def->sourceDev = virXMLPropString(source_node, "dev");
- break;
-
case VIR_DOMAIN_NET_TYPE_NULL:
case VIR_DOMAIN_NET_TYPE_LAST:
break;
@@ -10017,6 +10014,11 @@ virDomainNetDefParseXML(virDomainXMLOption *xmlopt,
return NULL;
}
+ if (def->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
+ def->sourceDev = virXMLPropString(source_node, "dev");
+ }
+
+
def->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DEFAULT;
if (linkstate != NULL) {
if ((def->linkstate = virDomainNetInterfaceLinkStateTypeFromString(linkstate)) <= 0) {
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 597ae3d938..9cedc8d6d2 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -2160,12 +2160,18 @@ virDomainNetDefValidate(const virDomainNetDef *net)
if (net->type != VIR_DOMAIN_NET_TYPE_USER &&
net->type != VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("The 'passt' backend can only be used with interface type='user' or type='vhostuser'"));
return -1;
}
}
+ if (net->sourceDev && net->backend.type != VIR_DOMAIN_NET_BACKEND_PASST) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("The 'dev' attribute of the <source> element can only be used with <interface> type='user' or type='vhostuser' if the <backend> type='passt'"));
+ return -1;
+ }
+
if (net->nPortForwards > 0) {
size_t p;
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml
index a1f9366722..529aff11f8 100644
--- a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml
+++ b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.xml
@@ -33,6 +33,7 @@
<controller type='pci' index='0' model='pci-root'/>
<interface type='vhostuser'>
<mac address='00:11:22:33:44:55'/>
+ <source dev='eth42'/>
<ip address='172.17.2.0' family='ipv4' prefix='24'/>
<ip address='2001:db8:ac10:fd01::feed' family='ipv6'/>
<portForward proto='tcp' address='2001:db8:ac10:fd01::1:10'>
@@ -63,6 +64,7 @@
</interface>
<interface type='vhostuser'>
<mac address='00:11:22:33:44:11'/>
+ <source dev='eth43'/>
<model type='virtio'/>
<backend type='passt'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
--
2.49.0

View File

@ -0,0 +1,44 @@
From 8e64dac6129cacd8f53813cbc7580209e96e7dc3 Mon Sep 17 00:00:00 2001
Message-ID: <8e64dac6129cacd8f53813cbc7580209e96e7dc3.1744361503.git.jdenemar@redhat.com>
From: Michal Privoznik <mprivozn@redhat.com>
Date: Thu, 13 Mar 2025 13:01:19 +0100
Subject: [PATCH] network: Free inhibitor in networkStateCleanup()
The shutdown inhibitor is created in networkStateInitialize() but
corresponding call to virInhibitorFree() is missing in
networkStateCleanup() leading to a memleak:
116 (72 direct, 44 indirect) bytes in 1 blocks are definitely lost in loss record 1,769 of 1,998
at 0x484CEF3: calloc (vg_replace_malloc.c:1675)
by 0x4F0E7A9: g_malloc0 (in /usr/lib64/libglib-2.0.so.0.8000.5)
by 0x4993B9B: virInhibitorNew (virinhibitor.c:152)
by 0x5279394: networkStateInitialize (bridge_driver.c:654)
by 0x4CC74DC: virStateInitialize (libvirt.c:665)
by 0x15B719: daemonRunStateInit (remote_daemon.c:613)
by 0x49F2B44: virThreadHelper (virthread.c:256)
by 0x5356662: start_thread (in /usr/lib64/libc.so.6)
by 0x53D7DA3: clone (in /usr/lib64/libc.so.6)
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit 8701ba4feb528109da8b72fa48a8ada50a235807)
Resolves: https://issues.redhat.com/browse/RHEL-83076
---
src/network/bridge_driver.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index ce793c12ef..adcff6f34f 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -802,6 +802,8 @@ networkStateCleanup(void)
network_driver->lockFD);
}
+ virInhibitorFree(network_driver->inhibitor);
+
virObjectUnref(network_driver->config);
virObjectUnref(network_driver->dnsmasqCaps);
--
2.49.0

View File

@ -0,0 +1,72 @@
From 816ce9100cbc410706fde26763158640f6d06f44 Mon Sep 17 00:00:00 2001
Message-ID: <816ce9100cbc410706fde26763158640f6d06f44.1745925135.git.jdenemar@redhat.com>
From: Martin Kletzander <mkletzan@redhat.com>
Date: Tue, 25 Feb 2025 15:36:32 +0100
Subject: [PATCH] qemu: Add support for VIR_DOMAIN_GUEST_INFO_LOAD
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit b4cf9c8cba45e65551aa9440dea2c3757a96aa0c)
https://issues.redhat.com/browse/RHEL-88449
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
---
src/qemu/qemu_driver.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index d65fc542d1..3e194999fe 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -19288,7 +19288,8 @@ static const unsigned int qemuDomainGetGuestInfoSupportedTypes =
VIR_DOMAIN_GUEST_INFO_HOSTNAME |
VIR_DOMAIN_GUEST_INFO_FILESYSTEM |
VIR_DOMAIN_GUEST_INFO_DISKS |
- VIR_DOMAIN_GUEST_INFO_INTERFACES;
+ VIR_DOMAIN_GUEST_INFO_INTERFACES |
+ VIR_DOMAIN_GUEST_INFO_LOAD;
static int
qemuDomainGetGuestInfoCheckSupport(unsigned int types,
@@ -19575,6 +19576,10 @@ qemuDomainGetGuestInfo(virDomainPtr dom,
qemuAgentDiskInfo **agentdiskinfo = NULL;
virDomainInterfacePtr *ifaces = NULL;
size_t nifaces = 0;
+ double load1m = 0;
+ double load5m = 0;
+ double load15m = 0;
+ bool format_load = false;
size_t i;
virCheckFlags(0, -1);
@@ -19645,6 +19650,14 @@ qemuDomainGetGuestInfo(virDomainPtr dom,
nifaces = rc;
}
+ if (supportedTypes & VIR_DOMAIN_GUEST_INFO_LOAD) {
+ rc = qemuAgentGetLoadAvg(agent, &load1m, &load5m, &load15m, report_unsupported);
+ if (rc == -1)
+ goto exitagent;
+ if (rc >= 0)
+ format_load = true;
+ }
+
qemuDomainObjExitAgent(vm, agent);
virDomainObjEndAgentJob(vm);
@@ -19671,6 +19684,12 @@ qemuDomainGetGuestInfo(virDomainPtr dom,
virDomainInterfaceFormatParams(ifaces, nifaces, params, nparams, &maxparams);
}
+ if (format_load) {
+ virTypedParamsAddDouble(params, nparams, &maxparams, "load.1m", load1m);
+ virTypedParamsAddDouble(params, nparams, &maxparams, "load.5m", load5m);
+ virTypedParamsAddDouble(params, nparams, &maxparams, "load.15m", load15m);
+ }
+
ret = 0;
cleanup:
--
2.49.0

View File

@ -1,38 +0,0 @@
From d874530eaded03d0b90139c9bbd80902b9464e87 Mon Sep 17 00:00:00 2001
Message-ID: <d874530eaded03d0b90139c9bbd80902b9464e87.1741876175.git.jdenemar@redhat.com>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Tue, 18 Feb 2025 11:24:32 +0100
Subject: [PATCH] qemu: Avoid crash in qemuDomainCheckCPU with unknown host CPU
When we don't have any information about host CPU (for example when
running on an aarch64 host), the virQEMUCapsGetHostModel would return
NULL.
Fixes: f928eb5fc80ca0ed7277f2513b63aed36c09d275
Fixes: https://gitlab.com/libvirt/libvirt/-/issues/747
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Tested-by: Jaroslav Suchanek <jsuchane@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 43eae1b7077104d4e2ed52447407a335c2d093e3)
https://issues.redhat.com/browse/RHEL-81747
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_domain.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 92035dd281..1ccaff90d9 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -11446,6 +11446,7 @@ qemuDomainCheckCPU(virArch arch,
/* Force compat check if the CPU model is not found in qemuCaps or
* we don't have host CPU data from QEMU */
if (!cpu->model ||
+ !hypervisorCPU ||
hypervisorCPU->fallback != VIR_CPU_FALLBACK_FORBID ||
virQEMUCapsGetCPUBlockers(qemuCaps, virtType,
cpu->model, &blockers) < 0)
--
2.48.1

View File

@ -0,0 +1,111 @@
From bc0074073da43052e4a786eca70dd5fbbf023903 Mon Sep 17 00:00:00 2001
Message-ID: <bc0074073da43052e4a786eca70dd5fbbf023903.1744361503.git.jdenemar@redhat.com>
From: Laine Stump <laine@redhat.com>
Date: Fri, 4 Apr 2025 19:44:52 -0400
Subject: [PATCH] qemu: make passt+vhostuser reconnect behave identically to
passt+user
When "original passt" support was added, we decided that we always
wanted to reconnect (i.e. restart the passt process) if it was somehow
terminated. Generic vhost-user, on the other hand, only turns on
reconnect if specified by the user in the config. But there is no
reason to require the user to specify this if the other end of the
vhost-user socket is a passt process - we know what has happened and
what we want to do; no reason to do the *wrong* thing by default, and
force the user to make an arbitrary decision about what to add to the
config in order to make it do the *right* thing; instead we just
hardcode it to always do the right thing.
(NB: when the backend is passt, <interface type='vhostuser'> has
always ignored the reconnect setting in <source> when parsing and
formatting, just as it has always ignored the socket path (since that
also is not user configurable for the passt backend)
Resolves: https://issues.redhat.com/browse/RHEL-80169
Signed-off-by: Laine Stump <laine@redhat.com>
Tested-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 44abaa0128ac0fc8be9de4eebc15c03809bf5867)
Conflicts:
tests/qemuxmlconfdata/schema-reorder-domain-subelements.x86_64-latest.args:
This file (created by upstream commit be5332c81d28) was modified
upstream but doesin't exist downstream
https://issues.redhat.com/browse/RHEL-84782
Signed-off-by: Laine Stump <laine@redhat.com>
---
src/qemu/qemu_passt.c | 16 +++++++++++++---
.../net-vhostuser-passt.x86_64-latest.args | 6 +++---
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/qemu/qemu_passt.c b/src/qemu/qemu_passt.c
index bc495eca1e..fcc34de384 100644
--- a/src/qemu/qemu_passt.c
+++ b/src/qemu/qemu_passt.c
@@ -36,7 +36,7 @@ VIR_LOG_INIT("qemu.passt");
#define PASST "passt"
-
+#define QEMU_PASST_RECONNECT_TIMEOUT 5
static char *
qemuPasstCreatePidFilename(virDomainObj *vm,
@@ -106,11 +106,15 @@ qemuPasstAddNetProps(virDomainObj *vm,
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV_STREAM_RECONNECT)) {
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV_STREAM_RECONNECT_MILISECONDS)) {
- if (virJSONValueObjectAdd(netprops, "u:reconnect-ms", 5000, NULL) < 0)
+ if (virJSONValueObjectAdd(netprops, "u:reconnect-ms",
+ QEMU_PASST_RECONNECT_TIMEOUT * 1000, NULL) < 0) {
return -1;
+ }
} else {
- if (virJSONValueObjectAdd(netprops, "u:reconnect", 5, NULL) < 0)
+ if (virJSONValueObjectAdd(netprops, "u:reconnect",
+ QEMU_PASST_RECONNECT_TIMEOUT, NULL) < 0) {
return -1;
+ }
}
}
@@ -182,6 +186,12 @@ qemuPasstPrepareVhostUser(virDomainObj *vm,
*/
g_free(net->data.vhostuser->data.nix.path);
net->data.vhostuser->data.nix.path = qemuPasstCreateSocketPath(vm, net);
+
+ /* reconnect is always enabled, with timeout always at 5 seconds, when
+ * using passt
+ */
+ net->data.vhostuser->data.nix.reconnect.enabled = VIR_TRISTATE_BOOL_YES;
+ net->data.vhostuser->data.nix.reconnect.timeout = QEMU_PASST_RECONNECT_TIMEOUT;
}
int
diff --git a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args
index 7c030d7067..afbbe188cf 100644
--- a/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/net-vhostuser-passt.x86_64-latest.args
@@ -28,13 +28,13 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-boot strict=on \
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest1","node-name":"libvirt-1-storage","read-only":false}' \
-device '{"driver":"ide-hd","bus":"ide.0","unit":0,"drive":"libvirt-1-storage","id":"ide0-0-0","bootindex":1}' \
--chardev socket,id=charnet0,path=/var/run/libvirt/qemu/passt/-1-QEMUGuest1-net0.socket \
+-chardev socket,id=charnet0,path=/var/run/libvirt/qemu/passt/-1-QEMUGuest1-net0.socket,reconnect-ms=5000 \
-netdev '{"type":"vhost-user","chardev":"charnet0","id":"hostnet0"}' \
-device '{"driver":"virtio-net-pci","netdev":"hostnet0","id":"net0","mac":"00:11:22:33:44:55","bus":"pci.0","addr":"0x2"}' \
--chardev socket,id=charnet1,path=/var/run/libvirt/qemu/passt/-1-QEMUGuest1-net1.socket \
+-chardev socket,id=charnet1,path=/var/run/libvirt/qemu/passt/-1-QEMUGuest1-net1.socket,reconnect-ms=5000 \
-netdev '{"type":"vhost-user","chardev":"charnet1","id":"hostnet1"}' \
-device '{"driver":"virtio-net-pci","netdev":"hostnet1","id":"net1","mac":"00:11:22:33:44:11","bus":"pci.0","addr":"0x3"}' \
--chardev socket,id=charnet2,path=/var/run/libvirt/qemu/passt/-1-QEMUGuest1-net2.socket \
+-chardev socket,id=charnet2,path=/var/run/libvirt/qemu/passt/-1-QEMUGuest1-net2.socket,reconnect-ms=5000 \
-netdev '{"type":"vhost-user","chardev":"charnet2","id":"hostnet2"}' \
-device '{"driver":"virtio-net-pci","netdev":"hostnet2","id":"net2","mac":"00:11:22:33:44:11","bus":"pci.0","addr":"0x4"}' \
-audiodev '{"id":"audio1","driver":"none"}' \
--
2.49.0

View File

@ -0,0 +1,119 @@
From 718c4bc80d3af4570d75b590625bd5249aa50a8d Mon Sep 17 00:00:00 2001
Message-ID: <718c4bc80d3af4570d75b590625bd5249aa50a8d.1744361503.git.jdenemar@redhat.com>
From: Laine Stump <laine@redhat.com>
Date: Fri, 4 Apr 2025 16:57:21 -0400
Subject: [PATCH] qemu: make processNetDevStreamDisconnectedEvent() reusable
We will be adding a new event whose response will be *exactly* the
same as the response to NETDEV_STREAM_DISCONNECTED. Rather than doing
a copy-paste of the complete function that does the processing, turn
that function into something more generic that takes the name of the
event as an arg (the event name is only used in log messages).
Signed-off-by: Laine Stump <laine@redhat.com>
Tested-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 03a6bc7752ec73d7ea222d5386e8f4124fe51c7f)
Conflicts:
src/qemu/qemu_driver.c:
In context surrounding a chunk, the arguments to
processNicRxFilterChangedEvent() changed upstream (due to upstream
commit 50981052a5f)
https://issues.redhat.com/browse/RHEL-84782
Signed-off-by: Laine Stump <laine@redhat.com>
---
src/qemu/qemu_driver.c | 37 +++++++++++++++++++++++--------------
1 file changed, 23 insertions(+), 14 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 53dcd690f0..65e17a870d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3618,8 +3618,9 @@ processDeviceDeletedEvent(virQEMUDriver *driver,
static void
-processNetdevStreamDisconnectedEvent(virDomainObj *vm,
- const char *netdevId)
+processNetdevDisconnectedEvent(virDomainObj *vm,
+ const char *netdevId,
+ const char *eventName)
{
virDomainDeviceDef dev;
virDomainNetDef *def;
@@ -3634,13 +3635,13 @@ processNetdevStreamDisconnectedEvent(virDomainObj *vm,
*/
if (!devAlias) {
- VIR_WARN("Received NETDEV_STREAM_DISCONNECTED event for unrecognized netdev %s from domain %p %s",
- netdevId, vm, vm->def->name);
+ VIR_WARN("Received %s event for unrecognized netdev %s from domain %p %s",
+ eventName, netdevId, vm, vm->def->name);
return;
}
- VIR_DEBUG("Received NETDEV_STREAM_DISCONNECTED event for device %s from domain %p %s",
- devAlias, vm, vm->def->name);
+ VIR_DEBUG("Received %s event for device %s from domain %p %s",
+ eventName, devAlias, vm, vm->def->name);
if (virDomainObjBeginJob(vm, VIR_JOB_QUERY) < 0)
return;
@@ -3651,28 +3652,28 @@ processNetdevStreamDisconnectedEvent(virDomainObj *vm,
}
if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0) {
- VIR_WARN("NETDEV_STREAM_DISCONNECTED event received for non-existent device %s in domain %s",
- devAlias, vm->def->name);
+ VIR_WARN("%s event received for non-existent device %s in domain %s",
+ eventName, devAlias, vm->def->name);
goto endjob;
}
if (dev.type != VIR_DOMAIN_DEVICE_NET) {
- VIR_WARN("NETDEV_STREAM_DISCONNECTED event received for non-network device %s in domain %s",
- devAlias, vm->def->name);
+ VIR_WARN("%s event received for non-network device %s in domain %s",
+ eventName, devAlias, vm->def->name);
goto endjob;
}
def = dev.data.net;
if (def->backend.type != VIR_DOMAIN_NET_BACKEND_PASST) {
- VIR_DEBUG("ignore NETDEV_STREAM_DISCONNECTED event for non-passt network device %s in domain %s",
- def->info.alias, vm->def->name);
+ VIR_DEBUG("ignore %s event for non-passt network device %s in domain %s",
+ eventName, def->info.alias, vm->def->name);
goto endjob;
}
/* handle the event - restart the passt process with its original
* parameters
*/
- VIR_DEBUG("process NETDEV_STREAM_DISCONNECTED event for network device %s in domain %s",
- def->info.alias, vm->def->name);
+ VIR_DEBUG("process %s event for network device %s in domain %s",
+ eventName, def->info.alias, vm->def->name);
if (qemuPasstStart(vm, def) < 0)
goto endjob;
@@ -3682,6 +3683,14 @@ processNetdevStreamDisconnectedEvent(virDomainObj *vm,
}
+static void
+processNetdevStreamDisconnectedEvent(virDomainObj *vm,
+ const char *netdevId)
+{
+ processNetdevDisconnectedEvent(vm, netdevId, "NETDEV_STREAM_DISCONNECTED");
+}
+
+
static void
processNicRxFilterChangedEvent(virDomainObj *vm,
const char *devAlias)
--
2.49.0

View File

@ -0,0 +1,110 @@
From c6e5688293b765885e8b76c35ad47bc316de81aa Mon Sep 17 00:00:00 2001
Message-ID: <c6e5688293b765885e8b76c35ad47bc316de81aa.1744361503.git.jdenemar@redhat.com>
From: Laine Stump <laine@redhat.com>
Date: Fri, 4 Apr 2025 19:38:28 -0400
Subject: [PATCH] qemu: put vhost-user code that's special for passt in a
helper function
Rather than duplicating these two lines of chr device object setup for
hotplug and domain start, put them in a helper function that's called
from both places. That way when we need to setup *more* stuff specific
to passt+vhostuser, we can just add it in that one place.
Signed-off-by: Laine Stump <laine@redhat.com>
Tested-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 95ff77f2896478e039673bb552affec2c5a5e822)
https://issues.redhat.com/browse/RHEL-84782
Signed-off-by: Laine Stump <laine@redhat.com>
---
src/qemu/qemu_hotplug.c | 7 +------
src/qemu/qemu_passt.c | 19 +++++++++++++++++++
src/qemu/qemu_passt.h | 3 +++
src/qemu/qemu_process.c | 9 ++-------
4 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index c8746f5e22..ff09b58bfe 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1264,12 +1264,7 @@ qemuDomainAttachNetDevice(virQEMUDriver *driver,
if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
- /* vhostuser needs socket path in this location, and when
- * backend is passt, the path is derived from other info,
- * not taken from config.
- */
- g_free(net->data.vhostuser->data.nix.path);
- net->data.vhostuser->data.nix.path = qemuPasstCreateSocketPath(vm, net);
+ qemuPasstPrepareVhostUser(vm, net);
if (qemuPasstStart(vm, net) < 0)
goto cleanup;
diff --git a/src/qemu/qemu_passt.c b/src/qemu/qemu_passt.c
index b9616d1c63..bc495eca1e 100644
--- a/src/qemu/qemu_passt.c
+++ b/src/qemu/qemu_passt.c
@@ -165,6 +165,25 @@ qemuPasstSetupCgroup(virDomainObj *vm,
}
+void
+qemuPasstPrepareVhostUser(virDomainObj *vm,
+ virDomainNetDef *net)
+{
+ /* There are some options on the QEMU commandline for a vhost-user
+ * chr device that are normally configurable, but when it is passt
+ * speaking to the vhost-user device those things are
+ * derived/fixed. This function, which is called prior to
+ * generating the QEMU commandline, sets thos derived/fixed things
+ * in the chr device object.
+ */
+
+ /* The socket path is not user-configurable for passt - it is
+ * derived from other info
+ */
+ g_free(net->data.vhostuser->data.nix.path);
+ net->data.vhostuser->data.nix.path = qemuPasstCreateSocketPath(vm, net);
+}
+
int
qemuPasstStart(virDomainObj *vm,
virDomainNetDef *net)
diff --git a/src/qemu/qemu_passt.h b/src/qemu/qemu_passt.h
index e0b9aaac8d..ea545ccf38 100644
--- a/src/qemu/qemu_passt.h
+++ b/src/qemu/qemu_passt.h
@@ -37,5 +37,8 @@ int qemuPasstSetupCgroup(virDomainObj *vm,
virDomainNetDef *net,
virCgroup *cgroup);
+void qemuPasstPrepareVhostUser(virDomainObj *vm,
+ virDomainNetDef *net);
+
char *qemuPasstCreateSocketPath(virDomainObj *vm,
virDomainNetDef *net);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index f5c277203f..c80d7bb6dc 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5952,13 +5952,8 @@ qemuProcessPrepareDomainNetwork(virDomainObj *vm)
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
if (net->backend.type == VIR_DOMAIN_NET_BACKEND_PASST) {
- /* when using the passt backend, the path of the
- * unix socket is always derived from other info
- * *not* manually given in the config, but all the
- * vhostuser code looks for it there.
- */
- g_free(net->data.vhostuser->data.nix.path);
- net->data.vhostuser->data.nix.path = qemuPasstCreateSocketPath(vm, net);
+ /* some extra setup of internal data for passt vhostuser mode */
+ qemuPasstPrepareVhostUser(vm, net);
}
break;
--
2.49.0

View File

@ -0,0 +1,56 @@
From f6d606779aaedc8a6d958a2e97b462df390cb0a5 Mon Sep 17 00:00:00 2001
Message-ID: <f6d606779aaedc8a6d958a2e97b462df390cb0a5.1744361503.git.jdenemar@redhat.com>
From: Laine Stump <laine@redhat.com>
Date: Fri, 4 Apr 2025 16:48:23 -0400
Subject: [PATCH] qemu: remove nonsensical sanity check in
processNetdevStreamDisconnectedEvent()
By definition QEMU will never send a NETDEV_STREAM_DISCONNECTED event
if it doesn't support the reconnect option for a stream netdev. And
even if, by some comedy of errors, it did send
NETDEV_STREAM_DISCONNECTED in that case, our response to the event
doesn't request anything at all of QEMU (much less something that
would fail if QEMU didn't understand NETDEV_STREAM_DISCONNECTED) - it
just starts a new passt process to replace the one that has been
terminated, so we don't need to check the QEMU capabilities for
QEMU_CAPS_NETDEV_STREAM_RECONNECT.
Signed-off-by: Laine Stump <laine@redhat.com>
Tested-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 51a54dc1c4ecf37d60acee1cb94252e51c5ef627)
https://issues.redhat.com/browse/RHEL-84782
Signed-off-by: Laine Stump <laine@redhat.com>
---
src/qemu/qemu_driver.c | 7 -------
1 file changed, 7 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index f8f3d2c725..53dcd690f0 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3623,7 +3623,6 @@ processNetdevStreamDisconnectedEvent(virDomainObj *vm,
{
virDomainDeviceDef dev;
virDomainNetDef *def;
- virQEMUCaps *qemuCaps = QEMU_DOMAIN_PRIVATE(vm)->qemuCaps;
const char *devAlias = STRSKIP(netdevId, "host");
/* The event sends us the "netdev-id", but we don't store the
@@ -3669,12 +3668,6 @@ processNetdevStreamDisconnectedEvent(virDomainObj *vm,
goto endjob;
}
- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_NETDEV_STREAM_RECONNECT)) {
- VIR_WARN("ignore NETDEV_STREAM_DISCONNECTED event for passt network device %s in domain %s - QEMU binary does not support reconnect",
- def->info.alias, vm->def->name);
- goto endjob;
- }
-
/* handle the event - restart the passt process with its original
* parameters
*/
--
2.49.0

View File

@ -0,0 +1,224 @@
From 874251dd0b6fdbf3a0be8e494f83001e5f028868 Mon Sep 17 00:00:00 2001
Message-ID: <874251dd0b6fdbf3a0be8e494f83001e5f028868.1744361503.git.jdenemar@redhat.com>
From: Laine Stump <laine@redhat.com>
Date: Fri, 4 Apr 2025 17:16:43 -0400
Subject: [PATCH] qemu: respond to NETDEV_VHOST_USER_DISCONNECTED event
This response to this event is identical to NETDEV_STREAM_DISCONNECTED
(start a new passt process to replace the one that just disappeared -
see commitf62ce81b8a5), except that the new passt process will have
"--vhost-user" appended to the commandline. Fortunately that
difference is already handled based on the virDomainNetDef contents,
so we can, in fact, respond to the new event in exactly the same
manner.
Signed-off-by: Laine Stump <laine@redhat.com>
Tested-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit dedf1ada95f046310827194eb8794fa18975b9e7)
Conflicts:
src/qemu/qemu_driver.c:
In context surrounding a chunk, the arguments to
processNicRxFilterChangedEvent() changed upstream (due to upstream
commit 50981052a5f)
https://issues.redhat.com/browse/RHEL-84782
Signed-off-by: Laine Stump <laine@redhat.com>
---
src/qemu/qemu_domain.c | 1 +
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_driver.c | 11 +++++++++++
src/qemu/qemu_monitor.c | 11 +++++++++++
src/qemu/qemu_monitor.h | 6 ++++++
src/qemu/qemu_monitor_json.c | 16 ++++++++++++++++
src/qemu/qemu_process.c | 18 ++++++++++++++++++
7 files changed, 64 insertions(+)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 92035dd281..95cca36fe1 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -10036,6 +10036,7 @@ qemuProcessEventFree(struct qemuProcessEvent *event)
case QEMU_PROCESS_EVENT_WATCHDOG:
case QEMU_PROCESS_EVENT_DEVICE_DELETED:
case QEMU_PROCESS_EVENT_NETDEV_STREAM_DISCONNECTED:
+ case QEMU_PROCESS_EVENT_NETDEV_VHOST_USER_DISCONNECTED:
case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
case QEMU_PROCESS_EVENT_SERIAL_CHANGED:
case QEMU_PROCESS_EVENT_GUEST_CRASHLOADED:
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index e810f79599..79bdc4e8fe 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -465,6 +465,7 @@ typedef enum {
QEMU_PROCESS_EVENT_GUESTPANIC,
QEMU_PROCESS_EVENT_DEVICE_DELETED,
QEMU_PROCESS_EVENT_NETDEV_STREAM_DISCONNECTED,
+ QEMU_PROCESS_EVENT_NETDEV_VHOST_USER_DISCONNECTED,
QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED,
QEMU_PROCESS_EVENT_SERIAL_CHANGED,
QEMU_PROCESS_EVENT_JOB_STATUS_CHANGE,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 65e17a870d..d65fc542d1 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3691,6 +3691,14 @@ processNetdevStreamDisconnectedEvent(virDomainObj *vm,
}
+static void
+processNetdevVhostUserDisconnectedEvent(virDomainObj *vm,
+ const char *netdevId)
+{
+ processNetdevDisconnectedEvent(vm, netdevId, "NETDEV_VHOST_USER_DISCONNECTED");
+}
+
+
static void
processNicRxFilterChangedEvent(virDomainObj *vm,
const char *devAlias)
@@ -4086,6 +4094,9 @@ static void qemuProcessEventHandler(void *data, void *opaque)
case QEMU_PROCESS_EVENT_NETDEV_STREAM_DISCONNECTED:
processNetdevStreamDisconnectedEvent(vm, processEvent->data);
break;
+ case QEMU_PROCESS_EVENT_NETDEV_VHOST_USER_DISCONNECTED:
+ processNetdevVhostUserDisconnectedEvent(vm, processEvent->data);
+ break;
case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
processNicRxFilterChangedEvent(vm, processEvent->data);
break;
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 82aa1cbc5f..ed63b7a29b 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1267,6 +1267,17 @@ qemuMonitorEmitNetdevStreamDisconnected(qemuMonitor *mon,
}
+void
+qemuMonitorEmitNetdevVhostUserDisconnected(qemuMonitor *mon,
+ const char *devAlias)
+{
+ VIR_DEBUG("mon=%p", mon);
+
+ QEMU_MONITOR_CALLBACK(mon, domainNetdevVhostUserDisconnected,
+ mon->vm, devAlias);
+}
+
+
void
qemuMonitorEmitSerialChange(qemuMonitor *mon,
const char *devAlias,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 672cd6487e..bcb39409ac 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -255,6 +255,9 @@ typedef void (*qemuMonitorDomainDeviceUnplugErrCallback)(qemuMonitor *mon,
typedef void (*qemuMonitorDomainNetdevStreamDisconnectedCallback)(qemuMonitor *mon,
virDomainObj *vm,
const char *devAlias);
+typedef void (*qemuMonitorDomainNetdevVhostUserDisconnectedCallback)(qemuMonitor *mon,
+ virDomainObj *vm,
+ const char *devAlias);
typedef void (*qemuMonitorDomainNicRxFilterChangedCallback)(qemuMonitor *mon,
virDomainObj *vm,
const char *devAlias);
@@ -403,6 +406,7 @@ struct _qemuMonitorCallbacks {
qemuMonitorDomainMemoryDeviceSizeChange domainMemoryDeviceSizeChange;
qemuMonitorDomainDeviceUnplugErrCallback domainDeviceUnplugError;
qemuMonitorDomainNetdevStreamDisconnectedCallback domainNetdevStreamDisconnected;
+ qemuMonitorDomainNetdevVhostUserDisconnectedCallback domainNetdevVhostUserDisconnected;
};
qemuMonitor *qemuMonitorOpen(virDomainObj *vm,
@@ -490,6 +494,8 @@ void qemuMonitorEmitDeviceUnplugErr(qemuMonitor *mon,
const char *devAlias);
void qemuMonitorEmitNetdevStreamDisconnected(qemuMonitor *mon,
const char *devAlias);
+void qemuMonitorEmitNetdevVhostUserDisconnected(qemuMonitor *mon,
+ const char *devAlias);
void qemuMonitorEmitNicRxFilterChanged(qemuMonitor *mon,
const char *devAlias);
void qemuMonitorEmitSerialChange(qemuMonitor *mon,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 6f9f495888..be5d3be7e6 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -85,6 +85,7 @@ static void qemuMonitorJSONHandleMemoryFailure(qemuMonitor *mon, virJSONValue *d
static void qemuMonitorJSONHandleMemoryDeviceSizeChange(qemuMonitor *mon, virJSONValue *data);
static void qemuMonitorJSONHandleDeviceUnplugErr(qemuMonitor *mon, virJSONValue *data);
static void qemuMonitorJSONHandleNetdevStreamDisconnected(qemuMonitor *mon, virJSONValue *data);
+static void qemuMonitorJSONHandleNetdevVhostUserDisconnected(qemuMonitor *mon, virJSONValue *data);
typedef struct {
const char *type;
@@ -108,6 +109,7 @@ static qemuEventHandler eventHandlers[] = {
{ "MIGRATION", qemuMonitorJSONHandleMigrationStatus, },
{ "MIGRATION_PASS", qemuMonitorJSONHandleMigrationPass, },
{ "NETDEV_STREAM_DISCONNECTED", qemuMonitorJSONHandleNetdevStreamDisconnected, },
+ { "NETDEV_VHOST_USER_DISCONNECTED", qemuMonitorJSONHandleNetdevVhostUserDisconnected, },
{ "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged, },
{ "PR_MANAGER_STATUS_CHANGED", qemuMonitorJSONHandlePRManagerStatusChanged, },
{ "RDMA_GID_STATUS_CHANGED", qemuMonitorJSONHandleRdmaGidStatusChanged, },
@@ -1044,6 +1046,20 @@ qemuMonitorJSONHandleNetdevStreamDisconnected(qemuMonitor *mon, virJSONValue *da
}
+static void
+qemuMonitorJSONHandleNetdevVhostUserDisconnected(qemuMonitor *mon, virJSONValue *data)
+{
+ const char *name;
+
+ if (!(name = virJSONValueObjectGetString(data, "netdev-id"))) {
+ VIR_WARN("missing device in NETDEV_VHOST_USER_DISCONNECTED event");
+ return;
+ }
+
+ qemuMonitorEmitNetdevVhostUserDisconnected(mon, name);
+}
+
+
static void
qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitor *mon, virJSONValue *data)
{
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 722e982b9e..f5c277203f 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1402,6 +1402,23 @@ qemuProcessHandleNetdevStreamDisconnected(qemuMonitor *mon G_GNUC_UNUSED,
}
+static void
+qemuProcessHandleNetdevVhostUserDisconnected(qemuMonitor *mon G_GNUC_UNUSED,
+ virDomainObj *vm,
+ const char *devAlias)
+{
+ virObjectLock(vm);
+
+ VIR_DEBUG("Device %s Netdev vhost-user Disconnected in domain %p %s",
+ devAlias, vm, vm->def->name);
+
+ qemuProcessEventSubmit(vm, QEMU_PROCESS_EVENT_NETDEV_VHOST_USER_DISCONNECTED,
+ 0, 0, g_strdup(devAlias));
+
+ virObjectUnlock(vm);
+}
+
+
static void
qemuProcessHandleNicRxFilterChanged(qemuMonitor *mon G_GNUC_UNUSED,
virDomainObj *vm,
@@ -1848,6 +1865,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
.domainMemoryDeviceSizeChange = qemuProcessHandleMemoryDeviceSizeChange,
.domainDeviceUnplugError = qemuProcessHandleDeviceUnplugErr,
.domainNetdevStreamDisconnected = qemuProcessHandleNetdevStreamDisconnected,
+ .domainNetdevVhostUserDisconnected = qemuProcessHandleNetdevVhostUserDisconnected,
};
static void
--
2.49.0

View File

@ -1,75 +0,0 @@
From c9c9405687b78713b913c09113697fcadec1cdba Mon Sep 17 00:00:00 2001
Message-ID: <c9c9405687b78713b913c09113697fcadec1cdba.1741876175.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Wed, 26 Feb 2025 11:04:52 +0100
Subject: [PATCH] qemu: snapshot: error out early when reverting snapshot for
VM with non-file disk
Before this patch the code would start the revert process by destroying
the VM and preparing to revert where it would fail with following error:
error: unsupported configuration: source for disk 'sdb' is not a regular file; refusing to generate external snapshot name
and leaving user with offline VM even if it was running.
Make the check before we start the revert process to not destroy VMs.
Resolves: https://issues.redhat.com/browse/RHEL-30971
Resolves: https://issues.redhat.com/browse/RHEL-79928
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit 278b8334eb26aa9495f6d37e4f72471cbc8739a6)
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_snapshot.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index 3a8510c69e..16d3aaf6e7 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -2190,6 +2190,8 @@ qemuSnapshotRevertValidate(virDomainObj *vm,
virDomainSnapshotDef *snapdef,
unsigned int flags)
{
+ size_t i;
+
if (!vm->persistent &&
snapdef->state != VIR_DOMAIN_SNAPSHOT_RUNNING &&
snapdef->state != VIR_DOMAIN_SNAPSHOT_PAUSED &&
@@ -2217,6 +2219,22 @@ qemuSnapshotRevertValidate(virDomainObj *vm,
}
}
+ /* Reverting to external snapshot creates overlay files for every disk and
+ * it would fail for non-file based disks.
+ * See qemuSnapshotRevertExternalPrepare for more details. */
+ if (virDomainSnapshotIsExternal(snap)) {
+ for (i = 0; i < snap->def->dom->ndisks; i++) {
+ virDomainDiskDef *disk = snap->def->dom->disks[i];
+
+ if (disk->src->type != VIR_STORAGE_TYPE_FILE) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
+ _("source disk for '%1$s' is not a regular file, reverting to snapshot is not supported"),
+ disk->dst);
+ return -1;
+ }
+ }
+ }
+
return 0;
}
@@ -2368,6 +2386,9 @@ qemuSnapshotRevertExternalPrepare(virDomainObj *vm,
if (virDomainMomentDefPostParse(&tmpsnapdef->parent) < 0)
return -1;
+ /* Force default location to be external in order to create overlay files
+ * for every disk. In qemuSnapshotRevertValidate we make sure that each
+ * disk is regular file otherwise this would fail. */
if (virDomainSnapshotAlignDisks(tmpsnapdef, domdef,
VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL,
false, true) < 0) {
--
2.48.1

View File

@ -0,0 +1,163 @@
From 4e04c0a27ced260053815b2348474ef7226aabb7 Mon Sep 17 00:00:00 2001
Message-ID: <4e04c0a27ced260053815b2348474ef7226aabb7.1745925135.git.jdenemar@redhat.com>
From: Martin Kletzander <mkletzan@redhat.com>
Date: Tue, 25 Feb 2025 15:23:07 +0100
Subject: [PATCH] qemu_agent: Add qemuAgentGetLoadAvg()
With qemu guest agent 9.3 we are able to get the load averages with a
new command.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit 1669d91eade46b930ebb44e4b9d398ea8c2064e7)
https://issues.redhat.com/browse/RHEL-88449
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
---
src/qemu/qemu_agent.c | 46 +++++++++++++++++++++++++++++++++++++
src/qemu/qemu_agent.h | 6 +++++
tests/qemuagenttest.c | 53 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 105 insertions(+)
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 43fca86f10..16a6eaa998 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -2568,3 +2568,49 @@ int qemuAgentGetDisks(qemuAgent *agent,
g_free(*disks);
return -1;
}
+
+
+int
+qemuAgentGetLoadAvg(qemuAgent *agent,
+ double *load1m,
+ double *load5m,
+ double *load15m,
+ bool report_unsupported)
+{
+ g_autoptr(virJSONValue) cmd = NULL;
+ g_autoptr(virJSONValue) reply = NULL;
+ virJSONValue *data = NULL;
+ int rc;
+
+ if (!(cmd = qemuAgentMakeCommand("guest-get-load", NULL)))
+ return -1;
+
+ if ((rc = qemuAgentCommandFull(agent, cmd, &reply, agent->timeout,
+ report_unsupported)) < 0)
+ return rc;
+
+ if (!(data = virJSONValueObjectGetObject(reply, "return"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qemu agent didn't return an array of loads"));
+ return -1;
+ }
+
+#define GET_NUMBER_PARAM(param_) \
+ do { \
+ if (param_ && \
+ virJSONValueObjectGetNumberDouble(data, #param_, param_) < 0) { \
+ virReportError(VIR_ERR_INTERNAL_ERROR, \
+ _("parameter '%1$s' is missing in reply of guest-get-load"), \
+ #param_); \
+ return -1; \
+ } \
+ } while (0)
+
+ GET_NUMBER_PARAM(load1m);
+ GET_NUMBER_PARAM(load5m);
+ GET_NUMBER_PARAM(load15m);
+
+#undef GET_NUMBER_PARAM
+
+ return 0;
+}
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index f98586e8f8..cd17a98d39 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -195,3 +195,9 @@ int qemuAgentSSHRemoveAuthorizedKeys(qemuAgent *agent,
int qemuAgentGetDisks(qemuAgent *mon,
qemuAgentDiskInfo ***disks,
bool report_unsupported);
+
+int qemuAgentGetLoadAvg(qemuAgent *agent,
+ double *load1m,
+ double *load5m,
+ double *load15m,
+ bool report_unsupported);
diff --git a/tests/qemuagenttest.c b/tests/qemuagenttest.c
index 3287880241..566571cf11 100644
--- a/tests/qemuagenttest.c
+++ b/tests/qemuagenttest.c
@@ -1356,6 +1356,58 @@ testQemuAgentTimezone(const void *data)
virTypedParamsFree(params, nparams);
return ret;
}
+
+
+static const char testQemuAgentGetLoadAvgResponse[] =
+ "{"
+ " \"return\": {"
+ " \"load15m\": 0.03564453125,"
+ " \"load5m\": 0.064453125,"
+ " \"load1m\": 0.00390625"
+ " }"
+ "}";
+
+static int
+testQemuAgentGetLoadAvg(const void *data)
+{
+ virDomainXMLOption *xmlopt = (virDomainXMLOption *)data;
+ g_autoptr(qemuMonitorTest) test = qemuMonitorTestNewAgent(xmlopt);
+ double load1m = 0;
+ double load5m = 0;
+ double load15m = 0;
+
+ if (!test)
+ return -1;
+
+ if (qemuMonitorTestAddAgentSyncResponse(test) < 0)
+ return -1;
+
+ if (qemuMonitorTestAddItem(test, "guest-get-load",
+ testQemuAgentGetLoadAvgResponse) < 0)
+ return -1;
+
+ if (qemuAgentGetLoadAvg(qemuMonitorTestGetAgent(test),
+ &load1m, &load5m, &load15m, true) < 0)
+ return -1;
+
+#define VALIDATE_LOAD(value_, expected_) \
+ do { \
+ if (value_ != expected_) { \
+ virReportError(VIR_ERR_INTERNAL_ERROR, \
+ "Expected " #value_ " '%.11f', got '%.11f'", \
+ expected_, value_); \
+ return -1; \
+ } \
+ } while (0)
+
+ VALIDATE_LOAD(load1m, 0.00390625);
+ VALIDATE_LOAD(load5m, 0.064453125);
+ VALIDATE_LOAD(load15m, 0.03564453125);
+
+ return 0;
+}
+
+
static int
mymain(void)
{
@@ -1392,6 +1444,7 @@ mymain(void)
DO_TEST(Timezone);
DO_TEST(SSHKeys);
DO_TEST(GetDisks);
+ DO_TEST(GetLoadAvg);
DO_TEST(Timeout); /* Timeout should always be called last */
--
2.49.0

View File

@ -1,50 +0,0 @@
From b0282d5149f90b155a38881f92e3263bd23d9878 Mon Sep 17 00:00:00 2001
Message-ID: <b0282d5149f90b155a38881f92e3263bd23d9878.1741876175.git.jdenemar@redhat.com>
From: Pavel Hrdina <phrdina@redhat.com>
Date: Wed, 31 Jan 2024 17:14:28 +0100
Subject: [PATCH] qemu_snapshot: allow reverting to external disk only snapshot
When snapshot is created with disk-only flag it is always external
snapshot without memory state. Historically when there was not support
to revert external snapshots this produced error message.
error: Failed to revert snapshot s1
error: internal error: Invalid target domain state 'disk-snapshot'. Refusing snapshot reversion
Now we can simply consider this as reverting to offline snapshot as the
possible damage to file system is already done at the point of snapshot
creation.
Resolves: https://issues.redhat.com/browse/RHEL-21549
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit 443ae4adec3a94a575ea2acaa112188e721c7dfe)
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
src/qemu/qemu_snapshot.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/qemu/qemu_snapshot.c b/src/qemu/qemu_snapshot.c
index b1f4ebb995..3a8510c69e 100644
--- a/src/qemu/qemu_snapshot.c
+++ b/src/qemu/qemu_snapshot.c
@@ -2884,6 +2884,7 @@ qemuSnapshotRevert(virDomainObj *vm,
case VIR_DOMAIN_SNAPSHOT_SHUTDOWN:
case VIR_DOMAIN_SNAPSHOT_SHUTOFF:
case VIR_DOMAIN_SNAPSHOT_CRASHED:
+ case VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT:
ret = qemuSnapshotRevertInactive(vm, snapshot, snap,
driver, cfg,
&inactiveConfig,
@@ -2895,8 +2896,6 @@ qemuSnapshotRevert(virDomainObj *vm,
_("qemu doesn't support reversion of snapshot taken in PMSUSPENDED state"));
goto endjob;
- case VIR_DOMAIN_SNAPSHOT_DISK_SNAPSHOT:
- /* Rejected earlier as an external snapshot */
case VIR_DOMAIN_SNAPSHOT_NOSTATE:
case VIR_DOMAIN_SNAPSHOT_BLOCKED:
case VIR_DOMAIN_SNAPSHOT_LAST:
--
2.48.1

View File

@ -1,5 +1,5 @@
From 44fc545f45e2e0077fbdc9d45bf8743d115fca35 Mon Sep 17 00:00:00 2001
Message-ID: <44fc545f45e2e0077fbdc9d45bf8743d115fca35.1741876175.git.jdenemar@redhat.com>
From 4aa0ea0a693e06110333a8f851525d0e5a8fcfed Mon Sep 17 00:00:00 2001
Message-ID: <4aa0ea0a693e06110333a8f851525d0e5a8fcfed.1741351378.git.jdenemar@redhat.com>
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Wed, 29 Jan 2025 15:37:46 +0000
Subject: [PATCH] remote: add sysusers file to create 'libvirt' group
@ -17,7 +17,7 @@ Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 18f0160994af80dfac2dcaf46097922e443b283b)
https://issues.redhat.com/browse/RHEL-81749
https://issues.redhat.com/browse/RHEL-81740
Signed-off-by: Andrea Bolognani <abologna@redhat.com>
---

View File

@ -0,0 +1,202 @@
From 4c6d50cb9675f59c8ba2e5bc4fc424cb3b8f5527 Mon Sep 17 00:00:00 2001
Message-ID: <4c6d50cb9675f59c8ba2e5bc4fc424cb3b8f5527.1744361503.git.jdenemar@redhat.com>
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 16 Dec 2024 16:37:52 +0000
Subject: [PATCH] rpc: remove logind support for virNetDaemon
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The virNetDaemon code now only concerns itself with preventing auto
shutdown of the local daemon. Logind is now handled by the new
virInhibitor object, for QEMU, LXC and LibXL. This fixes two notable
bugs
* Running virtual networks would prevent system shutdown
* Loaded ephemeral secrets would prevent system shutdown
Fixes 9e3cc0ff5e81ed2056a6a528893fd2cb5609d70b
Fixes 37800af9a400385801da6d73654249fdb51a93d8
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 8575724aef4f48f3d66cb7beb4c61014992e31eb)
Resolves: https://issues.redhat.com/browse/RHEL-83076
---
src/libxl/libxl_driver.c | 2 +-
src/lxc/lxc_driver.c | 2 +-
src/qemu/qemu_driver.c | 2 +-
src/rpc/virnetdaemon.c | 78 ----------------------------------------
4 files changed, 3 insertions(+), 81 deletions(-)
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index ecd6ea9fa8..2a4f31f93c 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -707,7 +707,7 @@ libxlStateInitialize(bool privileged,
goto error;
libxl_driver->inhibitor = virInhibitorNew(
- VIR_INHIBITOR_WHAT_NONE,
+ VIR_INHIBITOR_WHAT_SHUTDOWN,
_("Libvirt Xen"),
_("Xen virtual machines are running"),
VIR_INHIBITOR_MODE_DELAY,
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 9ee771c62a..72b950ac8a 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1488,7 +1488,7 @@ lxcStateInitialize(bool privileged,
goto cleanup;
lxc_driver->inhibitor = virInhibitorNew(
- VIR_INHIBITOR_WHAT_NONE,
+ VIR_INHIBITOR_WHAT_SHUTDOWN,
_("Libvirt LXC"),
_("LXC containers are running"),
VIR_INHIBITOR_MODE_DELAY,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 5b911d5221..f8f3d2c725 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -673,7 +673,7 @@ qemuStateInitialize(bool privileged,
}
qemu_driver->inhibitor = virInhibitorNew(
- VIR_INHIBITOR_WHAT_NONE,
+ VIR_INHIBITOR_WHAT_SHUTDOWN,
_("Libvirt QEMU"),
_("QEMU/KVM virtual machines are running"),
VIR_INHIBITOR_MODE_DELAY,
diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c
index 9795418126..e4c6261536 100644
--- a/src/rpc/virnetdaemon.c
+++ b/src/rpc/virnetdaemon.c
@@ -31,7 +31,6 @@
#include "virutil.h"
#include "virfile.h"
#include "virnetserver.h"
-#include "virgdbus.h"
#include "virhash.h"
#include "virprocess.h"
#include "virsystemd.h"
@@ -80,7 +79,6 @@ struct _virNetDaemon {
int autoShutdownTimerID;
bool autoShutdownTimerActive;
size_t autoShutdownInhibitions;
- int autoShutdownInhibitFd;
};
@@ -109,7 +107,6 @@ virNetDaemonDispose(void *obj)
virEventRemoveHandle(dmn->sigwatch);
#endif /* !WIN32 */
- VIR_FORCE_CLOSE(dmn->autoShutdownInhibitFd);
g_free(dmn->stateStopThread);
g_clear_pointer(&dmn->servers, g_hash_table_unref);
@@ -150,7 +147,6 @@ virNetDaemonNew(void)
#endif /* !WIN32 */
dmn->privileged = geteuid() == 0;
- dmn->autoShutdownInhibitFd = -1;
virProcessActivateMaxFiles();
@@ -491,66 +487,6 @@ virNetDaemonAutoShutdown(virNetDaemon *dmn,
}
-#ifdef G_OS_UNIX
-/* As per: https://www.freedesktop.org/wiki/Software/systemd/inhibit */
-static void
-virNetDaemonCallInhibit(virNetDaemon *dmn,
- const char *what,
- const char *who,
- const char *why,
- const char *mode)
-{
- g_autoptr(GVariant) reply = NULL;
- g_autoptr(GUnixFDList) replyFD = NULL;
- g_autoptr(GVariant) message = NULL;
- GDBusConnection *systemBus;
- int fd;
- int rc;
-
- VIR_DEBUG("dmn=%p what=%s who=%s why=%s mode=%s",
- dmn, NULLSTR(what), NULLSTR(who), NULLSTR(why), NULLSTR(mode));
-
- if (virSystemdHasLogind() < 0)
- return;
-
- if (!(systemBus = virGDBusGetSystemBus()))
- return;
-
- message = g_variant_new("(ssss)", what, who, why, mode);
-
- rc = virGDBusCallMethodWithFD(systemBus,
- &reply,
- G_VARIANT_TYPE("(h)"),
- &replyFD,
- NULL,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "Inhibit",
- message,
- NULL);
-
- if (rc < 0)
- return;
-
- if (g_unix_fd_list_get_length(replyFD) <= 0)
- return;
-
- fd = g_unix_fd_list_get(replyFD, 0, NULL);
- if (fd < 0)
- return;
-
- if (dmn->autoShutdownInhibitions) {
- dmn->autoShutdownInhibitFd = fd;
- VIR_DEBUG("Got inhibit FD %d", fd);
- } else {
- /* We stopped the last VM since we made the inhibit call */
- VIR_DEBUG("Closing inhibit FD %d", fd);
- VIR_FORCE_CLOSE(fd);
- }
-}
-#endif
-
void
virNetDaemonAddShutdownInhibition(virNetDaemon *dmn)
{
@@ -559,15 +495,6 @@ virNetDaemonAddShutdownInhibition(virNetDaemon *dmn)
dmn->autoShutdownInhibitions++;
VIR_DEBUG("dmn=%p inhibitions=%zu", dmn, dmn->autoShutdownInhibitions);
-
-#ifdef G_OS_UNIX
- if (dmn->autoShutdownInhibitions == 1)
- virNetDaemonCallInhibit(dmn,
- "shutdown",
- _("Libvirt"),
- _("Virtual machines need to be saved"),
- "delay");
-#endif
}
@@ -579,11 +506,6 @@ virNetDaemonRemoveShutdownInhibition(virNetDaemon *dmn)
dmn->autoShutdownInhibitions--;
VIR_DEBUG("dmn=%p inhibitions=%zu", dmn, dmn->autoShutdownInhibitions);
-
- if (dmn->autoShutdownInhibitions == 0) {
- VIR_DEBUG("Closing inhibit FD %d", dmn->autoShutdownInhibitFd);
- VIR_FORCE_CLOSE(dmn->autoShutdownInhibitFd);
- }
}
--
2.49.0

View File

@ -0,0 +1,549 @@
From fd7a63d7b6be85cb60b7157de52d28f5c76bdf42 Mon Sep 17 00:00:00 2001
Message-ID: <fd7a63d7b6be85cb60b7157de52d28f5c76bdf42.1744361503.git.jdenemar@redhat.com>
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 16 Dec 2024 16:28:48 +0000
Subject: [PATCH] src: convert drivers over to new virInhibitor APIs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This initial conversion of the drivers switches them over to use
the virInhibitor APIs in local daemon only mode. Communication to
logind is still handled by the virNetDaemon class logic.
This mostly just replaces upto 3 fields in the driver state
with a single new virInhibitor object, but otherwise should not
change functionality besides replacing atomics with mutex protected
APIs.
The exception is the LXC driver which has been trying to inhibit
shutdown shutdown but silently failing to, since nothing ever
remembered to set the 'inhibitCallback' pointer in the driver
state struct.
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit 48f0b6dfa12563f0006d2de4b0f85599e20f9449)
Resolves: https://issues.redhat.com/browse/RHEL-83076
---
src/libxl/libxl_conf.h | 9 +++----
src/libxl/libxl_domain.c | 6 ++---
src/libxl/libxl_driver.c | 15 +++++++----
src/lxc/lxc_conf.h | 9 +++----
src/lxc/lxc_driver.c | 13 +++++++--
src/lxc/lxc_process.c | 9 +++----
src/network/bridge_driver.c | 20 +++++++-------
src/network/bridge_driver_conf.h | 9 +++----
src/qemu/qemu_conf.h | 9 +++----
src/qemu/qemu_driver.c | 12 ++++++---
src/qemu/qemu_process.c | 9 +++----
src/secret/secret_driver.c | 46 +++++++++++++-------------------
12 files changed, 80 insertions(+), 86 deletions(-)
diff --git a/src/libxl/libxl_conf.h b/src/libxl/libxl_conf.h
index 7087b41079..0edcde079d 100644
--- a/src/libxl/libxl_conf.h
+++ b/src/libxl/libxl_conf.h
@@ -35,6 +35,7 @@
#include "virfirmware.h"
#include "libxl_capabilities.h"
#include "libxl_logger.h"
+#include "virinhibitor.h"
#define LIBXL_DRIVER_EXTERNAL_NAME "Xen"
/*
@@ -117,12 +118,8 @@ struct _libxlDriverPrivate {
/* pid file FD, ensures two copies of the driver can't use the same root */
int lockFD;
- /* Atomic inc/dec only */
- unsigned int nactive;
-
- /* Immutable pointers. Caller must provide locking */
- virStateInhibitCallback inhibitCallback;
- void *inhibitOpaque;
+ /* Immutable pointer, self-locking APIs */
+ virInhibitor *inhibitor;
/* Immutable pointer, self-locking APIs */
virDomainObjList *domains;
diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c
index 711e22b8df..6805160923 100644
--- a/src/libxl/libxl_domain.c
+++ b/src/libxl/libxl_domain.c
@@ -873,8 +873,7 @@ libxlDomainCleanup(libxlDriverPrivate *driver,
priv->deathW = NULL;
}
- if (g_atomic_int_dec_and_test(&driver->nactive) && driver->inhibitCallback)
- driver->inhibitCallback(false, driver->inhibitOpaque);
+ virInhibitorRelease(driver->inhibitor);
/* Release auto-allocated graphics ports */
for (i = 0; i < vm->def->ngraphics; i++) {
@@ -1418,8 +1417,7 @@ libxlDomainStart(libxlDriverPrivate *driver,
return -1;
}
- if (g_atomic_int_add(&driver->nactive, 1) == 0 && driver->inhibitCallback)
- driver->inhibitCallback(true, driver->inhibitOpaque);
+ virInhibitorHold(driver->inhibitor);
event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED,
restore_fd < 0 ?
diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
index b670e697c6..ecd6ea9fa8 100644
--- a/src/libxl/libxl_driver.c
+++ b/src/libxl/libxl_driver.c
@@ -437,8 +437,7 @@ libxlReconnectDomain(virDomainObj *vm,
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
VIR_DOMAIN_RUNNING_UNKNOWN);
- if (g_atomic_int_add(&driver->nactive, 1) == 0 && driver->inhibitCallback)
- driver->inhibitCallback(true, driver->inhibitOpaque);
+ virInhibitorHold(driver->inhibitor);
/* Enable domain death events */
libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, &priv->deathW);
@@ -514,6 +513,7 @@ libxlStateCleanup(void)
virObjectUnref(libxl_driver->domainEventState);
virSysinfoDefFree(libxl_driver->hostsysinfo);
+ virInhibitorFree(libxl_driver->inhibitor);
if (libxl_driver->lockFD != -1)
virPidFileRelease(libxl_driver->config->stateDir, "driver", libxl_driver->lockFD);
@@ -675,9 +675,6 @@ libxlStateInitialize(bool privileged,
return VIR_DRV_STATE_INIT_ERROR;
}
- libxl_driver->inhibitCallback = callback;
- libxl_driver->inhibitOpaque = opaque;
-
/* Allocate bitmap for vnc port reservation */
if (!(libxl_driver->reservedGraphicsPorts =
virPortAllocatorRangeNew(_("VNC"),
@@ -709,6 +706,14 @@ libxlStateInitialize(bool privileged,
if (libxlDriverConfigLoadFile(cfg, driverConf) < 0)
goto error;
+ libxl_driver->inhibitor = virInhibitorNew(
+ VIR_INHIBITOR_WHAT_NONE,
+ _("Libvirt Xen"),
+ _("Xen virtual machines are running"),
+ VIR_INHIBITOR_MODE_DELAY,
+ callback,
+ opaque);
+
/* Register the callbacks providing access to libvirt's event loop */
libxl_osevent_register_hooks(cfg->ctx, &libxl_osevent_callbacks, cfg->ctx);
diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h
index c0967ac63b..73c60c7ebf 100644
--- a/src/lxc/lxc_conf.h
+++ b/src/lxc/lxc_conf.h
@@ -30,6 +30,7 @@
#include "virsysinfo.h"
#include "virclosecallbacks.h"
#include "virhostdev.h"
+#include "virinhibitor.h"
#define LXC_DRIVER_NAME "LXC"
@@ -76,12 +77,8 @@ struct _virLXCDriver {
/* Immutable pointer, lockless APIs */
virSysinfoDef *hostsysinfo;
- /* Atomic inc/dec only */
- unsigned int nactive;
-
- /* Immutable pointers. Caller must provide locking */
- virStateInhibitCallback inhibitCallback;
- void *inhibitOpaque;
+ /* Immutable pointer, self-locking APIs */
+ virInhibitor *inhibitor;
/* Immutable pointer, self-locking APIs */
virDomainObjList *domains;
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 9609d7d10c..9ee771c62a 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1433,8 +1433,8 @@ static virDrvStateInitResult
lxcStateInitialize(bool privileged,
const char *root,
bool monolithic G_GNUC_UNUSED,
- virStateInhibitCallback callback G_GNUC_UNUSED,
- void *opaque G_GNUC_UNUSED)
+ virStateInhibitCallback callback,
+ void *opaque)
{
virLXCDriverConfig *cfg = NULL;
bool autostart = true;
@@ -1487,6 +1487,14 @@ lxcStateInitialize(bool privileged,
if (virLXCLoadDriverConfig(cfg, SYSCONFDIR "/libvirt/lxc.conf") < 0)
goto cleanup;
+ lxc_driver->inhibitor = virInhibitorNew(
+ VIR_INHIBITOR_WHAT_NONE,
+ _("Libvirt LXC"),
+ _("LXC containers are running"),
+ VIR_INHIBITOR_MODE_DELAY,
+ callback,
+ opaque);
+
if (!(lxc_driver->securityManager = lxcSecurityInit(cfg)))
goto cleanup;
@@ -1591,6 +1599,7 @@ static int lxcStateCleanup(void)
virObjectUnref(lxc_driver->caps);
virObjectUnref(lxc_driver->securityManager);
virObjectUnref(lxc_driver->xmlopt);
+ virInhibitorFree(lxc_driver->inhibitor);
if (lxc_driver->lockFD != -1)
virPidFileRelease(lxc_driver->config->stateDir, "driver", lxc_driver->lockFD);
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index cd8bcfc282..c2982244f0 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -203,8 +203,7 @@ static void virLXCProcessCleanup(virLXCDriver *driver,
vm->pid = 0;
vm->def->id = -1;
- if (g_atomic_int_dec_and_test(&driver->nactive) && driver->inhibitCallback)
- driver->inhibitCallback(false, driver->inhibitOpaque);
+ virInhibitorRelease(driver->inhibitor);
virLXCDomainReAttachHostDevices(driver, vm->def);
@@ -1466,8 +1465,7 @@ int virLXCProcessStart(virLXCDriver * driver,
if (virCommandHandshakeNotify(cmd) < 0)
goto cleanup;
- if (g_atomic_int_add(&driver->nactive, 1) == 0 && driver->inhibitCallback)
- driver->inhibitCallback(true, driver->inhibitOpaque);
+ virInhibitorHold(driver->inhibitor);
/* The first synchronization point is when the controller creates CGroups. */
if (lxcContainerWaitForContinue(handshakefds[0]) < 0) {
@@ -1665,8 +1663,7 @@ virLXCProcessReconnectDomain(virDomainObj *vm,
virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
VIR_DOMAIN_RUNNING_UNKNOWN);
- if (g_atomic_int_add(&driver->nactive, 1) == 0 && driver->inhibitCallback)
- driver->inhibitCallback(true, driver->inhibitOpaque);
+ virInhibitorHold(driver->inhibitor);
if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
goto error;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index e700a614a9..ce793c12ef 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -504,8 +504,7 @@ networkUpdateState(virNetworkObj *obj,
if (virNetworkObjIsActive(obj)) {
virNetworkObjPortForEach(obj, networkUpdatePort, obj);
- if (g_atomic_int_add(&driver->nactive, 1) == 0 && driver->inhibitCallback)
- driver->inhibitCallback(true, driver->inhibitOpaque);
+ virInhibitorHold(driver->inhibitor);
}
/* Try and read dnsmasq pids of both active and inactive networks, just in
@@ -644,9 +643,6 @@ networkStateInitialize(bool privileged,
goto error;
}
- network_driver->inhibitCallback = callback;
- network_driver->inhibitOpaque = opaque;
-
network_driver->privileged = privileged;
if (!(network_driver->xmlopt = networkDnsmasqCreateXMLConf()))
@@ -655,6 +651,14 @@ networkStateInitialize(bool privileged,
if (!(network_driver->config = cfg = virNetworkDriverConfigNew(privileged)))
goto error;
+ network_driver->inhibitor = virInhibitorNew(
+ VIR_INHIBITOR_WHAT_NONE,
+ _("Libvirt Network"),
+ _("Virtual networks are active"),
+ VIR_INHIBITOR_MODE_DELAY,
+ callback,
+ opaque);
+
if ((network_driver->lockFD =
virPidFileAcquire(cfg->stateDir, "driver", getpid())) < 0)
goto error;
@@ -2432,8 +2436,7 @@ networkStartNetwork(virNetworkDriverState *driver,
obj, network_driver->xmlopt) < 0)
goto cleanup;
- if (g_atomic_int_add(&driver->nactive, 1) == 0 && driver->inhibitCallback)
- driver->inhibitCallback(true, driver->inhibitOpaque);
+ virInhibitorHold(driver->inhibitor);
virNetworkObjSetActive(obj, true);
VIR_INFO("Network '%s' started up", def->name);
@@ -2509,8 +2512,7 @@ networkShutdownNetwork(virNetworkDriverState *driver,
virNetworkObjSetActive(obj, false);
- if (g_atomic_int_dec_and_test(&driver->nactive) && driver->inhibitCallback)
- driver->inhibitCallback(false, driver->inhibitOpaque);
+ virInhibitorRelease(driver->inhibitor);
virNetworkObjUnsetDefTransient(obj);
return ret;
diff --git a/src/network/bridge_driver_conf.h b/src/network/bridge_driver_conf.h
index 1beed01efb..2a2e2bc16d 100644
--- a/src/network/bridge_driver_conf.h
+++ b/src/network/bridge_driver_conf.h
@@ -27,6 +27,7 @@
#include "virnetworkobj.h"
#include "object_event.h"
#include "virfirewall.h"
+#include "virinhibitor.h"
typedef struct _virNetworkDriverConfig virNetworkDriverConfig;
struct _virNetworkDriverConfig {
@@ -49,12 +50,8 @@ typedef struct _virNetworkDriverState virNetworkDriverState;
struct _virNetworkDriverState {
virMutex lock;
- /* Atomic inc/dec only */
- unsigned int nactive;
-
- /* Immutable pointers. Caller must provide locking */
- virStateInhibitCallback inhibitCallback;
- void *inhibitOpaque;
+ /* Immutable pointer, self-locking APIs */
+ virInhibitor *inhibitor;
/* Read-only */
bool privileged;
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 23a900193e..42cdb6f883 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -42,6 +42,7 @@
#include "virfile.h"
#include "virfilecache.h"
#include "virfirmware.h"
+#include "virinhibitor.h"
#define QEMU_DRIVER_NAME "QEMU"
@@ -257,16 +258,12 @@ struct _virQEMUDriver {
/* Atomic increment only */
int lastvmid;
- /* Atomic inc/dec only */
- unsigned int nactive;
-
/* Immutable values */
bool privileged;
char *embeddedRoot;
- /* Immutable pointers. Caller must provide locking */
- virStateInhibitCallback inhibitCallback;
- void *inhibitOpaque;
+ /* Immutable pointer, self-locking APIs */
+ virInhibitor *inhibitor;
/* Immutable pointer, self-locking APIs */
virDomainObjList *domains;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 379f9fb74f..5b911d5221 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -573,9 +573,6 @@ qemuStateInitialize(bool privileged,
return VIR_DRV_STATE_INIT_ERROR;
}
- qemu_driver->inhibitCallback = callback;
- qemu_driver->inhibitOpaque = opaque;
-
qemu_driver->privileged = privileged;
qemu_driver->hostarch = virArchFromHost();
if (root != NULL)
@@ -675,6 +672,14 @@ qemuStateInitialize(bool privileged,
goto error;
}
+ qemu_driver->inhibitor = virInhibitorNew(
+ VIR_INHIBITOR_WHAT_NONE,
+ _("Libvirt QEMU"),
+ _("QEMU/KVM virtual machines are running"),
+ VIR_INHIBITOR_MODE_DELAY,
+ callback,
+ opaque);
+
if ((qemu_driver->lockFD =
virPidFileAcquire(cfg->stateDir, "driver", getpid())) < 0)
goto error;
@@ -1065,6 +1070,7 @@ qemuStateCleanup(void)
ebtablesContextFree(qemu_driver->ebtables);
virObjectUnref(qemu_driver->domains);
virObjectUnref(qemu_driver->nbdkitCapsCache);
+ virInhibitorFree(qemu_driver->inhibitor);
if (qemu_driver->lockFD != -1)
virPidFileRelease(qemu_driver->config->stateDir, "driver", qemu_driver->lockFD);
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 7285fd5ce9..722e982b9e 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5853,8 +5853,7 @@ qemuProcessInit(virQEMUDriver *driver,
qemuDomainSetFakeReboot(vm, false);
virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_STARTING_UP);
- if (g_atomic_int_add(&driver->nactive, 1) == 0 && driver->inhibitCallback)
- driver->inhibitCallback(true, driver->inhibitOpaque);
+ virInhibitorHold(driver->inhibitor);
/* Run an early hook to set-up missing devices */
if (qemuProcessStartHook(driver, vm,
@@ -8885,8 +8884,7 @@ void qemuProcessStop(virQEMUDriver *driver,
if (priv->eventThread)
g_object_unref(g_steal_pointer(&priv->eventThread));
- if (g_atomic_int_dec_and_test(&driver->nactive) && driver->inhibitCallback)
- driver->inhibitCallback(false, driver->inhibitOpaque);
+ virInhibitorRelease(driver->inhibitor);
/* Clear network bandwidth */
virDomainClearNetBandwidth(vm->def);
@@ -9644,8 +9642,7 @@ qemuProcessReconnect(void *opaque)
goto error;
}
- if (g_atomic_int_add(&driver->nactive, 1) == 0 && driver->inhibitCallback)
- driver->inhibitCallback(true, driver->inhibitOpaque);
+ virInhibitorHold(driver->inhibitor);
cleanup:
if (jobStarted)
diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c
index a2d6b879d0..04c3ca49f1 100644
--- a/src/secret/secret_driver.c
+++ b/src/secret/secret_driver.c
@@ -41,6 +41,7 @@
#include "viraccessapicheck.h"
#include "secret_event.h"
#include "virutil.h"
+#include "virinhibitor.h"
#define VIR_FROM_THIS VIR_FROM_SECRET
@@ -67,9 +68,8 @@ struct _virSecretDriverState {
/* Immutable pointer, self-locking APIs */
virObjectEventState *secretEventState;
- /* Immutable pointers. Caller must provide locking */
- virStateInhibitCallback inhibitCallback;
- void *inhibitOpaque;
+ /* Immutable pointer, self-locking APIs */
+ virInhibitor *inhibitor;
};
static virSecretDriverState *driver;
@@ -90,23 +90,6 @@ secretObjFromSecret(virSecretPtr secret)
}
-static bool
-secretNumOfEphemeralSecretsHelper(virConnectPtr conn G_GNUC_UNUSED,
- virSecretDef *def)
-{
- return def->isephemeral;
-}
-
-
-static int
-secretNumOfEphemeralSecrets(void)
-{
- return virSecretObjListNumOfSecrets(driver->secrets,
- secretNumOfEphemeralSecretsHelper,
- NULL);
-}
-
-
/* Driver functions */
static int
@@ -271,6 +254,10 @@ secretDefineXML(virConnectPtr conn,
objDef->uuid,
objDef->usage_type,
objDef->usage_id);
+
+ if (objDef->isephemeral)
+ virInhibitorHold(driver->inhibitor);
+
goto cleanup;
restore_backup:
@@ -288,8 +275,6 @@ secretDefineXML(virConnectPtr conn,
virSecretDefFree(def);
virSecretObjEndAPI(&obj);
- if (secretNumOfEphemeralSecrets() > 0)
- driver->inhibitCallback(true, driver->inhibitOpaque);
virObjectEventStateQueue(driver->secretEventState, event);
@@ -440,6 +425,9 @@ secretUndefine(virSecretPtr secret)
VIR_SECRET_EVENT_UNDEFINED,
0);
+ if (def->isephemeral)
+ virInhibitorRelease(driver->inhibitor);
+
virSecretObjDeleteData(obj);
virSecretObjListRemove(driver->secrets, obj);
@@ -450,9 +438,6 @@ secretUndefine(virSecretPtr secret)
cleanup:
virSecretObjEndAPI(&obj);
- if (secretNumOfEphemeralSecrets() == 0)
- driver->inhibitCallback(false, driver->inhibitOpaque);
-
virObjectEventStateQueue(driver->secretEventState, event);
return ret;
@@ -469,6 +454,7 @@ secretStateCleanupLocked(void)
VIR_FREE(driver->configDir);
virObjectUnref(driver->secretEventState);
+ virInhibitorFree(driver->inhibitor);
if (driver->lockFD != -1)
virPidFileRelease(driver->stateDir, "driver", driver->lockFD);
@@ -502,8 +488,6 @@ secretStateInitialize(bool privileged,
driver->lockFD = -1;
driver->secretEventState = virObjectEventStateNew();
driver->privileged = privileged;
- driver->inhibitCallback = callback;
- driver->inhibitOpaque = opaque;
if (root) {
driver->embeddedRoot = g_strdup(root);
@@ -535,6 +519,14 @@ secretStateInitialize(bool privileged,
goto error;
}
+ driver->inhibitor = virInhibitorNew(
+ VIR_INHIBITOR_WHAT_NONE,
+ _("Libvirt Secret"),
+ _("Ephemeral secrets are loaded"),
+ VIR_INHIBITOR_MODE_DELAY,
+ callback,
+ opaque);
+
if ((driver->lockFD =
virPidFileAcquire(driver->stateDir, "driver", getpid())) < 0)
goto error;
--
2.49.0

View File

@ -0,0 +1,52 @@
From 05aa05e3b17000b2a886dddb2abdb183bd6d4295 Mon Sep 17 00:00:00 2001
Message-ID: <05aa05e3b17000b2a886dddb2abdb183bd6d4295.1744361503.git.jdenemar@redhat.com>
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Wed, 8 Jan 2025 17:37:03 +0000
Subject: [PATCH] util: don't attempt to acquire logind inhibitor if not
requested
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When VIR_INHIBITOR_WHAT_NONE is passed to virInhibitorNew, it is
an indication that daemon shutdown should be inhibited, but no
OS level inhibitors acquired. This is done by the virtnetworkd
daemon, for example, to prevent shutdown while running virtual
machines are present, without blocking / delaying OS shutdown.
Unfortunately the code forgot to skip the DBus call in this case,
resulting in errors being logged.
Reviewed-by: Laine Stump <laine@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit caa10431cdd1aa476637ff721f1947c4e0b53da1)
Resolves: https://issues.redhat.com/browse/RHEL-83076
---
src/util/virinhibitor.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/util/virinhibitor.c b/src/util/virinhibitor.c
index 647bdc9fbb..a95021de5a 100644
--- a/src/util/virinhibitor.c
+++ b/src/util/virinhibitor.c
@@ -152,7 +152,7 @@ virInhibitor *virInhibitorNew(virInhibitorWhat what,
virInhibitor *inhibitor = g_new0(virInhibitor, 1);
inhibitor->fd = -1;
- inhibitor->what = virInhibitorWhatFormat(what);
+ inhibitor->what = what ? virInhibitorWhatFormat(what) : NULL;
inhibitor->who = g_strdup(who);
inhibitor->why = g_strdup(why);
inhibitor->mode = virInhibitorModeTypeToString(mode);
@@ -171,7 +171,8 @@ void virInhibitorHold(virInhibitor *inhibitor)
inhibitor->action(true, inhibitor->actionData);
}
#ifdef G_OS_UNIX
- if (virInhibitorAcquire(
+ if (inhibitor->what &&
+ virInhibitorAcquire(
inhibitor->what, inhibitor->who, inhibitor->why,
inhibitor->mode, &inhibitor->fd) < 0) {
VIR_ERROR(_("Failed to acquire inhibitor: %1$s"),
--
2.49.0

View File

@ -0,0 +1,46 @@
From 10b60d5a7910c243249e296306c7dc9e87e79f71 Mon Sep 17 00:00:00 2001
Message-ID: <10b60d5a7910c243249e296306c7dc9e87e79f71.1744361503.git.jdenemar@redhat.com>
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Tue, 7 Jan 2025 15:21:18 +0000
Subject: [PATCH] util: fix off-by-1 in inhibitor constants
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The inhibitor constant values were off-by-1, so when converted into
string format, we picked the wrong names
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit fc3a60d9d7b29283a0b2d57bb06d15fb597a5003)
Resolves: https://issues.redhat.com/browse/RHEL-83076
---
src/util/virinhibitor.h | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/util/virinhibitor.h b/src/util/virinhibitor.h
index 0a1c445d41..49cf32fbeb 100644
--- a/src/util/virinhibitor.h
+++ b/src/util/virinhibitor.h
@@ -26,13 +26,13 @@ typedef struct _virInhibitor virInhibitor;
typedef enum {
VIR_INHIBITOR_WHAT_NONE = 0,
- VIR_INHIBITOR_WHAT_SLEEP = (1 << 1),
- VIR_INHIBITOR_WHAT_SHUTDOWN = (1 << 2),
- VIR_INHIBITOR_WHAT_IDLE = (1 << 3),
- VIR_INHIBITOR_WHAT_POWER_KEY = (1 << 4),
- VIR_INHIBITOR_WHAT_SUSPEND_KEY = (1 << 5),
- VIR_INHIBITOR_WHAT_HIBERNATE_KEY = (1 << 6),
- VIR_INHIBITOR_WHAT_LID_SWITCH = (1 << 7),
+ VIR_INHIBITOR_WHAT_SLEEP = (1 << 0),
+ VIR_INHIBITOR_WHAT_SHUTDOWN = (1 << 1),
+ VIR_INHIBITOR_WHAT_IDLE = (1 << 2),
+ VIR_INHIBITOR_WHAT_POWER_KEY = (1 << 3),
+ VIR_INHIBITOR_WHAT_SUSPEND_KEY = (1 << 4),
+ VIR_INHIBITOR_WHAT_HIBERNATE_KEY = (1 << 5),
+ VIR_INHIBITOR_WHAT_LID_SWITCH = (1 << 6),
} virInhibitorWhat;
typedef enum {
--
2.49.0

View File

@ -0,0 +1,375 @@
From 9f2c4a2117eec85d5146e7dedd628585bb55df01 Mon Sep 17 00:00:00 2001
Message-ID: <9f2c4a2117eec85d5146e7dedd628585bb55df01.1744361502.git.jdenemar@redhat.com>
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
Date: Mon, 16 Dec 2024 15:19:34 +0000
Subject: [PATCH] util: introduce object for holding a system inhibitor lock
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The system inhibitor locks are currently handled by code in the
virNetDaemon class. The driver code invokes a callback provided
by the daemon when it wants to start or end inhibition.
When the first inhibition is started, the daemon will call out
to logind to apply it system wide.
This has many flaws
* A single message is registered with logind regardless of
what driver holds the inhibition
* An inhibition of daemon shutdown can't be acquired
without also inhibiting system shutdown
* Config of the inhibitions cannot be tailored by the
driver
The new virInhibitor object addresses these:
* The object directly manages an inhibition with logind
privately to the driver, enabling custom messages to
be set.
* It is possible to acquire an inhibition locally to the
daemon without forwarding it to logind.
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
(cherry picked from commit d2e5aa4f4e1501149c9e3095d38ebc04c9a4ba31)
Resolves: https://issues.redhat.com/browse/RHEL-83076
---
po/POTFILES | 1 +
src/libvirt_private.syms | 7 ++
src/util/meson.build | 1 +
src/util/virinhibitor.c | 214 +++++++++++++++++++++++++++++++++++++++
src/util/virinhibitor.h | 58 +++++++++++
5 files changed, 281 insertions(+)
create mode 100644 src/util/virinhibitor.c
create mode 100644 src/util/virinhibitor.h
diff --git a/po/POTFILES b/po/POTFILES
index 3514aa3dca..c71e439fe3 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -293,6 +293,7 @@ src/util/virhostcpu.c
src/util/virhostmem.c
src/util/virhostuptime.c
src/util/viridentity.c
+src/util/virinhibitor.c
src/util/virinitctl.c
src/util/viriscsi.c
src/util/virjson.c
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 7d404fdbf5..727ab52cfe 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2605,6 +2605,13 @@ virIdentitySetUserName;
virIdentitySetX509DName;
+# util/virinhibitor.h
+virInhibitorFree;
+virInhibitorHold;
+virInhibitorNew;
+virInhibitorRelease;
+
+
# util/virinitctl.h
virInitctlFifos;
virInitctlSetRunLevel;
diff --git a/src/util/meson.build b/src/util/meson.build
index 30f71b0227..69ef49139a 100644
--- a/src/util/meson.build
+++ b/src/util/meson.build
@@ -45,6 +45,7 @@ util_sources = [
'virhostmem.c',
'virhostuptime.c',
'viridentity.c',
+ 'virinhibitor.c',
'virinitctl.c',
'viriscsi.c',
'virjson.c',
diff --git a/src/util/virinhibitor.c b/src/util/virinhibitor.c
new file mode 100644
index 0000000000..647bdc9fbb
--- /dev/null
+++ b/src/util/virinhibitor.c
@@ -0,0 +1,214 @@
+/*
+ * virinhibitor.c: helper APIs for inhibiting host actions
+ *
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "virinhibitor.h"
+#include "virgdbus.h"
+#include "virsystemd.h"
+#include "virfile.h"
+#include "virlog.h"
+#include "virenum.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("util.inhibitor");
+
+struct _virInhibitor {
+ GMutex lock;
+ size_t count;
+ int fd;
+
+ char *what;
+ char *who;
+ char *why;
+ const char *mode;
+
+ virInhibitorAction action;
+ void *actionData;
+};
+
+VIR_ENUM_DECL(virInhibitorMode);
+
+VIR_ENUM_IMPL(virInhibitorMode,
+ VIR_INHIBITOR_MODE_LAST,
+ "block", "delay");
+
+#ifdef G_OS_UNIX
+/* As per: https://www.freedesktop.org/wiki/Software/systemd/inhibit */
+static int
+virInhibitorAcquire(const char *what,
+ const char *who,
+ const char *why,
+ const char *mode,
+ int *inhibitorFD)
+{
+ g_autoptr(GVariant) reply = NULL;
+ g_autoptr(GUnixFDList) replyFD = NULL;
+ g_autoptr(GVariant) message = NULL;
+ GDBusConnection *systemBus;
+ int fd;
+ int rc;
+
+ VIR_DEBUG("what=%s who=%s why=%s mode=%s",
+ NULLSTR(what), NULLSTR(who), NULLSTR(why), NULLSTR(mode));
+
+ if (!(systemBus = virGDBusGetSystemBus())) {
+ VIR_DEBUG("system dbus not available, skipping system inhibitor");
+ return 0;
+ }
+
+ if (virSystemdHasLogind() < 0) {
+ VIR_DEBUG("logind not available, skipping system inhibitor");
+ return 0;
+ }
+
+ message = g_variant_new("(ssss)", what, who, why, mode);
+
+ rc = virGDBusCallMethodWithFD(systemBus,
+ &reply,
+ G_VARIANT_TYPE("(h)"),
+ &replyFD,
+ NULL,
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ "Inhibit",
+ message,
+ NULL);
+
+ if (rc < 0)
+ return -1;
+
+ if (g_unix_fd_list_get_length(replyFD) <= 0) {
+ VIR_DEBUG("Missing inhibitor FD in logind reply");
+ return -1;
+ }
+
+ fd = g_unix_fd_list_get(replyFD, 0, NULL);
+ if (fd < 0) {
+ VIR_DEBUG("Unable to get inhibitor FD from logind reply");
+ return -1;
+ }
+
+ *inhibitorFD = fd;
+ VIR_DEBUG("Got inhibitor FD %d", fd);
+ return 0;
+}
+#endif
+
+
+static char *
+virInhibitorWhatFormat(virInhibitorWhat what)
+{
+ const char *whatstr[] = {
+ "sleep",
+ "shutdown",
+ "idle",
+ "handle-power-key",
+ "handle-suspend-key",
+ "handle-hibernate-key",
+ "handle-lid-switch",
+ };
+ GString *str = g_string_new("");
+ size_t i;
+
+ for (i = 0; i < G_N_ELEMENTS(whatstr); i++) {
+ if (what & (1 << i)) {
+ if (str->len)
+ g_string_append(str, ":");
+ g_string_append(str, whatstr[i]);
+ }
+ }
+
+ return g_string_free(str, FALSE);
+}
+
+
+virInhibitor *virInhibitorNew(virInhibitorWhat what,
+ const char *who,
+ const char *why,
+ virInhibitorMode mode,
+ virInhibitorAction action,
+ void *actionData)
+{
+ virInhibitor *inhibitor = g_new0(virInhibitor, 1);
+
+ inhibitor->fd = -1;
+ inhibitor->what = virInhibitorWhatFormat(what);
+ inhibitor->who = g_strdup(who);
+ inhibitor->why = g_strdup(why);
+ inhibitor->mode = virInhibitorModeTypeToString(mode);
+ inhibitor->action = action;
+ inhibitor->actionData = actionData;
+
+ return inhibitor;
+}
+
+void virInhibitorHold(virInhibitor *inhibitor)
+{
+ g_mutex_lock(&inhibitor->lock);
+
+ if (inhibitor->count == 0) {
+ if (inhibitor->action) {
+ inhibitor->action(true, inhibitor->actionData);
+ }
+#ifdef G_OS_UNIX
+ if (virInhibitorAcquire(
+ inhibitor->what, inhibitor->who, inhibitor->why,
+ inhibitor->mode, &inhibitor->fd) < 0) {
+ VIR_ERROR(_("Failed to acquire inhibitor: %1$s"),
+ virGetLastErrorMessage());
+ virResetLastError();
+ }
+#else
+ VIR_DEBUG("No inhibitor implementation on non-UNIX platforms");
+#endif
+ }
+ inhibitor->count++;
+ g_mutex_unlock(&inhibitor->lock);
+}
+
+
+void virInhibitorRelease(virInhibitor *inhibitor)
+{
+ g_mutex_lock(&inhibitor->lock);
+ inhibitor->count--;
+ if (inhibitor->count == 0) {
+ VIR_FORCE_CLOSE(inhibitor->fd);
+ if (inhibitor->action) {
+ inhibitor->action(false, inhibitor->actionData);
+ }
+ }
+ g_mutex_unlock(&inhibitor->lock);
+}
+
+
+void virInhibitorFree(virInhibitor *inhibitor)
+{
+ if (!inhibitor)
+ return;
+
+ g_free(inhibitor->what);
+ g_free(inhibitor->who);
+ g_free(inhibitor->why);
+ VIR_FORCE_CLOSE(inhibitor->fd);
+ g_free(inhibitor);
+}
diff --git a/src/util/virinhibitor.h b/src/util/virinhibitor.h
new file mode 100644
index 0000000000..0a1c445d41
--- /dev/null
+++ b/src/util/virinhibitor.h
@@ -0,0 +1,58 @@
+/*
+ * virinhibitor.h: helper APIs for inhibiting host actions
+ *
+ * Copyright (C) 2024 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "internal.h"
+
+typedef struct _virInhibitor virInhibitor;
+
+typedef enum {
+ VIR_INHIBITOR_WHAT_NONE = 0,
+ VIR_INHIBITOR_WHAT_SLEEP = (1 << 1),
+ VIR_INHIBITOR_WHAT_SHUTDOWN = (1 << 2),
+ VIR_INHIBITOR_WHAT_IDLE = (1 << 3),
+ VIR_INHIBITOR_WHAT_POWER_KEY = (1 << 4),
+ VIR_INHIBITOR_WHAT_SUSPEND_KEY = (1 << 5),
+ VIR_INHIBITOR_WHAT_HIBERNATE_KEY = (1 << 6),
+ VIR_INHIBITOR_WHAT_LID_SWITCH = (1 << 7),
+} virInhibitorWhat;
+
+typedef enum {
+ VIR_INHIBITOR_MODE_BLOCK,
+ VIR_INHIBITOR_MODE_DELAY,
+
+ VIR_INHIBITOR_MODE_LAST
+} virInhibitorMode;
+
+typedef void (*virInhibitorAction)(bool inhibited,
+ void *opaque);
+
+virInhibitor *virInhibitorNew(virInhibitorWhat what,
+ const char *who,
+ const char *why,
+ virInhibitorMode mode,
+ virInhibitorAction action,
+ void *actionData);
+
+void virInhibitorHold(virInhibitor *inhibitor);
+void virInhibitorRelease(virInhibitor *inhibitor);
+
+void virInhibitorFree(virInhibitor *inhibitor);
--
2.49.0

View File

@ -0,0 +1,71 @@
From f2b3e5bf2ae55e028125e545a1fe9565e2bc86f9 Mon Sep 17 00:00:00 2001
Message-ID: <f2b3e5bf2ae55e028125e545a1fe9565e2bc86f9.1745925135.git.jdenemar@redhat.com>
From: Martin Kletzander <mkletzan@redhat.com>
Date: Tue, 25 Feb 2025 15:22:35 +0100
Subject: [PATCH] virsh: Add support for VIR_DOMAIN_GUEST_INFO_LOAD
Resolves: https://issues.redhat.com/browse/RHEL-71883
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
(cherry picked from commit 71e75ce09203aa2489803426ae368d1693ee925b)
https://issues.redhat.com/browse/RHEL-88449
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
---
docs/manpages/virsh.rst | 8 +++++++-
tools/virsh-domain.c | 6 ++++++
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index 2e525d3fac..77798af7d3 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -2912,7 +2912,7 @@ Success is always reported in this case.
You can limit the types of information that are returned by specifying one or
more flags. Available information types flags are *--user*, *--os*,
-*--timezone*, *--hostname*, *--filesystem*, *--disk* and *--interface*.
+*--timezone*, *--hostname*, *--filesystem*, *--disk*, *--interface* and *--load*.
If an explicitly requested information type is not supported by the guest agent
at that point, the processes will provide an exit code of 1.
@@ -2991,6 +2991,12 @@ returned:
* ``if.<num>.addr.<num1>.addr`` - the IP address of addr <num1>
* ``if.<num>.addr.<num1>.prefix`` - the prefix of IP address of addr <num1>
+*--load* returns:
+* ``load.1m`` - average load in guest for last 1 minute
+* ``load.5m`` - average load in guest for last 5 minutes
+* ``load.15m`` - average load in guest for last 15 minutes
+
+
guestvcpus
----------
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index e4923284af..0f30a65fd9 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -13066,6 +13066,10 @@ static const vshCmdOptDef opts_guestinfo[] = {
.type = VSH_OT_BOOL,
.help = N_("report interface information"),
},
+ {.name = "load",
+ .type = VSH_OT_BOOL,
+ .help = N_("report load averages information"),
+ },
{.name = NULL}
};
@@ -13093,6 +13097,8 @@ cmdGuestInfo(vshControl *ctl, const vshCmd *cmd)
types |= VIR_DOMAIN_GUEST_INFO_DISKS;
if (vshCommandOptBool(cmd, "interface"))
types |= VIR_DOMAIN_GUEST_INFO_INTERFACES;
+ if (vshCommandOptBool(cmd, "load"))
+ types |= VIR_DOMAIN_GUEST_INFO_LOAD;
if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
return false;
--
2.49.0

View File

@ -293,7 +293,7 @@
Summary: Library providing a simple virtualization API
Name: libvirt
Version: 10.10.0
Release: 7.1%{?dist}%{?extra_release}.alma.1
Release: 7.3%{?dist}%{?extra_release}.alma.1
License: GPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND OFL-1.1
URL: https://libvirt.org/
@ -385,6 +385,22 @@ Patch81: libvirt-docs-improve-type-user-docs-to-higlight-differences-between-SLI
Patch82: libvirt-docs-document-using-passt-backend-with-interface-type-vhostuser.patch
Patch83: libvirt-utils-Canonicalize-paths-before-comparing-them.patch
Patch84: libvirt-remote-add-sysusers-file-to-create-libvirt-group.patch
Patch85: libvirt-util-introduce-object-for-holding-a-system-inhibitor-lock.patch
Patch86: libvirt-src-convert-drivers-over-to-new-virInhibitor-APIs.patch
Patch87: libvirt-rpc-remove-logind-support-for-virNetDaemon.patch
Patch88: libvirt-util-fix-off-by-1-in-inhibitor-constants.patch
Patch89: libvirt-util-don-t-attempt-to-acquire-logind-inhibitor-if-not-requested.patch
Patch90: libvirt-network-Free-inhibitor-in-networkStateCleanup.patch
Patch91: libvirt-conf-parse-interface-source-dev-for-all-interface-types-with-backend-type-passt.patch
Patch92: libvirt-qemu-remove-nonsensical-sanity-check-in-processNetdevStreamDisconnectedEvent.patch
Patch93: libvirt-qemu-make-processNetDevStreamDisconnectedEvent-reusable.patch
Patch94: libvirt-qemu-respond-to-NETDEV_VHOST_USER_DISCONNECTED-event.patch
Patch95: libvirt-qemu-put-vhost-user-code-that-s-special-for-passt-in-a-helper-function.patch
Patch96: libvirt-qemu-make-passt-vhostuser-reconnect-behave-identically-to-passt-user.patch
Patch97: libvirt-Add-load-average-information-type-into-virDomainGetGuestInfo.patch
Patch98: libvirt-qemu_agent-Add-qemuAgentGetLoadAvg.patch
Patch99: libvirt-qemu-Add-support-for-VIR_DOMAIN_GUEST_INFO_LOAD.patch
Patch100: libvirt-virsh-Add-support-for-VIR_DOMAIN_GUEST_INFO_LOAD.patch
Requires: libvirt-daemon = %{version}-%{release}
@ -2710,11 +2726,31 @@ exit 0
%endif
%changelog
* Tue May 13 2025 Eduard Abdullin <eabdullin@almalinux.org> - 10.10.0-7.1.alma.1
* Fri May 23 2025 Eduard Abdullin <eabdullin@almalinux.org> - 10.10.0-7.3.alma.1
- Enable building for ppc64le
* Thu Mar 13 2025 Jiri Denemark <jdenemar@redhat.com> - 10.10.0-7.1
- remote: add sysusers file to create 'libvirt' group (RHEL-81749)
* Tue Apr 29 2025 Jiri Denemark <jdenemar@redhat.com> - 10.10.0-7.3.el9_6
- Add load average information type into virDomainGetGuestInfo (RHEL-88449)
- qemu_agent: Add qemuAgentGetLoadAvg() (RHEL-88449)
- qemu: Add support for VIR_DOMAIN_GUEST_INFO_LOAD (RHEL-88449)
- virsh: Add support for VIR_DOMAIN_GUEST_INFO_LOAD (RHEL-88449)
* Fri Apr 11 2025 Jiri Denemark <jdenemar@redhat.com> - 10.10.0-7.2.el9_6
- util: introduce object for holding a system inhibitor lock (RHEL-83076)
- src: convert drivers over to new virInhibitor APIs (RHEL-83076)
- rpc: remove logind support for virNetDaemon (RHEL-83076)
- util: fix off-by-1 in inhibitor constants (RHEL-83076)
- util: don't attempt to acquire logind inhibitor if not requested (RHEL-83076)
- network: Free inhibitor in networkStateCleanup() (RHEL-83076)
- conf: parse interface/source/@dev for all interface types (with backend type='passt') (RHEL-84689)
- qemu: remove nonsensical sanity check in processNetdevStreamDisconnectedEvent() (RHEL-84782)
- qemu: make processNetDevStreamDisconnectedEvent() reusable (RHEL-84782)
- qemu: respond to NETDEV_VHOST_USER_DISCONNECTED event (RHEL-84782)
- qemu: put vhost-user code that's special for passt in a helper function (RHEL-84782)
- qemu: make passt+vhostuser reconnect behave identically to passt+user (RHEL-84782)
* Fri Mar 7 2025 Jiri Denemark <jdenemar@redhat.com> - 10.10.0-7.1.el9_6
- remote: add sysusers file to create 'libvirt' group (RHEL-81740)
* Mon Feb 17 2025 Jiri Denemark <jdenemar@redhat.com> - 10.10.0-7
- qemu_migration: Refactor qemuMigrationSrcRestoreDomainState (RHEL-79168)