diff --git a/SOURCES/libvirt-Handle-copying-bitmaps-to-larger-data-buffers.patch b/SOURCES/libvirt-Handle-copying-bitmaps-to-larger-data-buffers.patch new file mode 100644 index 0000000..8a5f286 --- /dev/null +++ b/SOURCES/libvirt-Handle-copying-bitmaps-to-larger-data-buffers.patch @@ -0,0 +1,54 @@ +From 806c01fea005e3887ad74efa3ecbab8294c0ddca Mon Sep 17 00:00:00 2001 +Message-Id: <806c01fea005e3887ad74efa3ecbab8294c0ddca@dist-git> +From: "Allen, John" +Date: Fri, 26 Apr 2019 15:12:01 +0200 +Subject: [PATCH] Handle copying bitmaps to larger data buffers + +If a bitmap of a shorter length than the data buffer is passed to +virBitmapToDataBuf, it will read off the end of the bitmap and copy junk +into the returned buffer. Add a check to only copy the length of the +bitmap to the buffer. + +The problem can be observed after setting a vcpu affinity using the vcpupin +command on a system with a large number of cores: + # virsh vcpupin example_domain 0 0 + # virsh vcpupin example_domain 0 + VCPU CPU Affinity + --------------------------- + 0 0,192,197-198,202 + +Signed-off-by: John Allen +(cherry picked from commit 51f9f80d350e633adf479c6a9b3c55f82ca9cbd4) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1703159 + +Signed-off-by: Pavel Hrdina +Message-Id: <8c72d73f39288e0a38d72481e771d1df53d593a3.1556284274.git.phrdina@redhat.com> +Reviewed-by: Andrea Bolognani +--- + src/util/virbitmap.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c +index 0cc5292d8c..0bc0d068bb 100644 +--- a/src/util/virbitmap.c ++++ b/src/util/virbitmap.c +@@ -832,11 +832,15 @@ virBitmapToDataBuf(virBitmapPtr bitmap, + unsigned char *bytes, + size_t len) + { ++ size_t nbytes = bitmap->map_len * (VIR_BITMAP_BITS_PER_UNIT / CHAR_BIT); + unsigned long *l; + size_t i, j; + + memset(bytes, 0, len); + ++ /* If bitmap and buffer differ in size, only fill to the smaller length */ ++ len = MIN(len, nbytes); ++ + /* htole64 is not provided by gnulib, so we do the conversion by hand */ + l = bitmap->map; + for (i = j = 0; i < len; i++, j++) { +-- +2.21.0 + diff --git a/SOURCES/libvirt-RHEL-conf-storage-Fix-a-memory-leak-in-virStoragePoolDefParseSource.patch b/SOURCES/libvirt-RHEL-conf-storage-Fix-a-memory-leak-in-virStoragePoolDefParseSource.patch new file mode 100644 index 0000000..d4580a0 --- /dev/null +++ b/SOURCES/libvirt-RHEL-conf-storage-Fix-a-memory-leak-in-virStoragePoolDefParseSource.patch @@ -0,0 +1,41 @@ +From b5f39d1ad467ab712d41f693f998c6a9e3046b4f Mon Sep 17 00:00:00 2001 +Message-Id: +From: Erik Skultety +Date: Wed, 10 Apr 2019 10:25:01 +0200 +Subject: [PATCH] RHEL: conf: storage: Fix a memory leak in + virStoragePoolDefParseSource +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +https://bugzilla.redhat.com/show_bug.cgi?id=1584663 + +RHEL-only + +Commit acf8c561 backported an upstream memory leak in @ver variable that +was later fixed upstream by using AUTOFREE which is not available +downstream, so we need a downstream fix. The issue was reported by +coverity. + +Signed-off-by: Erik Skultety +Message-Id: +Reviewed-by: Ján Tomko +--- + src/conf/storage_conf.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c +index 5a124a0a2f..e171425239 100644 +--- a/src/conf/storage_conf.c ++++ b/src/conf/storage_conf.c +@@ -566,6 +566,7 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, + cleanup: + ctxt->node = relnode; + ++ VIR_FREE(ver); + VIR_FREE(port); + VIR_FREE(nodeset); + virStorageAuthDefFree(authdef); +-- +2.21.0 + diff --git a/SOURCES/libvirt-RHEL-cpu_map-Mark-arch-facilities-feature-as-non-migratable.patch b/SOURCES/libvirt-RHEL-cpu_map-Mark-arch-facilities-feature-as-non-migratable.patch index ebdaa75..ddd3d48 100644 --- a/SOURCES/libvirt-RHEL-cpu_map-Mark-arch-facilities-feature-as-non-migratable.patch +++ b/SOURCES/libvirt-RHEL-cpu_map-Mark-arch-facilities-feature-as-non-migratable.patch @@ -1,5 +1,5 @@ -From a74e5a0ea4e4a938bf9694b3d6194b68e5cffab1 Mon Sep 17 00:00:00 2001 -Message-Id: +From ead15fe7a0cd60eb91ff7744b24af15b6c122239 Mon Sep 17 00:00:00 2001 +Message-Id: From: Jiri Denemark Date: Wed, 9 Jan 2019 15:39:49 +0100 Subject: [PATCH] RHEL: cpu_map: Mark arch-facilities feature as non-migratable @@ -39,5 +39,5 @@ index f1f8048c14..9d53d4b43a 100644 -- -2.20.1 +2.21.0 diff --git a/SOURCES/libvirt-RHEL-qemu-Alter-qemuSetUnprivSGIO-hostdev-shareable-logic.patch b/SOURCES/libvirt-RHEL-qemu-Alter-qemuSetUnprivSGIO-hostdev-shareable-logic.patch new file mode 100644 index 0000000..aa40c07 --- /dev/null +++ b/SOURCES/libvirt-RHEL-qemu-Alter-qemuSetUnprivSGIO-hostdev-shareable-logic.patch @@ -0,0 +1,52 @@ +From 5b24ffe0ec9bd2fb18d26e6261b84556097067b7 Mon Sep 17 00:00:00 2001 +Message-Id: <5b24ffe0ec9bd2fb18d26e6261b84556097067b7@dist-git> +From: John Ferlan +Date: Wed, 5 Dec 2018 08:49:31 -0500 +Subject: [PATCH] RHEL: qemu: Alter qemuSetUnprivSGIO hostdev shareable logic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +https://bugzilla.redhat.com/show_bug.cgi?id=1656360 + +RHEL-only + +Fix the logic to handle the case where if the element +was removed from the domain , then we have to reset the +SGIO value back to 0. Without this patch the check for not shareable +and return 0 would bypass resetting the value back to 0. + +Signed-off-by: John Ferlan +Reviewed-by: Ján Tomko +--- + src/qemu/qemu_conf.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c +index de0cbca083..5971f3eb64 100644 +--- a/src/qemu/qemu_conf.c ++++ b/src/qemu/qemu_conf.c +@@ -1667,9 +1667,6 @@ qemuSetUnprivSGIO(virDomainDeviceDefPtr dev) + } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + hostdev = dev->data.hostdev; + +- if (!qemuIsSharedHostdev(hostdev)) +- return 0; +- + if (!(hostdev_path = qemuGetHostdevPath(hostdev))) + goto cleanup; + +@@ -1686,7 +1683,9 @@ qemuSetUnprivSGIO(virDomainDeviceDefPtr dev) + disk->sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED) { + val = 1; + } else { +- if (hostdev->source.subsys.u.scsi.sgio == ++ /* Only settable if was present for hostdev */ ++ if (qemuIsSharedHostdev(hostdev) && ++ hostdev->source.subsys.u.scsi.sgio == + VIR_DOMAIN_DEVICE_SGIO_UNFILTERED) + val = 1; + } +-- +2.21.0 + diff --git a/SOURCES/libvirt-RHEL-qemu-Alter-val-usage-in-qemuSetUnprivSGIO.patch b/SOURCES/libvirt-RHEL-qemu-Alter-val-usage-in-qemuSetUnprivSGIO.patch new file mode 100644 index 0000000..07082ba --- /dev/null +++ b/SOURCES/libvirt-RHEL-qemu-Alter-val-usage-in-qemuSetUnprivSGIO.patch @@ -0,0 +1,59 @@ +From 6764c4c345ba0ce1f60adab7958441279c3f4913 Mon Sep 17 00:00:00 2001 +Message-Id: <6764c4c345ba0ce1f60adab7958441279c3f4913@dist-git> +From: John Ferlan +Date: Wed, 5 Dec 2018 08:49:30 -0500 +Subject: [PATCH] RHEL: qemu: Alter @val usage in qemuSetUnprivSGIO +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +https://bugzilla.redhat.com/show_bug.cgi?id=1656360 + +RHEL-only + +Rather than initializing to -1 and then setting to the result +of a boolean check (either 0 or 1), let's just initialize @val +to 0 and then only change to 1 if conditions are "right". + +Signed-off-by: John Ferlan +Reviewed-by: Ján Tomko +--- + src/qemu/qemu_conf.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c +index 7d15af9c0b..de0cbca083 100644 +--- a/src/qemu/qemu_conf.c ++++ b/src/qemu/qemu_conf.c +@@ -1650,7 +1650,7 @@ qemuSetUnprivSGIO(virDomainDeviceDefPtr dev) + char *sysfs_path = NULL; + char *hostdev_path = NULL; + const char *path = NULL; +- int val = -1; ++ int val = 0; + int ret = -1; + + /* "sgio" is only valid for block disk; cdrom +@@ -1682,11 +1682,14 @@ qemuSetUnprivSGIO(virDomainDeviceDefPtr dev) + goto cleanup; + + /* By default, filter the SG_IO commands, i.e. set unpriv_sgio to 0. */ +- if (dev->type == VIR_DOMAIN_DEVICE_DISK) +- val = (disk->sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED); +- else +- val = (hostdev->source.subsys.u.scsi.sgio == +- VIR_DOMAIN_DEVICE_SGIO_UNFILTERED); ++ if (dev->type == VIR_DOMAIN_DEVICE_DISK && ++ disk->sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED) { ++ val = 1; ++ } else { ++ if (hostdev->source.subsys.u.scsi.sgio == ++ VIR_DOMAIN_DEVICE_SGIO_UNFILTERED) ++ val = 1; ++ } + + /* Do not do anything if unpriv_sgio is not supported by the kernel and the + * whitelist is enabled. But if requesting unfiltered access, always call +-- +2.21.0 + diff --git a/SOURCES/libvirt-access-Modify-the-VIR_ERR_ACCESS_DENIED-to-include-driverName.patch b/SOURCES/libvirt-access-Modify-the-VIR_ERR_ACCESS_DENIED-to-include-driverName.patch new file mode 100644 index 0000000..089ebf9 --- /dev/null +++ b/SOURCES/libvirt-access-Modify-the-VIR_ERR_ACCESS_DENIED-to-include-driverName.patch @@ -0,0 +1,159 @@ +From c7d644f205a64175961218c82f764cdd10766bff Mon Sep 17 00:00:00 2001 +Message-Id: +From: John Ferlan +Date: Wed, 3 Apr 2019 07:22:20 -0400 +Subject: [PATCH] access: Modify the VIR_ERR_ACCESS_DENIED to include + driverName + +https://bugzilla.redhat.com/show_bug.cgi?id=1631606 + +Changes made to manage and utilize a secondary connection +driver to APIs outside the scope of the primary connection +driver have resulted in some confusion processing polkit rules +since the simple "access denied" error message doesn't provide +enough of a clue when combined with the "authentication failed: +access denied by policy" as to which connection driver refused +or failed the ACL check. + +In order to provide some context, let's modify the existing +"access denied" error returned from the various vir*EnsureACL +API's to provide the connection driver name that is causing +the failure. This should provide the context for writing the +polkit rules that would allow access via the driver, but yet +still adhere to the virAccessManagerSanitizeError commentary +regarding not telling the user why access was denied. + +Signed-off-by: John Ferlan +(cherry picked from commit 605496be609e153526fcdd3e98df8cf5244bc8fa) +Message-Id: <20190403112220.23881-1-jferlan@redhat.com> +Reviewed-by: Erik Skultety +--- + src/access/viraccessmanager.c | 26 ++++++++++++++------------ + src/rpc/gendispatch.pl | 3 ++- + 2 files changed, 16 insertions(+), 13 deletions(-) + +diff --git a/src/access/viraccessmanager.c b/src/access/viraccessmanager.c +index e7b5bf38da..f5d62604cf 100644 +--- a/src/access/viraccessmanager.c ++++ b/src/access/viraccessmanager.c +@@ -196,11 +196,13 @@ static void virAccessManagerDispose(void *object) + * should the admin need to debug things + */ + static int +-virAccessManagerSanitizeError(int ret) ++virAccessManagerSanitizeError(int ret, ++ const char *driverName) + { + if (ret < 0) { + virResetLastError(); +- virAccessError(VIR_ERR_ACCESS_DENIED, NULL); ++ virAccessError(VIR_ERR_ACCESS_DENIED, ++ _("'%s' denied access"), driverName); + } + + return ret; +@@ -217,7 +219,7 @@ int virAccessManagerCheckConnect(virAccessManagerPtr manager, + if (manager->drv->checkConnect) + ret = manager->drv->checkConnect(manager, driverName, perm); + +- return virAccessManagerSanitizeError(ret); ++ return virAccessManagerSanitizeError(ret, driverName); + } + + +@@ -233,7 +235,7 @@ int virAccessManagerCheckDomain(virAccessManagerPtr manager, + if (manager->drv->checkDomain) + ret = manager->drv->checkDomain(manager, driverName, domain, perm); + +- return virAccessManagerSanitizeError(ret); ++ return virAccessManagerSanitizeError(ret, driverName); + } + + int virAccessManagerCheckInterface(virAccessManagerPtr manager, +@@ -248,7 +250,7 @@ int virAccessManagerCheckInterface(virAccessManagerPtr manager, + if (manager->drv->checkInterface) + ret = manager->drv->checkInterface(manager, driverName, iface, perm); + +- return virAccessManagerSanitizeError(ret); ++ return virAccessManagerSanitizeError(ret, driverName); + } + + int virAccessManagerCheckNetwork(virAccessManagerPtr manager, +@@ -263,7 +265,7 @@ int virAccessManagerCheckNetwork(virAccessManagerPtr manager, + if (manager->drv->checkNetwork) + ret = manager->drv->checkNetwork(manager, driverName, network, perm); + +- return virAccessManagerSanitizeError(ret); ++ return virAccessManagerSanitizeError(ret, driverName); + } + + int virAccessManagerCheckNodeDevice(virAccessManagerPtr manager, +@@ -278,7 +280,7 @@ int virAccessManagerCheckNodeDevice(virAccessManagerPtr manager, + if (manager->drv->checkNodeDevice) + ret = manager->drv->checkNodeDevice(manager, driverName, nodedev, perm); + +- return virAccessManagerSanitizeError(ret); ++ return virAccessManagerSanitizeError(ret, driverName); + } + + int virAccessManagerCheckNWFilter(virAccessManagerPtr manager, +@@ -293,7 +295,7 @@ int virAccessManagerCheckNWFilter(virAccessManagerPtr manager, + if (manager->drv->checkNWFilter) + ret = manager->drv->checkNWFilter(manager, driverName, nwfilter, perm); + +- return virAccessManagerSanitizeError(ret); ++ return virAccessManagerSanitizeError(ret, driverName); + } + + int virAccessManagerCheckNWFilterBinding(virAccessManagerPtr manager, +@@ -308,7 +310,7 @@ int virAccessManagerCheckNWFilterBinding(virAccessManagerPtr manager, + if (manager->drv->checkNWFilterBinding) + ret = manager->drv->checkNWFilterBinding(manager, driverName, binding, perm); + +- return virAccessManagerSanitizeError(ret); ++ return virAccessManagerSanitizeError(ret, driverName); + } + + int virAccessManagerCheckSecret(virAccessManagerPtr manager, +@@ -323,7 +325,7 @@ int virAccessManagerCheckSecret(virAccessManagerPtr manager, + if (manager->drv->checkSecret) + ret = manager->drv->checkSecret(manager, driverName, secret, perm); + +- return virAccessManagerSanitizeError(ret); ++ return virAccessManagerSanitizeError(ret, driverName); + } + + int virAccessManagerCheckStoragePool(virAccessManagerPtr manager, +@@ -338,7 +340,7 @@ int virAccessManagerCheckStoragePool(virAccessManagerPtr manager, + if (manager->drv->checkStoragePool) + ret = manager->drv->checkStoragePool(manager, driverName, pool, perm); + +- return virAccessManagerSanitizeError(ret); ++ return virAccessManagerSanitizeError(ret, driverName); + } + + int virAccessManagerCheckStorageVol(virAccessManagerPtr manager, +@@ -354,5 +356,5 @@ int virAccessManagerCheckStorageVol(virAccessManagerPtr manager, + if (manager->drv->checkStorageVol) + ret = manager->drv->checkStorageVol(manager, driverName, pool, vol, perm); + +- return virAccessManagerSanitizeError(ret); ++ return virAccessManagerSanitizeError(ret, driverName); + } +diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl +index 0c4648c0fb..a8b9f5aeca 100755 +--- a/src/rpc/gendispatch.pl ++++ b/src/rpc/gendispatch.pl +@@ -2199,7 +2199,8 @@ elsif ($mode eq "client") { + print " virObjectUnref(mgr);\n"; + if ($action eq "Ensure") { + print " if (rv == 0)\n"; +- print " virReportError(VIR_ERR_ACCESS_DENIED, NULL);\n"; ++ print " virReportError(VIR_ERR_ACCESS_DENIED,\n"; ++ print" _(\"'%s' denied access\"), conn->driver->name);\n"; + print " return $fail;\n"; + } else { + print " virResetLastError();\n"; +-- +2.21.0 + diff --git a/SOURCES/libvirt-admin-reject-clients-unless-their-UID-matches-the-current-UID.patch b/SOURCES/libvirt-admin-reject-clients-unless-their-UID-matches-the-current-UID.patch index fe99250..8ab6861 100644 --- a/SOURCES/libvirt-admin-reject-clients-unless-their-UID-matches-the-current-UID.patch +++ b/SOURCES/libvirt-admin-reject-clients-unless-their-UID-matches-the-current-UID.patch @@ -1,5 +1,5 @@ -From dba153a54183187d16cb983d269516930c555ad8 Mon Sep 17 00:00:00 2001 -Message-Id: +From 0abfa9e0b0b396420a165ac90e69952b23b5ca3e Mon Sep 17 00:00:00 2001 +Message-Id: <0abfa9e0b0b396420a165ac90e69952b23b5ca3e@dist-git> From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Wed, 15 May 2019 21:40:56 +0100 Subject: [PATCH] admin: reject clients unless their UID matches the current @@ -16,7 +16,7 @@ Fixes CVE-2019-10132 Reviewed-by: Ján Tomko Signed-off-by: Daniel P. Berrangé -(cherry picked from a private commit) +(cherry picked from commit 96f41cd765c9e525fe28ee5abbfbf4a79b3720c7) Reviewed-by: Jiri Denemark Message-Id: <20190515204058.28077-2-berrange@redhat.com> --- diff --git a/SOURCES/libvirt-api-disallow-virConnect-HypervisorCPU-on-read-only-connections.patch b/SOURCES/libvirt-api-disallow-virConnect-HypervisorCPU-on-read-only-connections.patch index 97f8622..bf8786e 100644 --- a/SOURCES/libvirt-api-disallow-virConnect-HypervisorCPU-on-read-only-connections.patch +++ b/SOURCES/libvirt-api-disallow-virConnect-HypervisorCPU-on-read-only-connections.patch @@ -1,5 +1,5 @@ -From 66884f16592038ec091d4bb2ab1d492062a71c74 Mon Sep 17 00:00:00 2001 -Message-Id: <66884f16592038ec091d4bb2ab1d492062a71c74@dist-git> +From f97144b76b3452e69c14834d1ecc69dbf802ac12 Mon Sep 17 00:00:00 2001 +Message-Id: From: =?UTF-8?q?J=C3=A1n=20Tomko?= Date: Tue, 18 Jun 2019 13:30:02 +0200 Subject: [PATCH] api: disallow virConnect*HypervisorCPU on read-only diff --git a/SOURCES/libvirt-api-disallow-virConnectGetDomainCapabilities-on-read-only-connections.patch b/SOURCES/libvirt-api-disallow-virConnectGetDomainCapabilities-on-read-only-connections.patch index 7028fcc..672dd0f 100644 --- a/SOURCES/libvirt-api-disallow-virConnectGetDomainCapabilities-on-read-only-connections.patch +++ b/SOURCES/libvirt-api-disallow-virConnectGetDomainCapabilities-on-read-only-connections.patch @@ -1,5 +1,5 @@ -From 804925f7bdd8cb7e80a0a76ea3323c55d89193ba Mon Sep 17 00:00:00 2001 -Message-Id: <804925f7bdd8cb7e80a0a76ea3323c55d89193ba@dist-git> +From fae17c4141d504073e9cb16b49d2af9e73272ac2 Mon Sep 17 00:00:00 2001 +Message-Id: From: =?UTF-8?q?J=C3=A1n=20Tomko?= Date: Tue, 18 Jun 2019 13:30:01 +0200 Subject: [PATCH] api: disallow virConnectGetDomainCapabilities on read-only @@ -22,10 +22,10 @@ Reviewed-by: Jiri Denemark 1 file changed, 1 insertion(+) diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c -index 3855dfe0dd..a1c913bd86 100644 +index b936dd8eb7..ab2c44cfe1 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c -@@ -11279,6 +11279,7 @@ virConnectGetDomainCapabilities(virConnectPtr conn, +@@ -11287,6 +11287,7 @@ virConnectGetDomainCapabilities(virConnectPtr conn, virResetLastError(); virCheckConnectReturn(conn, NULL); diff --git a/SOURCES/libvirt-api-disallow-virDomainManagedSaveDefineXML-on-read-only-connections.patch b/SOURCES/libvirt-api-disallow-virDomainManagedSaveDefineXML-on-read-only-connections.patch index 170a379..6cd6db1 100644 --- a/SOURCES/libvirt-api-disallow-virDomainManagedSaveDefineXML-on-read-only-connections.patch +++ b/SOURCES/libvirt-api-disallow-virDomainManagedSaveDefineXML-on-read-only-connections.patch @@ -1,5 +1,5 @@ -From 0f8966e0ce1887610b5eb9d955780662fc854094 Mon Sep 17 00:00:00 2001 -Message-Id: <0f8966e0ce1887610b5eb9d955780662fc854094@dist-git> +From 20a2fc74e717ca21e1a183b4e210872eb0c56be9 Mon Sep 17 00:00:00 2001 +Message-Id: <20a2fc74e717ca21e1a183b4e210872eb0c56be9@dist-git> From: =?UTF-8?q?J=C3=A1n=20Tomko?= Date: Tue, 18 Jun 2019 13:30:00 +0200 Subject: [PATCH] api: disallow virDomainManagedSaveDefineXML on read-only @@ -24,10 +24,10 @@ Reviewed-by: Jiri Denemark 1 file changed, 1 insertion(+) diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c -index 0ba85b9360..3855dfe0dd 100644 +index 697326ae9a..b936dd8eb7 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c -@@ -9487,6 +9487,7 @@ virDomainManagedSaveDefineXML(virDomainPtr domain, const char *dxml, +@@ -9495,6 +9495,7 @@ virDomainManagedSaveDefineXML(virDomainPtr domain, const char *dxml, virCheckDomainReturn(domain, -1); conn = domain->conn; diff --git a/SOURCES/libvirt-api-disallow-virDomainSaveImageGetXMLDesc-on-read-only-connections.patch b/SOURCES/libvirt-api-disallow-virDomainSaveImageGetXMLDesc-on-read-only-connections.patch index 83a3d5a..7653e1f 100644 --- a/SOURCES/libvirt-api-disallow-virDomainSaveImageGetXMLDesc-on-read-only-connections.patch +++ b/SOURCES/libvirt-api-disallow-virDomainSaveImageGetXMLDesc-on-read-only-connections.patch @@ -1,5 +1,5 @@ -From 799c1b70cdcfffd313315e9ab31d96bbb836aed6 Mon Sep 17 00:00:00 2001 -Message-Id: <799c1b70cdcfffd313315e9ab31d96bbb836aed6@dist-git> +From 2e532b74b3100a06e0f1ba21f657883fe5aafcc5 Mon Sep 17 00:00:00 2001 +Message-Id: <2e532b74b3100a06e0f1ba21f657883fe5aafcc5@dist-git> From: =?UTF-8?q?J=C3=A1n=20Tomko?= Date: Tue, 18 Jun 2019 13:29:59 +0200 Subject: [PATCH] api: disallow virDomainSaveImageGetXMLDesc on read-only @@ -38,7 +38,7 @@ Reviewed-by: Jiri Denemark 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c -index ad0ded9ee3..0ba85b9360 100644 +index 568023176b..697326ae9a 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -1073,9 +1073,7 @@ virDomainRestoreFlags(virConnectPtr conn, const char *from, const char *dxml, @@ -67,7 +67,7 @@ index ad0ded9ee3..0ba85b9360 100644 if (conn->driver->domainSaveImageGetXMLDesc) { char *ret; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c -index 21d836a540..fcccdb57c3 100644 +index 704ba24215..25818f5d8c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -6784,7 +6784,7 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, diff --git a/SOURCES/libvirt-conf-Add-memory-bandwidth-allocation-capability-of-host.patch b/SOURCES/libvirt-conf-Add-memory-bandwidth-allocation-capability-of-host.patch new file mode 100644 index 0000000..bf92ee0 --- /dev/null +++ b/SOURCES/libvirt-conf-Add-memory-bandwidth-allocation-capability-of-host.patch @@ -0,0 +1,397 @@ +From a7292e2be3fef0c14d5393120471b1dc5d7a5adb Mon Sep 17 00:00:00 2001 +Message-Id: +From: Bing Niu +Date: Mon, 15 Apr 2019 17:33:00 +0200 +Subject: [PATCH] conf: Add memory bandwidth allocation capability of host +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add new XML section to report host's memory bandwidth allocation +capability. The format as below example: + + + ..... + + + + + + + +granularity ---- granularity of memory bandwidth, unit percentage. +min ---- minimum memory bandwidth allowed, unit percentage. +maxAllocs ---- maximum memory bandwidth allocation group supported. + +Signed-off-by: Bing Niu +Reviewed-by: John Ferlan +(cherry picked from commit 7995fecc25c6bc8d0ebb243ea2c8765b076c8974) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1468650 + +Signed-off-by: Pavel Hrdina +Message-Id: +Reviewed-by: Ján Tomko +--- + docs/schemas/capability.rng | 33 ++++++ + src/conf/capabilities.c | 107 ++++++++++++++++++ + src/conf/capabilities.h | 11 ++ + src/util/virresctrl.c | 20 ++++ + src/util/virresctrl.h | 15 +++ + .../resctrl/info/MB/bandwidth_gran | 1 + + .../resctrl/info/MB/min_bandwidth | 1 + + .../linux-resctrl/resctrl/info/MB/num_closids | 1 + + .../vircaps-x86_64-resctrl.xml | 8 ++ + tests/virresctrldata/resctrl.schemata | 1 + + 10 files changed, 198 insertions(+) + create mode 100644 tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/bandwidth_gran + create mode 100644 tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/min_bandwidth + create mode 100644 tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/num_closids + +diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng +index 52164d5ecb..d61515ccbe 100644 +--- a/docs/schemas/capability.rng ++++ b/docs/schemas/capability.rng +@@ -51,6 +51,9 @@ + + + ++ ++ ++ + + + +@@ -326,6 +329,36 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c +index 7a810efa66..3d893447cb 100644 +--- a/src/conf/capabilities.c ++++ b/src/conf/capabilities.c +@@ -197,6 +197,16 @@ virCapabilitiesFreeNUMAInfo(virCapsPtr caps) + caps->host.nnumaCell = 0; + } + ++static void ++virCapsHostMemBWNodeFree(virCapsHostMemBWNodePtr ptr) ++{ ++ if (!ptr) ++ return; ++ ++ virBitmapFree(ptr->cpus); ++ VIR_FREE(ptr); ++} ++ + static void + virCapabilitiesClearSecModel(virCapsHostSecModelPtr secmodel) + { +@@ -239,6 +249,10 @@ virCapsDispose(void *object) + virCapsHostCacheBankFree(caps->host.caches[i]); + VIR_FREE(caps->host.caches); + ++ for (i = 0; i < caps->host.nnodes; i++) ++ virCapsHostMemBWNodeFree(caps->host.nodes[i]); ++ VIR_FREE(caps->host.nodes); ++ + VIR_FREE(caps->host.netprefix); + VIR_FREE(caps->host.pagesSize); + virCPUDefFree(caps->host.cpu); +@@ -957,6 +971,58 @@ virCapabilitiesFormatCaches(virBufferPtr buf, + return 0; + } + ++static int ++virCapabilitiesFormatMemoryBandwidth(virBufferPtr buf, ++ size_t nnodes, ++ virCapsHostMemBWNodePtr *nodes) ++{ ++ size_t i = 0; ++ virBuffer controlBuf = VIR_BUFFER_INITIALIZER; ++ ++ if (!nnodes) ++ return 0; ++ ++ virBufferAddLit(buf, "\n"); ++ virBufferAdjustIndent(buf, 2); ++ ++ for (i = 0; i < nnodes; i++) { ++ virCapsHostMemBWNodePtr node = nodes[i]; ++ virResctrlInfoMemBWPerNodePtr control = &node->control; ++ char *cpus_str = virBitmapFormat(node->cpus); ++ ++ if (!cpus_str) ++ return -1; ++ ++ virBufferAsprintf(buf, ++ "id, cpus_str); ++ VIR_FREE(cpus_str); ++ ++ virBufferSetChildIndent(&controlBuf, buf); ++ virBufferAsprintf(&controlBuf, ++ "\n", ++ control->granularity, control->min, ++ control->max_allocation); ++ ++ if (virBufferCheckError(&controlBuf) < 0) ++ return -1; ++ ++ if (virBufferUse(&controlBuf)) { ++ virBufferAddLit(buf, ">\n"); ++ virBufferAddBuffer(buf, &controlBuf); ++ virBufferAddLit(buf, "\n"); ++ } else { ++ virBufferAddLit(buf, "/>\n"); ++ } ++ } ++ ++ virBufferAdjustIndent(buf, -2); ++ virBufferAddLit(buf, "\n"); ++ ++ return 0; ++} ++ + /** + * virCapabilitiesFormatXML: + * @caps: capabilities to format +@@ -1060,6 +1126,10 @@ virCapabilitiesFormatXML(virCapsPtr caps) + caps->host.caches) < 0) + goto error; + ++ if (virCapabilitiesFormatMemoryBandwidth(&buf, caps->host.nnodes, ++ caps->host.nodes) < 0) ++ goto error; ++ + for (i = 0; i < caps->host.nsecModels; i++) { + virBufferAddLit(&buf, "\n"); + virBufferAdjustIndent(&buf, 2); +@@ -1602,6 +1672,40 @@ virCapabilitiesInitResctrl(virCapsPtr caps) + } + + ++static int ++virCapabilitiesInitResctrlMemory(virCapsPtr caps) ++{ ++ virCapsHostMemBWNodePtr node = NULL; ++ size_t i = 0; ++ int ret = -1; ++ ++ for (i = 0; i < caps->host.ncaches; i++) { ++ virCapsHostCacheBankPtr bank = caps->host.caches[i]; ++ if (VIR_ALLOC(node) < 0) ++ goto cleanup; ++ ++ if (virResctrlInfoGetMemoryBandwidth(caps->host.resctrl, ++ bank->level, &node->control) > 0) { ++ node->id = bank->id; ++ if (!(node->cpus = virBitmapNewCopy(bank->cpus))) ++ goto cleanup; ++ ++ if (VIR_APPEND_ELEMENT(caps->host.nodes, ++ caps->host.nnodes, node) < 0) { ++ goto cleanup; ++ } ++ } ++ virCapsHostMemBWNodeFree(node); ++ node = NULL; ++ } ++ ++ ret = 0; ++ cleanup: ++ virCapsHostMemBWNodeFree(node); ++ return ret; ++} ++ ++ + int + virCapabilitiesInitCaches(virCapsPtr caps) + { +@@ -1731,6 +1835,9 @@ virCapabilitiesInitCaches(virCapsPtr caps) + qsort(caps->host.caches, caps->host.ncaches, + sizeof(*caps->host.caches), virCapsHostCacheBankSorter); + ++ if (virCapabilitiesInitResctrlMemory(caps) < 0) ++ goto cleanup; ++ + ret = 0; + cleanup: + VIR_FREE(type); +diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h +index fe1b9ea455..046e275ac6 100644 +--- a/src/conf/capabilities.h ++++ b/src/conf/capabilities.h +@@ -151,6 +151,14 @@ struct _virCapsHostCacheBank { + virResctrlInfoPerCachePtr *controls; + }; + ++typedef struct _virCapsHostMemBWNode virCapsHostMemBWNode; ++typedef virCapsHostMemBWNode *virCapsHostMemBWNodePtr; ++struct _virCapsHostMemBWNode { ++ unsigned int id; ++ virBitmapPtr cpus; /* All CPUs that belong to this node*/ ++ virResctrlInfoMemBWPerNode control; ++}; ++ + typedef struct _virCapsHost virCapsHost; + typedef virCapsHost *virCapsHostPtr; + struct _virCapsHost { +@@ -175,6 +183,9 @@ struct _virCapsHost { + size_t ncaches; + virCapsHostCacheBankPtr *caches; + ++ size_t nnodes; ++ virCapsHostMemBWNodePtr *nodes; ++ + size_t nsecModels; + virCapsHostSecModelPtr secModels; + +diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c +index adf36a7c0a..4b5442f879 100644 +--- a/src/util/virresctrl.c ++++ b/src/util/virresctrl.c +@@ -629,6 +629,26 @@ virResctrlInfoIsEmpty(virResctrlInfoPtr resctrl) + } + + ++int ++virResctrlInfoGetMemoryBandwidth(virResctrlInfoPtr resctrl, ++ unsigned int level, ++ virResctrlInfoMemBWPerNodePtr control) ++{ ++ virResctrlInfoMemBWPtr membw_info = resctrl->membw_info; ++ ++ if (!membw_info) ++ return 0; ++ ++ if (membw_info->last_level_cache != level) ++ return 0; ++ ++ control->granularity = membw_info->bandwidth_granularity; ++ control->min = membw_info->min_bandwidth; ++ control->max_allocation = membw_info->max_allocation; ++ return 1; ++} ++ ++ + int + virResctrlInfoGetCache(virResctrlInfoPtr resctrl, + unsigned int level, +diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h +index 8d62517aa1..cfd56ddd06 100644 +--- a/src/util/virresctrl.h ++++ b/src/util/virresctrl.h +@@ -50,6 +50,17 @@ struct _virResctrlInfoPerCache { + unsigned int max_allocation; + }; + ++typedef struct _virResctrlInfoMemBWPerNode virResctrlInfoMemBWPerNode; ++typedef virResctrlInfoMemBWPerNode *virResctrlInfoMemBWPerNodePtr; ++struct _virResctrlInfoMemBWPerNode { ++ /* Smallest possible increase of the allocation bandwidth in percentage */ ++ unsigned int granularity; ++ /* Minimal allocatable bandwidth in percentage */ ++ unsigned int min; ++ /* Maximum number of simultaneous allocations */ ++ unsigned int max_allocation; ++}; ++ + typedef struct _virResctrlInfo virResctrlInfo; + typedef virResctrlInfo *virResctrlInfoPtr; + +@@ -63,6 +74,10 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl, + size_t *ncontrols, + virResctrlInfoPerCachePtr **controls); + ++int ++virResctrlInfoGetMemoryBandwidth(virResctrlInfoPtr resctrl, ++ unsigned int level, ++ virResctrlInfoMemBWPerNodePtr control); + /* Alloc-related things */ + typedef struct _virResctrlAlloc virResctrlAlloc; + typedef virResctrlAlloc *virResctrlAllocPtr; +diff --git a/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/bandwidth_gran b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/bandwidth_gran +new file mode 100644 +index 0000000000..f599e28b8a +--- /dev/null ++++ b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/bandwidth_gran +@@ -0,0 +1 @@ ++10 +diff --git a/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/min_bandwidth b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/min_bandwidth +new file mode 100644 +index 0000000000..f599e28b8a +--- /dev/null ++++ b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/min_bandwidth +@@ -0,0 +1 @@ ++10 +diff --git a/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/num_closids b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/num_closids +new file mode 100644 +index 0000000000..b8626c4cff +--- /dev/null ++++ b/tests/vircaps2xmldata/linux-resctrl/resctrl/info/MB/num_closids +@@ -0,0 +1 @@ ++4 +diff --git a/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml b/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml +index 4840614e86..9b00cf0995 100644 +--- a/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml ++++ b/tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml +@@ -49,6 +49,14 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/tests/virresctrldata/resctrl.schemata b/tests/virresctrldata/resctrl.schemata +index fa980e58c9..2578822b70 100644 +--- a/tests/virresctrldata/resctrl.schemata ++++ b/tests/virresctrldata/resctrl.schemata +@@ -1 +1,2 @@ + L3:0=000ff;1=000f0 ++MB:0=100;1=100 +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Add-optional-NFS-Source-Pool-protocol-ver-n-option.patch b/SOURCES/libvirt-conf-Add-optional-NFS-Source-Pool-protocol-ver-n-option.patch new file mode 100644 index 0000000..1be6b48 --- /dev/null +++ b/SOURCES/libvirt-conf-Add-optional-NFS-Source-Pool-protocol-ver-n-option.patch @@ -0,0 +1,213 @@ +From acf8c5619852146eed84123c7f432db925781511 Mon Sep 17 00:00:00 2001 +Message-Id: +From: John Ferlan +Date: Wed, 3 Apr 2019 10:58:19 -0400 +Subject: [PATCH] conf: Add optional NFS Source Pool option +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +https://bugzilla.redhat.com/show_bug.cgi?id=1584663 + +Add an optional way to define which NFS Server version will be +used to content the target NFS server. + +Signed-off-by: John Ferlan +Reviewed-by: Daniel P. Berrangé +(cherry picked from commit 801f8cfb37f12007878df53332fdc03245a9d40d) +Message-Id: <20190403145819.4656-1-jferlan@redhat.com> +Reviewed-by: Ján Tomko +--- + docs/formatstorage.html.in | 16 ++++++++++++++ + docs/schemas/storagepool.rng | 7 ++++++ + src/conf/storage_conf.c | 22 +++++++++++++++++++ + src/conf/storage_conf.h | 3 +++ + .../pool-netfs-protocol-ver.xml | 21 ++++++++++++++++++ + .../pool-netfs-protocol-ver.xml | 21 ++++++++++++++++++ + tests/storagepoolxml2xmltest.c | 1 + + 7 files changed, 91 insertions(+) + create mode 100644 tests/storagepoolxml2xmlin/pool-netfs-protocol-ver.xml + create mode 100644 tests/storagepoolxml2xmlout/pool-netfs-protocol-ver.xml + +diff --git a/docs/formatstorage.html.in b/docs/formatstorage.html.in +index b6bf3edbd2..b1b76a1dda 100644 +--- a/docs/formatstorage.html.in ++++ b/docs/formatstorage.html.in +@@ -121,6 +121,16 @@ + </source> + ... + ++
++...
++  <source>
++    <host name='localhost'/>
++    <dir path='/var/lib/libvirt/images'/>
++    <format type='nfs'/>
++    <protocol ver='3'/>
++  </source>
++...
++ +
+
device
+
Provides the source for pools backed by physical devices +@@ -386,6 +396,12 @@ + LVM metadata type. All drivers are required to have a default + value for this, so it is optional. Since 0.4.1
+ ++
protocol
++
For a netfs Storage Pool provide a mechanism to ++ define which NFS protocol version number will be used to contact ++ the server's NFS service. The attribute ver accepts ++ an unsigned integer as the version number to use. ++ Since 5.1.0
+
vendor
+
Provides optional information about the vendor of the + storage device. This contains a single +diff --git a/docs/schemas/storagepool.rng b/docs/schemas/storagepool.rng +index 52b2044bef..0cb8beb926 100644 +--- a/docs/schemas/storagepool.rng ++++ b/docs/schemas/storagepool.rng +@@ -520,6 +520,13 @@ + + + ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c +index 5036ab9ef8..5a124a0a2f 100644 +--- a/src/conf/storage_conf.c ++++ b/src/conf/storage_conf.c +@@ -415,6 +415,7 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, + virStorageAuthDefPtr authdef = NULL; + char *name = NULL; + char *port = NULL; ++ char *ver = NULL; + int n; + + relnode = ctxt->node; +@@ -540,6 +541,24 @@ virStoragePoolDefParseSource(xmlXPathContextPtr ctxt, + authdef = NULL; + } + ++ /* Option protocol version string (NFSvN) */ ++ if ((ver = virXPathString("string(./protocol/@ver)", ctxt))) { ++ if ((source->format != VIR_STORAGE_POOL_NETFS_NFS) && ++ (source->format != VIR_STORAGE_POOL_NETFS_AUTO)) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("storage pool protocol ver unsupported for " ++ "pool type '%s'"), ++ virStoragePoolFormatFileSystemNetTypeToString(source->format)); ++ goto cleanup; ++ } ++ if (virStrToLong_uip(ver, NULL, 0, &source->protocolVer) < 0) { ++ virReportError(VIR_ERR_XML_ERROR, ++ _("storage pool protocol ver '%s' is malformaed"), ++ ver); ++ goto cleanup; ++ } ++ } ++ + source->vendor = virXPathString("string(./vendor/@name)", ctxt); + source->product = virXPathString("string(./product/@name)", ctxt); + +@@ -956,6 +975,9 @@ virStoragePoolSourceFormat(virBufferPtr buf, + if (src->auth) + virStorageAuthDefFormat(buf, src->auth); + ++ if (src->protocolVer) ++ virBufferAsprintf(buf, "\n", src->protocolVer); ++ + virBufferEscapeString(buf, "\n", src->vendor); + virBufferEscapeString(buf, "\n", src->product); + +diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h +index 15dfd8becf..3b637e2258 100644 +--- a/src/conf/storage_conf.h ++++ b/src/conf/storage_conf.h +@@ -203,6 +203,9 @@ struct _virStoragePoolSource { + * or lvm version, etc. + */ + int format; ++ ++ /* Protocol version value for netfs */ ++ unsigned int protocolVer; + }; + + typedef struct _virStoragePoolTarget virStoragePoolTarget; +diff --git a/tests/storagepoolxml2xmlin/pool-netfs-protocol-ver.xml b/tests/storagepoolxml2xmlin/pool-netfs-protocol-ver.xml +new file mode 100644 +index 0000000000..40f3f94e41 +--- /dev/null ++++ b/tests/storagepoolxml2xmlin/pool-netfs-protocol-ver.xml +@@ -0,0 +1,21 @@ ++ ++ nfsimages ++ 7641d5a8-af11-f730-a34e-0a7dfcede71f ++ 0 ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ /mnt ++ ++ 0700 ++ 0 ++ 0 ++ ++ ++ +diff --git a/tests/storagepoolxml2xmlout/pool-netfs-protocol-ver.xml b/tests/storagepoolxml2xmlout/pool-netfs-protocol-ver.xml +new file mode 100644 +index 0000000000..5fcad1305b +--- /dev/null ++++ b/tests/storagepoolxml2xmlout/pool-netfs-protocol-ver.xml +@@ -0,0 +1,21 @@ ++ ++ nfsimages ++ 7641d5a8-af11-f730-a34e-0a7dfcede71f ++ 0 ++ 0 ++ 0 ++ ++ ++ ++ ++ ++ ++ ++ /mnt ++ ++ 0700 ++ 0 ++ 0 ++ ++ ++ +diff --git a/tests/storagepoolxml2xmltest.c b/tests/storagepoolxml2xmltest.c +index 29c0e42479..cf41b4d065 100644 +--- a/tests/storagepoolxml2xmltest.c ++++ b/tests/storagepoolxml2xmltest.c +@@ -86,6 +86,7 @@ mymain(void) + DO_TEST("pool-iscsi-auth"); + DO_TEST("pool-netfs"); + DO_TEST("pool-netfs-auto"); ++ DO_TEST("pool-netfs-protocol-ver"); + DO_TEST("pool-netfs-gluster"); + DO_TEST("pool-netfs-cifs"); + DO_TEST("pool-scsi"); +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Add-return-value-check-to-virResctrlAllocForeachCache.patch b/SOURCES/libvirt-conf-Add-return-value-check-to-virResctrlAllocForeachCache.patch new file mode 100644 index 0000000..13da8f8 --- /dev/null +++ b/SOURCES/libvirt-conf-Add-return-value-check-to-virResctrlAllocForeachCache.patch @@ -0,0 +1,49 @@ +From 7a8c614b37e0d7e1b2eac08a72f46ef715b72c5a Mon Sep 17 00:00:00 2001 +Message-Id: <7a8c614b37e0d7e1b2eac08a72f46ef715b72c5a@dist-git> +From: Bing Niu +Date: Mon, 15 Apr 2019 17:32:59 +0200 +Subject: [PATCH] conf: Add return value check to virResctrlAllocForeachCache +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add return value check to virResctrlAllocForeachCache in +virDomainCachetuneDefFormat. The virResctrlAllocForeachCache does have +return value, so need check return value to make sure function executed +without error. + +Signed-off-by: Bing Niu +Reviewed-by: John Ferlan +(cherry picked from commit 8d6f508e64728f9aaa5a624462ac0da325854cad) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1468650 + +Signed-off-by: Pavel Hrdina +Message-Id: +Reviewed-by: Ján Tomko +--- + src/conf/domain_conf.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 2f56c077a9..74781fe596 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -27258,10 +27258,10 @@ virDomainCachetuneDefFormat(virBufferPtr buf, + int ret = -1; + + virBufferSetChildIndent(&childrenBuf, buf); +- virResctrlAllocForeachCache(resctrl->alloc, +- virDomainCachetuneDefFormatHelper, +- &childrenBuf); +- ++ if (virResctrlAllocForeachCache(resctrl->alloc, ++ virDomainCachetuneDefFormatHelper, ++ &childrenBuf) < 0) ++ goto cleanup; + + if (virBufferCheckError(&childrenBuf) < 0) + goto cleanup; +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Add-support-for-memorytune-XML-processing-for-resctrl-MBA.patch b/SOURCES/libvirt-conf-Add-support-for-memorytune-XML-processing-for-resctrl-MBA.patch new file mode 100644 index 0000000..2d34310 --- /dev/null +++ b/SOURCES/libvirt-conf-Add-support-for-memorytune-XML-processing-for-resctrl-MBA.patch @@ -0,0 +1,503 @@ +From 1240e6d5b3d53a34a94b308ddf2f10a12f2556f6 Mon Sep 17 00:00:00 2001 +Message-Id: <1240e6d5b3d53a34a94b308ddf2f10a12f2556f6@dist-git> +From: Bing Niu +Date: Mon, 15 Apr 2019 17:32:58 +0200 +Subject: [PATCH] conf: Add support for memorytune XML processing for resctrl + MBA +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Introduce a new section memorytune to support memory bandwidth allocation. +This is consistent with existing cachetune. As the example: +below: + + ...... + + + + + +vpus --- vpus subjected to this memory bandwidth. +id --- on which node memory bandwidth to be set. +bandwidth --- the memory bandwidth percent to set. + +Signed-off-by: Bing Niu +Reviewed-by: John Ferlan +(cherry picked from commit 6956b7eedce4cb6dc2f95684fc3e10c163dfc6fc) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1468650 + +Signed-off-by: Pavel Hrdina +Message-Id: <3139e3b8f3c3d66891847b5a99bd9125ec01f00b.1555342313.git.phrdina@redhat.com> +Reviewed-by: Ján Tomko +--- + docs/formatdomain.html.in | 39 +++- + docs/schemas/domaincommon.rng | 17 ++ + src/conf/domain_conf.c | 200 ++++++++++++++++++ + .../memorytune-colliding-allocs.xml | 30 +++ + .../memorytune-colliding-cachetune.xml | 32 +++ + tests/genericxml2xmlindata/memorytune.xml | 33 +++ + tests/genericxml2xmltest.c | 5 + + 7 files changed, 355 insertions(+), 1 deletion(-) + create mode 100644 tests/genericxml2xmlindata/memorytune-colliding-allocs.xml + create mode 100644 tests/genericxml2xmlindata/memorytune-colliding-cachetune.xml + create mode 100644 tests/genericxml2xmlindata/memorytune.xml + +diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in +index 42acf7a828..8cf2c12524 100644 +--- a/docs/formatdomain.html.in ++++ b/docs/formatdomain.html.in +@@ -757,6 +757,10 @@ + <cache id='0' level='3' type='both' size='3' unit='MiB'/> + <cache id='1' level='3' type='both' size='3' unit='MiB'/> + </cachetune> ++ <memorytune vcpus='0-3'> ++ <node id='0' bandwidth='60'/> ++ </memorytune> ++ + </cputune> + ... + </domain> +@@ -910,7 +914,9 @@ + size and required granularity are reported as well. The required + attribute vcpus specifies to which vCPUs this allocation + applies. A vCPU can only be member of one cachetune element +- allocations. Supported subelements are: ++ allocation. The vCPUs specified by cachetune can be identical with those ++ in memorytune, however they are not allowed to overlap. ++ Supported subelements are: +
+
cache
+
+@@ -950,7 +956,38 @@ +
+
+
++ + ++
memorytuneSince 4.7.0
++
++ Optional memorytune element can control allocations for ++ memory bandwidth using the resctrl on the host. Whether or not is this ++ supported can be gathered from capabilities where some limitations like ++ minimum bandwidth and required granularity are reported as well. The ++ required attribute vcpus specifies to which vCPUs this ++ allocation applies. A vCPU can only be member of one ++ memorytune element allocation. The vcpus specified ++ by memorytune can be identical to those specified by ++ cachetune. However they are not allowed to overlap each other. ++ Supported subelements are: ++
++
node
++
++ This element controls the allocation of CPU memory bandwidth and has the ++ following attributes: ++
++
id
++
++ Host node id from which to allocate memory bandwidth. ++
++
bandwidth
++
++ The memory bandwidth to allocate from this node. The value by default ++ is in percentage. ++
++
++
++
+
+ + +diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng +index ac04af51a1..48f0637cad 100644 +--- a/docs/schemas/domaincommon.rng ++++ b/docs/schemas/domaincommon.rng +@@ -983,6 +983,23 @@ + +
+ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + +
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 44bfd75b72..2f56c077a9 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -19296,6 +19296,129 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + } + + ++static int ++virDomainMemorytuneDefParseMemory(xmlXPathContextPtr ctxt, ++ xmlNodePtr node, ++ virResctrlAllocPtr alloc) ++{ ++ xmlNodePtr oldnode = ctxt->node; ++ unsigned int id; ++ unsigned int bandwidth; ++ char *tmp = NULL; ++ int ret = -1; ++ ++ ctxt->node = node; ++ ++ tmp = virXMLPropString(node, "id"); ++ if (!tmp) { ++ virReportError(VIR_ERR_XML_ERROR, "%s", ++ _("Missing memorytune attribute 'id'")); ++ goto cleanup; ++ } ++ if (virStrToLong_uip(tmp, NULL, 10, &id) < 0) { ++ virReportError(VIR_ERR_XML_ERROR, ++ _("Invalid memorytune attribute 'id' value '%s'"), ++ tmp); ++ goto cleanup; ++ } ++ VIR_FREE(tmp); ++ ++ tmp = virXMLPropString(node, "bandwidth"); ++ if (!tmp) { ++ virReportError(VIR_ERR_XML_ERROR, "%s", ++ _("Missing memorytune attribute 'bandwidth'")); ++ goto cleanup; ++ } ++ if (virStrToLong_uip(tmp, NULL, 10, &bandwidth) < 0) { ++ virReportError(VIR_ERR_XML_ERROR, ++ _("Invalid memorytune attribute 'bandwidth' value '%s'"), ++ tmp); ++ goto cleanup; ++ } ++ VIR_FREE(tmp); ++ if (virResctrlAllocSetMemoryBandwidth(alloc, id, bandwidth) < 0) ++ goto cleanup; ++ ++ ret = 0; ++ cleanup: ++ ctxt->node = oldnode; ++ VIR_FREE(tmp); ++ return ret; ++} ++ ++ ++static int ++virDomainMemorytuneDefParse(virDomainDefPtr def, ++ xmlXPathContextPtr ctxt, ++ xmlNodePtr node, ++ unsigned int flags) ++{ ++ xmlNodePtr oldnode = ctxt->node; ++ xmlNodePtr *nodes = NULL; ++ virBitmapPtr vcpus = NULL; ++ virResctrlAllocPtr alloc = NULL; ++ ssize_t i = 0; ++ int n; ++ int ret = -1; ++ bool new_alloc = false; ++ ++ ctxt->node = node; ++ ++ if (virDomainResctrlParseVcpus(def, node, &vcpus) < 0) ++ goto cleanup; ++ ++ if (virBitmapIsAllClear(vcpus)) { ++ ret = 0; ++ goto cleanup; ++ } ++ ++ if ((n = virXPathNodeSet("./node", ctxt, &nodes)) < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("Cannot extract memory nodes under memorytune")); ++ goto cleanup; ++ } ++ ++ if (virDomainResctrlVcpuMatch(def, vcpus, &alloc) < 0) ++ goto cleanup; ++ ++ if (!alloc) { ++ alloc = virResctrlAllocNew(); ++ if (!alloc) ++ goto cleanup; ++ new_alloc = true; ++ } else { ++ alloc = virObjectRef(alloc); ++ } ++ ++ for (i = 0; i < n; i++) { ++ if (virDomainMemorytuneDefParseMemory(ctxt, nodes[i], alloc) < 0) ++ goto cleanup; ++ } ++ if (virResctrlAllocIsEmpty(alloc)) { ++ ret = 0; ++ goto cleanup; ++ } ++ /* ++ * If this is a new allocation, format ID and append to resctrl, otherwise ++ * just update the existing alloc information, which is done in above ++ * virDomainMemorytuneDefParseMemory */ ++ if (new_alloc) { ++ if (virDomainResctrlAppend(def, node, alloc, vcpus, flags) < 0) ++ goto cleanup; ++ vcpus = NULL; ++ alloc = NULL; ++ } ++ ++ ret = 0; ++ cleanup: ++ ctxt->node = oldnode; ++ virObjectUnref(alloc); ++ virBitmapFree(vcpus); ++ VIR_FREE(nodes); ++ return ret; ++} ++ ++ + static virDomainDefPtr + virDomainDefParseXML(xmlDocPtr xml, + xmlNodePtr root, +@@ -19856,6 +19979,18 @@ virDomainDefParseXML(xmlDocPtr xml, + } + VIR_FREE(nodes); + ++ if ((n = virXPathNodeSet("./cputune/memorytune", ctxt, &nodes)) < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", ++ _("cannot extract memorytune nodes")); ++ goto error; ++ } ++ ++ for (i = 0; i < n; i++) { ++ if (virDomainMemorytuneDefParse(def, ctxt, nodes[i], flags) < 0) ++ goto error; ++ } ++ VIR_FREE(nodes); ++ + if (virCPUDefParseXML(ctxt, "./cpu[1]", VIR_CPU_TYPE_GUEST, &def->cpu) < 0) + goto error; + +@@ -27162,6 +27297,68 @@ virDomainCachetuneDefFormat(virBufferPtr buf, + } + + ++static int ++virDomainMemorytuneDefFormatHelper(unsigned int id, ++ unsigned int bandwidth, ++ void *opaque) ++{ ++ virBufferPtr buf = opaque; ++ ++ virBufferAsprintf(buf, ++ "\n", ++ id, bandwidth); ++ return 0; ++} ++ ++ ++static int ++virDomainMemorytuneDefFormat(virBufferPtr buf, ++ virDomainResctrlDefPtr resctrl, ++ unsigned int flags) ++{ ++ virBuffer childrenBuf = VIR_BUFFER_INITIALIZER; ++ char *vcpus = NULL; ++ int ret = -1; ++ ++ virBufferSetChildIndent(&childrenBuf, buf); ++ if (virResctrlAllocForeachMemory(resctrl->alloc, ++ virDomainMemorytuneDefFormatHelper, ++ &childrenBuf) < 0) ++ goto cleanup; ++ ++ if (virBufferCheckError(&childrenBuf) < 0) ++ goto cleanup; ++ ++ if (!virBufferUse(&childrenBuf)) { ++ ret = 0; ++ goto cleanup; ++ } ++ ++ vcpus = virBitmapFormat(resctrl->vcpus); ++ if (!vcpus) ++ goto cleanup; ++ ++ virBufferAsprintf(buf, "alloc); ++ if (!alloc_id) ++ goto cleanup; ++ ++ virBufferAsprintf(buf, " id='%s'", alloc_id); ++ } ++ virBufferAddLit(buf, ">\n"); ++ ++ virBufferAddBuffer(buf, &childrenBuf); ++ virBufferAddLit(buf, "\n"); ++ ++ ret = 0; ++ cleanup: ++ virBufferFreeAndReset(&childrenBuf); ++ VIR_FREE(vcpus); ++ return ret; ++} ++ + static int + virDomainCputuneDefFormat(virBufferPtr buf, + virDomainDefPtr def, +@@ -27267,6 +27464,9 @@ virDomainCputuneDefFormat(virBufferPtr buf, + for (i = 0; i < def->nresctrls; i++) + virDomainCachetuneDefFormat(&childrenBuf, def->resctrls[i], flags); + ++ for (i = 0; i < def->nresctrls; i++) ++ virDomainMemorytuneDefFormat(&childrenBuf, def->resctrls[i], flags); ++ + if (virBufferCheckError(&childrenBuf) < 0) + return -1; + +diff --git a/tests/genericxml2xmlindata/memorytune-colliding-allocs.xml b/tests/genericxml2xmlindata/memorytune-colliding-allocs.xml +new file mode 100644 +index 0000000000..9b8ebaa084 +--- /dev/null ++++ b/tests/genericxml2xmlindata/memorytune-colliding-allocs.xml +@@ -0,0 +1,30 @@ ++ ++ QEMUGuest1 ++ c7a5fdbd-edaf-9455-926a-d65c16db1809 ++ 219136 ++ 219136 ++ 4 ++ ++ ++ ++ ++ ++ ++ ++ hvm ++ ++ ++ ++ destroy ++ restart ++ destroy ++ ++ /usr/bin/qemu-system-i686 ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/genericxml2xmlindata/memorytune-colliding-cachetune.xml b/tests/genericxml2xmlindata/memorytune-colliding-cachetune.xml +new file mode 100644 +index 0000000000..5416870de2 +--- /dev/null ++++ b/tests/genericxml2xmlindata/memorytune-colliding-cachetune.xml +@@ -0,0 +1,32 @@ ++ ++ QEMUGuest1 ++ c7a5fdbd-edaf-9455-926a-d65c16db1809 ++ 219136 ++ 219136 ++ 4 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ hvm ++ ++ ++ ++ destroy ++ restart ++ destroy ++ ++ /usr/bin/qemu-system-i686 ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/genericxml2xmlindata/memorytune.xml b/tests/genericxml2xmlindata/memorytune.xml +new file mode 100644 +index 0000000000..ea03e22fc2 +--- /dev/null ++++ b/tests/genericxml2xmlindata/memorytune.xml +@@ -0,0 +1,33 @@ ++ ++ QEMUGuest1 ++ c7a5fdbd-edaf-9455-926a-d65c16db1809 ++ 219136 ++ 219136 ++ 4 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ hvm ++ ++ ++ ++ destroy ++ restart ++ destroy ++ ++ /usr/bin/qemu-system-i686 ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c +index 7a4fc1eb7a..e6d4ef2a7f 100644 +--- a/tests/genericxml2xmltest.c ++++ b/tests/genericxml2xmltest.c +@@ -140,6 +140,11 @@ mymain(void) + TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE); + DO_TEST_FULL("cachetune-colliding-types", false, true, + TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE); ++ DO_TEST("memorytune"); ++ DO_TEST_FULL("memorytune-colliding-allocs", false, true, ++ TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE); ++ DO_TEST_FULL("memorytune-colliding-cachetune", false, true, ++ TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE); + + DO_TEST("tseg"); + +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Expose-virDomainSCSIDriveAddressIsUsed.patch b/SOURCES/libvirt-conf-Expose-virDomainSCSIDriveAddressIsUsed.patch new file mode 100644 index 0000000..ab7257b --- /dev/null +++ b/SOURCES/libvirt-conf-Expose-virDomainSCSIDriveAddressIsUsed.patch @@ -0,0 +1,68 @@ +From bb9521f7e0e8a67f04b5776cccf8b458a16bc94b Mon Sep 17 00:00:00 2001 +Message-Id: +From: Michal Privoznik +Date: Thu, 18 Apr 2019 18:43:10 +0200 +Subject: [PATCH] conf: Expose virDomainSCSIDriveAddressIsUsed + +https://bugzilla.redhat.com/show_bug.cgi?id=1692296 + +This function checks if given drive address is already present in +passed domain definition. Expose the function as it will be used +shortly. + +Signed-off-by: Michal Privoznik +Tested-by: Daniel Henrique Barboza +Reviewed-by: Jim Fehlig +(cherry picked from commit 89237d534f0fe950d06a2081089154160c6c2224) +Signed-off-by: Michal Privoznik +Message-Id: <79f85c93272ac232b81cb80f80d1ba396d557198.1555605741.git.mprivozn@redhat.com> +Reviewed-by: Jiri Denemark +--- + src/conf/domain_conf.c | 2 +- + src/conf/domain_conf.h | 4 ++++ + src/libvirt_private.syms | 1 + + 3 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 712efbb9f9..1096499831 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -4400,7 +4400,7 @@ virDomainDriveAddressIsUsedByHostdev(const virDomainDef *def, + * Return true if the SCSI drive address is already in use, false + * otherwise. + */ +-static bool ++bool + virDomainSCSIDriveAddressIsUsed(const virDomainDef *def, + const virDomainDeviceDriveAddress *addr) + { +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index 5e2f21dea3..390bd81aa0 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -2785,6 +2785,10 @@ virDomainXMLNamespacePtr + virDomainXMLOptionGetNamespace(virDomainXMLOptionPtr xmlopt) + ATTRIBUTE_NONNULL(1); + ++bool ++virDomainSCSIDriveAddressIsUsed(const virDomainDef *def, ++ const virDomainDeviceDriveAddress *addr); ++ + int virDomainDefPostParse(virDomainDefPtr def, + virCapsPtr caps, + unsigned int parseFlags, +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index 3325b90535..3000d6ee0a 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -520,6 +520,7 @@ virDomainRunningReasonTypeToString; + virDomainSaveConfig; + virDomainSaveStatus; + virDomainSaveXML; ++virDomainSCSIDriveAddressIsUsed; + virDomainSeclabelTypeFromString; + virDomainSeclabelTypeToString; + virDomainShmemDefEquals; +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Factor-out-vcpus-overlapping-from-virDomainCachetuneDefParse.patch b/SOURCES/libvirt-conf-Factor-out-vcpus-overlapping-from-virDomainCachetuneDefParse.patch new file mode 100644 index 0000000..f46e7db --- /dev/null +++ b/SOURCES/libvirt-conf-Factor-out-vcpus-overlapping-from-virDomainCachetuneDefParse.patch @@ -0,0 +1,124 @@ +From c00106d41b74d86ee7357ed62399ea7ffb9cd393 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Bing Niu +Date: Mon, 15 Apr 2019 17:32:56 +0200 +Subject: [PATCH] conf: Factor out vcpus overlapping from + virDomainCachetuneDefParse +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Factor out vcpus overlapping detecting part from +virDomainCachetuneDefParse and introduce virDomainResctrlVcpuMatch. +Instead of allocating virResctrlAllocPtr by default, allocating +virResctrlAllocPtr after confirm vcpus not overlap with existing ones. +And virDomainResctrlVcpuMatch can be reused by other resource control +technologies. virDomainResctrlVcpuMatch can clarify old vcpus overlap +error whether an overlap or a redefinition. + +Signed-off-by: Bing Niu +Reviewed-by: John Ferlan +(cherry picked from commit e5cc7c0a0258530000aa9fd930c649b525b6f801) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1468650 + +Signed-off-by: Pavel Hrdina +Message-Id: +Reviewed-by: Ján Tomko +--- + src/conf/domain_conf.c | 51 ++++++++++++++++++++++++++++++++---------- + 1 file changed, 39 insertions(+), 12 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 07d21f8026..fb5adbcd10 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -19077,6 +19077,31 @@ virDomainResctrlParseVcpus(virDomainDefPtr def, + } + + ++static int ++virDomainResctrlVcpuMatch(virDomainDefPtr def, ++ virBitmapPtr vcpus, ++ virResctrlAllocPtr *alloc) ++{ ++ ssize_t i = 0; ++ ++ for (i = 0; i < def->nresctrls; i++) { ++ /* vcpus group has been created, directly use the existing one. ++ * Just updating memory allocation information of that group ++ */ ++ if (virBitmapEqual(def->resctrls[i]->vcpus, vcpus)) { ++ *alloc = def->resctrls[i]->alloc; ++ break; ++ } ++ if (virBitmapOverlaps(def->resctrls[i]->vcpus, vcpus)) { ++ virReportError(VIR_ERR_XML_ERROR, "%s", ++ _("Overlapping vcpus in resctrls")); ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++ + static int + virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt, + xmlNodePtr node, +@@ -19160,7 +19185,7 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + xmlNodePtr oldnode = ctxt->node; + xmlNodePtr *nodes = NULL; + virBitmapPtr vcpus = NULL; +- virResctrlAllocPtr alloc = virResctrlAllocNew(); ++ virResctrlAllocPtr alloc = NULL; + virDomainResctrlDefPtr tmp_resctrl = NULL; + char *tmp = NULL; + char *vcpus_str = NULL; +@@ -19171,9 +19196,6 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + + ctxt->node = node; + +- if (!alloc) +- goto cleanup; +- + if (VIR_ALLOC(tmp_resctrl) < 0) + goto cleanup; + +@@ -19191,6 +19213,19 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + goto cleanup; + } + ++ if (virDomainResctrlVcpuMatch(def, vcpus, &alloc) < 0) ++ goto cleanup; ++ ++ if (!alloc) { ++ alloc = virResctrlAllocNew(); ++ if (!alloc) ++ goto cleanup; ++ } else { ++ virReportError(VIR_ERR_XML_ERROR, "%s", ++ _("Identical vcpus in cachetunes found")); ++ goto cleanup; ++ } ++ + for (i = 0; i < n; i++) { + if (virDomainCachetuneDefParseCache(ctxt, nodes[i], alloc) < 0) + goto cleanup; +@@ -19201,14 +19236,6 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + goto cleanup; + } + +- for (i = 0; i < def->nresctrls; i++) { +- if (virBitmapOverlaps(def->resctrls[i]->vcpus, vcpus)) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _("Overlapping vcpus in cachetunes")); +- goto cleanup; +- } +- } +- + /* We need to format it back because we need to be consistent in the naming + * even when users specify some "sub-optimal" string there. */ + VIR_FREE(vcpus_str); +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Factor-out-vcpus-parsing-part-from-virDomainCachetuneDefParse.patch b/SOURCES/libvirt-conf-Factor-out-vcpus-parsing-part-from-virDomainCachetuneDefParse.patch new file mode 100644 index 0000000..461216f --- /dev/null +++ b/SOURCES/libvirt-conf-Factor-out-vcpus-parsing-part-from-virDomainCachetuneDefParse.patch @@ -0,0 +1,99 @@ +From ca59034c25fe39acb246f82587c0c32ba04d6c89 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Bing Niu +Date: Mon, 15 Apr 2019 17:32:55 +0200 +Subject: [PATCH] conf: Factor out vcpus parsing part from + virDomainCachetuneDefParse +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Extract vcpus parsing part from virDomainCachetuneDefParse into one +function called virDomainResctrlParseVcpus. So that vcpus parsing logic +can be reused by other resource control technologies. Adjust error +message and use node->name so that the error message can fit to all +technologies. + +Signed-off-by: Bing Niu +Reviewed-by: John Ferlan +(cherry picked from commit 6021c3926ba62a2593f0db63e5413e9663c69a5f) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1468650 + +Signed-off-by: Pavel Hrdina +Message-Id: <2f330b4bbface15dce23370d5f212b2240e031cd.1555342313.git.phrdina@redhat.com> +Reviewed-by: Ján Tomko +--- + src/conf/domain_conf.c | 48 +++++++++++++++++++++++++++++------------- + 1 file changed, 33 insertions(+), 15 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 0c8afe78c6..07d21f8026 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -19045,6 +19045,38 @@ virDomainDefParseBootOptions(virDomainDefPtr def, + } + + ++static int ++virDomainResctrlParseVcpus(virDomainDefPtr def, ++ xmlNodePtr node, ++ virBitmapPtr *vcpus) ++{ ++ char *vcpus_str = NULL; ++ int ret = -1; ++ ++ vcpus_str = virXMLPropString(node, "vcpus"); ++ if (!vcpus_str) { ++ virReportError(VIR_ERR_XML_ERROR, _("Missing %s attribute 'vcpus'"), ++ node->name); ++ goto cleanup; ++ } ++ if (virBitmapParse(vcpus_str, vcpus, VIR_DOMAIN_CPUMASK_LEN) < 0) { ++ virReportError(VIR_ERR_XML_ERROR, ++ _("Invalid %s attribute 'vcpus' value '%s'"), ++ node->name, vcpus_str); ++ goto cleanup; ++ } ++ ++ /* We need to limit the bitmap to number of vCPUs. If there's nothing left, ++ * then we can just clean up and return 0 immediately */ ++ virBitmapShrink(*vcpus, def->maxvcpus); ++ ++ ret = 0; ++ cleanup: ++ VIR_FREE(vcpus_str); ++ return ret; ++} ++ ++ + static int + virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt, + xmlNodePtr node, +@@ -19145,22 +19177,8 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + if (VIR_ALLOC(tmp_resctrl) < 0) + goto cleanup; + +- vcpus_str = virXMLPropString(node, "vcpus"); +- if (!vcpus_str) { +- virReportError(VIR_ERR_XML_ERROR, "%s", +- _("Missing cachetune attribute 'vcpus'")); ++ if (virDomainResctrlParseVcpus(def, node, &vcpus) < 0) + goto cleanup; +- } +- if (virBitmapParse(vcpus_str, &vcpus, VIR_DOMAIN_CPUMASK_LEN) < 0) { +- virReportError(VIR_ERR_XML_ERROR, +- _("Invalid cachetune attribute 'vcpus' value '%s'"), +- vcpus_str); +- goto cleanup; +- } +- +- /* We need to limit the bitmap to number of vCPUs. If there's nothing left, +- * then we can just clean up and return 0 immediately */ +- virBitmapShrink(vcpus, def->maxvcpus); + + if (virBitmapIsAllClear(vcpus)) { + ret = 0; +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Factor-out-virDomainResctrlDef-update-from-virDomainCachetuneDefParse.patch b/SOURCES/libvirt-conf-Factor-out-virDomainResctrlDef-update-from-virDomainCachetuneDefParse.patch new file mode 100644 index 0000000..c8b844e --- /dev/null +++ b/SOURCES/libvirt-conf-Factor-out-virDomainResctrlDef-update-from-virDomainCachetuneDefParse.patch @@ -0,0 +1,164 @@ +From 7551c4a8b453278e7a27a8e7a722851af1f23efc Mon Sep 17 00:00:00 2001 +Message-Id: <7551c4a8b453278e7a27a8e7a722851af1f23efc@dist-git> +From: Bing Niu +Date: Mon, 15 Apr 2019 17:32:57 +0200 +Subject: [PATCH] conf: Factor out virDomainResctrlDef update from + virDomainCachetuneDefParse +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Factor out vcpus virDomainResctrlDef update from +virDomainCachetuneDefParse and introduce virDomainResctrlAppend. +virDomainResctrlAppend will format vcpus string and append a new +virDomainResctrlDef to virDomainDefPtr. So that this logic can +be reusable. + +Signed-off-by: Bing Niu +Reviewed-by: John Ferlan +(cherry picked from commit 72824f67cdb9c474034539e81fb03fb1bc94495f) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1468650 + +Signed-off-by: Pavel Hrdina +Message-Id: +Reviewed-by: Ján Tomko +--- + src/conf/domain_conf.c | 93 +++++++++++++++++++++++++----------------- + 1 file changed, 55 insertions(+), 38 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index fb5adbcd10..44bfd75b72 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -19176,6 +19176,58 @@ virDomainCachetuneDefParseCache(xmlXPathContextPtr ctxt, + } + + ++static int ++virDomainResctrlAppend(virDomainDefPtr def, ++ xmlNodePtr node, ++ virResctrlAllocPtr alloc, ++ virBitmapPtr vcpus, ++ unsigned int flags) ++{ ++ char *vcpus_str = NULL; ++ char *alloc_id = NULL; ++ virDomainResctrlDefPtr tmp_resctrl = NULL; ++ int ret = -1; ++ ++ if (VIR_ALLOC(tmp_resctrl) < 0) ++ goto cleanup; ++ ++ /* We need to format it back because we need to be consistent in the naming ++ * even when users specify some "sub-optimal" string there. */ ++ vcpus_str = virBitmapFormat(vcpus); ++ if (!vcpus_str) ++ goto cleanup; ++ ++ if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) ++ alloc_id = virXMLPropString(node, "id"); ++ ++ if (!alloc_id) { ++ /* The number of allocations is limited and the directory structure is flat, ++ * not hierarchical, so we need to have all same allocations in one ++ * directory, so it's nice to have it named appropriately. For now it's ++ * 'vcpus_...' but it's designed in order for it to be changeable in the ++ * future (it's part of the status XML). */ ++ if (virAsprintf(&alloc_id, "vcpus_%s", vcpus_str) < 0) ++ goto cleanup; ++ } ++ ++ if (virResctrlAllocSetID(alloc, alloc_id) < 0) ++ goto cleanup; ++ ++ tmp_resctrl->vcpus = vcpus; ++ tmp_resctrl->alloc = alloc; ++ ++ if (VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, tmp_resctrl) < 0) ++ goto cleanup; ++ ++ ret = 0; ++ cleanup: ++ virDomainResctrlDefFree(tmp_resctrl); ++ VIR_FREE(alloc_id); ++ VIR_FREE(vcpus_str); ++ return ret; ++} ++ ++ + static int + virDomainCachetuneDefParse(virDomainDefPtr def, + xmlXPathContextPtr ctxt, +@@ -19186,19 +19238,12 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + xmlNodePtr *nodes = NULL; + virBitmapPtr vcpus = NULL; + virResctrlAllocPtr alloc = NULL; +- virDomainResctrlDefPtr tmp_resctrl = NULL; +- char *tmp = NULL; +- char *vcpus_str = NULL; +- char *alloc_id = NULL; + ssize_t i = 0; + int n; + int ret = -1; + + ctxt->node = node; + +- if (VIR_ALLOC(tmp_resctrl) < 0) +- goto cleanup; +- + if (virDomainResctrlParseVcpus(def, node, &vcpus) < 0) + goto cleanup; + +@@ -19236,45 +19281,17 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + goto cleanup; + } + +- /* We need to format it back because we need to be consistent in the naming +- * even when users specify some "sub-optimal" string there. */ +- VIR_FREE(vcpus_str); +- vcpus_str = virBitmapFormat(vcpus); +- if (!vcpus_str) +- goto cleanup; +- +- if (!(flags & VIR_DOMAIN_DEF_PARSE_INACTIVE)) +- alloc_id = virXMLPropString(node, "id"); +- +- if (!alloc_id) { +- /* The number of allocations is limited and the directory structure is flat, +- * not hierarchical, so we need to have all same allocations in one +- * directory, so it's nice to have it named appropriately. For now it's +- * 'vcpus_...' but it's designed in order for it to be changeable in the +- * future (it's part of the status XML). */ +- if (virAsprintf(&alloc_id, "vcpus_%s", vcpus_str) < 0) +- goto cleanup; +- } +- +- if (virResctrlAllocSetID(alloc, alloc_id) < 0) +- goto cleanup; +- +- VIR_STEAL_PTR(tmp_resctrl->vcpus, vcpus); +- VIR_STEAL_PTR(tmp_resctrl->alloc, alloc); +- +- if (VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, tmp_resctrl) < 0) ++ if (virDomainResctrlAppend(def, node, alloc, vcpus, flags) < 0) + goto cleanup; ++ vcpus = NULL; ++ alloc = NULL; + + ret = 0; + cleanup: + ctxt->node = oldnode; +- virDomainResctrlDefFree(tmp_resctrl); + virObjectUnref(alloc); + virBitmapFree(vcpus); +- VIR_FREE(alloc_id); +- VIR_FREE(vcpus_str); + VIR_FREE(nodes); +- VIR_FREE(tmp); + return ret; + } + +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Fix-bug-in-finding-alloc-through-matching-vcpus.patch b/SOURCES/libvirt-conf-Fix-bug-in-finding-alloc-through-matching-vcpus.patch new file mode 100644 index 0000000..2d9f402 --- /dev/null +++ b/SOURCES/libvirt-conf-Fix-bug-in-finding-alloc-through-matching-vcpus.patch @@ -0,0 +1,52 @@ +From 408d9e217f05b6c68351804df56aa9c9af7db4e7 Mon Sep 17 00:00:00 2001 +Message-Id: <408d9e217f05b6c68351804df56aa9c9af7db4e7@dist-git> +From: Wang Huaqiang +Date: Mon, 15 Apr 2019 17:33:01 +0200 +Subject: [PATCH] conf: Fix bug in finding alloc through matching vcpus +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The @alloc object returned by virDomainResctrlVcpuMatch is not +properly referenced and un-referenced in virDomainCachetuneDefParse. + +This patch fixes this problem. + +Signed-off-by: Wang Huaqiang +Reviewed-by: John Ferlan +(cherry picked from commit 3a1cdb06fd9bc5e35230f6198e697d6ec03d1206) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1468650 + +Signed-off-by: Pavel Hrdina +Message-Id: <7049386040dc0d170193b5fbfc81f2a8335d0063.1555342313.git.phrdina@redhat.com> +Reviewed-by: Ján Tomko +--- + src/conf/domain_conf.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 74781fe596..6af14cc06f 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -19089,7 +19089,7 @@ virDomainResctrlVcpuMatch(virDomainDefPtr def, + * Just updating memory allocation information of that group + */ + if (virBitmapEqual(def->resctrls[i]->vcpus, vcpus)) { +- *alloc = def->resctrls[i]->alloc; ++ *alloc = virObjectRef(def->resctrls[i]->alloc); + break; + } + if (virBitmapOverlaps(def->resctrls[i]->vcpus, vcpus)) { +@@ -19386,8 +19386,6 @@ virDomainMemorytuneDefParse(virDomainDefPtr def, + if (!alloc) + goto cleanup; + new_alloc = true; +- } else { +- alloc = virObjectRef(alloc); + } + + for (i = 0; i < n; i++) { +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Fix-check-for-chardev-source-path.patch b/SOURCES/libvirt-conf-Fix-check-for-chardev-source-path.patch new file mode 100644 index 0000000..8b03303 --- /dev/null +++ b/SOURCES/libvirt-conf-Fix-check-for-chardev-source-path.patch @@ -0,0 +1,112 @@ +From dc638f4d9fea8647a190dc9d2dabc4ce81ab2a3c Mon Sep 17 00:00:00 2001 +Message-Id: +From: Andrea Bolognani +Date: Wed, 3 Apr 2019 17:08:57 +0200 +Subject: [PATCH] conf: Fix check for chardev source path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Attempting to use a chardev definition like + + + + + +correctly results in an error being reported, since the source +path - a required piece of information - is missing; however, +the very similar + + + + + +was happily accepted by libvirt, only to result in libvirtd +crashing as soon as the guest was started. + +The issue was caused by checking the chardev's targetType +against whitelisted values from virDomainChrChannelTargetType +without first checking the chardev's deviceType to make sure +it is actually a channel, for which the check makes sense, +rather than a different type of chardev. + +The only reason this wasn't spotted earlier is that the +whitelisted values just so happen to correspond to USB and +PCI serial devices and Xen and UML consoles respectively, +all of which are fairly uncommon. + +https://bugzilla.redhat.com/show_bug.cgi?id=1609720 + +Signed-off-by: Andrea Bolognani +Reviewed-by: Ján Tomko + +(cherry picked from commit 614193fac67445a7e92bf620ffef726ed1bd6f07) +Signed-off-by: Andrea Bolognani +Message-Id: <20190403150857.20850-1-abologna@redhat.com> +Reviewed-by: Erik Skultety +--- + src/conf/domain_conf.c | 11 +++++++---- + .../serial-unix-missing-source.xml | 15 +++++++++++++++ + tests/qemuxml2argvtest.c | 1 + + 3 files changed, 23 insertions(+), 4 deletions(-) + create mode 100644 tests/qemuxml2argvdata/serial-unix-missing-source.xml + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index eb4e9ac523..712efbb9f9 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -5531,11 +5531,14 @@ virDomainChrSourceDefValidate(const virDomainChrSourceDef *def, + break; + + case VIR_DOMAIN_CHR_TYPE_UNIX: +- /* path can be auto generated */ ++ /* The source path can be auto generated for certain specific ++ * types of channels, but in most cases we should report an ++ * error if the user didn't provide it */ + if (!def->data.nix.path && +- (!chr_def || +- (chr_def->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN && +- chr_def->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO))) { ++ !(chr_def && ++ chr_def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL && ++ (chr_def->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN || ++ chr_def->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing source path attribute for char device")); + return -1; +diff --git a/tests/qemuxml2argvdata/serial-unix-missing-source.xml b/tests/qemuxml2argvdata/serial-unix-missing-source.xml +new file mode 100644 +index 0000000000..1e1221f12d +--- /dev/null ++++ b/tests/qemuxml2argvdata/serial-unix-missing-source.xml +@@ -0,0 +1,15 @@ ++ ++ guest ++ c7a5fdbd-edaf-9455-926a-d65c16db1809 ++ 1048576 ++ 1 ++ ++ hvm ++ ++ ++ /usr/bin/qemu-system-aarch64 ++ ++ ++ ++ ++ +diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c +index d97dc0ea8d..7a731e2f40 100644 +--- a/tests/qemuxml2argvtest.c ++++ b/tests/qemuxml2argvtest.c +@@ -1363,6 +1363,7 @@ mymain(void) + DO_TEST("serial-unix-chardev", + QEMU_CAPS_DEVICE_ISA_SERIAL); + DO_TEST_CAPS_LATEST("serial-unix-chardev"); ++ DO_TEST_PARSE_ERROR("serial-unix-missing-source", NONE); + DO_TEST("serial-tcp-chardev", + QEMU_CAPS_DEVICE_ISA_SERIAL); + DO_TEST("serial-udp-chardev", +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Introduce-virDomainGraphics-related-helpers.patch b/SOURCES/libvirt-conf-Introduce-virDomainGraphics-related-helpers.patch new file mode 100644 index 0000000..06ce7a0 --- /dev/null +++ b/SOURCES/libvirt-conf-Introduce-virDomainGraphics-related-helpers.patch @@ -0,0 +1,121 @@ +From 7b4b21814c4a1af212b061e265ee0ca8220abd1e Mon Sep 17 00:00:00 2001 +Message-Id: <7b4b21814c4a1af212b061e265ee0ca8220abd1e@dist-git> +From: Erik Skultety +Date: Tue, 9 Apr 2019 08:34:26 +0200 +Subject: [PATCH] conf: Introduce virDomainGraphics-related helpers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +A few simple helpers that allow us to determine whether a graphics can +and will need to make use of a DRM render node. + +Signed-off-by: Erik Skultety +Reviewed-by: Ján Tomko +(cherry picked from commit 255e073263b55b524f68b64c282e73509f93985e) + +https: //bugzilla.redhat.com/show_bug.cgi?id=1628892 +Signed-off-by: Erik Skultety +Message-Id: <24845c3d51a90b5de6989e70e9de51b07b44ade9.1554791287.git.eskultet@redhat.com> +Reviewed-by: Jiri Denemark +--- + src/conf/domain_conf.c | 43 ++++++++++++++++++++++++++++++++++++++++ + src/conf/domain_conf.h | 9 +++++++++ + src/libvirt_private.syms | 3 +++ + 3 files changed, 55 insertions(+) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index 6af14cc06f..d079be2bb5 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -30713,3 +30713,46 @@ virDomainGraphicsDefHasOpenGL(const virDomainDef *def) + + return false; + } ++ ++ ++bool ++virDomainGraphicsSupportsRenderNode(const virDomainGraphicsDef *graphics) ++{ ++ return graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE; ++} ++ ++ ++const char * ++virDomainGraphicsGetRenderNode(const virDomainGraphicsDef *graphics) ++{ ++ const char *ret = NULL; ++ ++ switch (graphics->type) { ++ case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: ++ if (graphics->data.spice.gl == VIR_TRISTATE_BOOL_YES) ++ ret = graphics->data.spice.rendernode; ++ break; ++ case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: ++ case VIR_DOMAIN_GRAPHICS_TYPE_SDL: ++ case VIR_DOMAIN_GRAPHICS_TYPE_VNC: ++ case VIR_DOMAIN_GRAPHICS_TYPE_RDP: ++ case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP: ++ case VIR_DOMAIN_GRAPHICS_TYPE_LAST: ++ break; ++ } ++ ++ return ret; ++} ++ ++ ++bool ++virDomainGraphicsNeedsAutoRenderNode(const virDomainGraphicsDef *graphics) ++{ ++ if (!virDomainGraphicsSupportsRenderNode(graphics)) ++ return false; ++ ++ if (virDomainGraphicsGetRenderNode(graphics)) ++ return false; ++ ++ return true; ++} +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index 65abe9cde6..b1139812d5 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -3651,4 +3651,13 @@ virDomainDefHasManagedPR(const virDomainDef *def); + bool + virDomainGraphicsDefHasOpenGL(const virDomainDef *def); + ++bool ++virDomainGraphicsSupportsRenderNode(const virDomainGraphicsDef *graphics); ++ ++const char * ++virDomainGraphicsGetRenderNode(const virDomainGraphicsDef *graphics); ++ ++bool ++virDomainGraphicsNeedsAutoRenderNode(const virDomainGraphicsDef *graphics); ++ + #endif /* __DOMAIN_CONF_H */ +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index 6655dfdecc..984a9be18f 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -370,8 +370,10 @@ virDomainGraphicsAuthConnectedTypeToString; + virDomainGraphicsDefFree; + virDomainGraphicsDefHasOpenGL; + virDomainGraphicsGetListen; ++virDomainGraphicsGetRenderNode; + virDomainGraphicsListenAppendAddress; + virDomainGraphicsListenAppendSocket; ++virDomainGraphicsNeedsAutoRenderNode; + virDomainGraphicsSpiceChannelModeTypeFromString; + virDomainGraphicsSpiceChannelModeTypeToString; + virDomainGraphicsSpiceChannelNameTypeFromString; +@@ -386,6 +388,7 @@ virDomainGraphicsSpiceStreamingModeTypeFromString; + virDomainGraphicsSpiceStreamingModeTypeToString; + virDomainGraphicsSpiceZlibCompressionTypeFromString; + virDomainGraphicsSpiceZlibCompressionTypeToString; ++virDomainGraphicsSupportsRenderNode; + virDomainGraphicsTypeFromString; + virDomainGraphicsTypeToString; + virDomainGraphicsVNCSharePolicyTypeFromString; +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Rename-cachetune-to-resctrl.patch b/SOURCES/libvirt-conf-Rename-cachetune-to-resctrl.patch new file mode 100644 index 0000000..f9ba031 --- /dev/null +++ b/SOURCES/libvirt-conf-Rename-cachetune-to-resctrl.patch @@ -0,0 +1,267 @@ +From 8e87a5625a571d05177c6766405db814b6e8e7b3 Mon Sep 17 00:00:00 2001 +Message-Id: <8e87a5625a571d05177c6766405db814b6e8e7b3@dist-git> +From: Bing Niu +Date: Mon, 15 Apr 2019 17:32:54 +0200 +Subject: [PATCH] conf: Rename cachetune to resctrl +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resctrl not only supports cache tuning, but also memory bandwidth +tuning. Renaming cachetune to resctrl to reflect that. With resctrl, +all allocation for different resources (cache, memory bandwidth) are +aggregated and represented by a virResctrlAllocPtr inside +virDomainResctrlDef. + +Signed-off-by: Bing Niu +Reviewed-by: John Ferlan +(cherry picked from commit acc288d655237a22a95c5a1ae7207916fb9efac9) + +Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1468650 + +Signed-off-by: Pavel Hrdina +Message-Id: <9ee9c0993a62ddf084968b211ca82c9e6b62ef0d.1555342313.git.phrdina@redhat.com> +Reviewed-by: Ján Tomko +--- + src/conf/domain_conf.c | 44 ++++++++++++++++++++--------------------- + src/conf/domain_conf.h | 10 +++++----- + src/qemu/qemu_domain.c | 2 +- + src/qemu/qemu_process.c | 18 ++++++++--------- + 4 files changed, 37 insertions(+), 37 deletions(-) + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index e04edd97dc..0c8afe78c6 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -2966,14 +2966,14 @@ virDomainLoaderDefFree(virDomainLoaderDefPtr loader) + + + static void +-virDomainCachetuneDefFree(virDomainCachetuneDefPtr cachetune) ++virDomainResctrlDefFree(virDomainResctrlDefPtr resctrl) + { +- if (!cachetune) ++ if (!resctrl) + return; + +- virObjectUnref(cachetune->alloc); +- virBitmapFree(cachetune->vcpus); +- VIR_FREE(cachetune); ++ virObjectUnref(resctrl->alloc); ++ virBitmapFree(resctrl->vcpus); ++ VIR_FREE(resctrl); + } + + +@@ -3163,9 +3163,9 @@ void virDomainDefFree(virDomainDefPtr def) + virDomainShmemDefFree(def->shmems[i]); + VIR_FREE(def->shmems); + +- for (i = 0; i < def->ncachetunes; i++) +- virDomainCachetuneDefFree(def->cachetunes[i]); +- VIR_FREE(def->cachetunes); ++ for (i = 0; i < def->nresctrls; i++) ++ virDomainResctrlDefFree(def->resctrls[i]); ++ VIR_FREE(def->resctrls); + + VIR_FREE(def->keywrap); + +@@ -19129,7 +19129,7 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + xmlNodePtr *nodes = NULL; + virBitmapPtr vcpus = NULL; + virResctrlAllocPtr alloc = virResctrlAllocNew(); +- virDomainCachetuneDefPtr tmp_cachetune = NULL; ++ virDomainResctrlDefPtr tmp_resctrl = NULL; + char *tmp = NULL; + char *vcpus_str = NULL; + char *alloc_id = NULL; +@@ -19142,7 +19142,7 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + if (!alloc) + goto cleanup; + +- if (VIR_ALLOC(tmp_cachetune) < 0) ++ if (VIR_ALLOC(tmp_resctrl) < 0) + goto cleanup; + + vcpus_str = virXMLPropString(node, "vcpus"); +@@ -19183,8 +19183,8 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + goto cleanup; + } + +- for (i = 0; i < def->ncachetunes; i++) { +- if (virBitmapOverlaps(def->cachetunes[i]->vcpus, vcpus)) { ++ for (i = 0; i < def->nresctrls; i++) { ++ if (virBitmapOverlaps(def->resctrls[i]->vcpus, vcpus)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Overlapping vcpus in cachetunes")); + goto cleanup; +@@ -19214,16 +19214,16 @@ virDomainCachetuneDefParse(virDomainDefPtr def, + if (virResctrlAllocSetID(alloc, alloc_id) < 0) + goto cleanup; + +- VIR_STEAL_PTR(tmp_cachetune->vcpus, vcpus); +- VIR_STEAL_PTR(tmp_cachetune->alloc, alloc); ++ VIR_STEAL_PTR(tmp_resctrl->vcpus, vcpus); ++ VIR_STEAL_PTR(tmp_resctrl->alloc, alloc); + +- if (VIR_APPEND_ELEMENT(def->cachetunes, def->ncachetunes, tmp_cachetune) < 0) ++ if (VIR_APPEND_ELEMENT(def->resctrls, def->nresctrls, tmp_resctrl) < 0) + goto cleanup; + + ret = 0; + cleanup: + ctxt->node = oldnode; +- virDomainCachetuneDefFree(tmp_cachetune); ++ virDomainResctrlDefFree(tmp_resctrl); + virObjectUnref(alloc); + virBitmapFree(vcpus); + VIR_FREE(alloc_id); +@@ -27053,7 +27053,7 @@ virDomainCachetuneDefFormatHelper(unsigned int level, + + static int + virDomainCachetuneDefFormat(virBufferPtr buf, +- virDomainCachetuneDefPtr cachetune, ++ virDomainResctrlDefPtr resctrl, + unsigned int flags) + { + virBuffer childrenBuf = VIR_BUFFER_INITIALIZER; +@@ -27061,7 +27061,7 @@ virDomainCachetuneDefFormat(virBufferPtr buf, + int ret = -1; + + virBufferSetChildIndent(&childrenBuf, buf); +- virResctrlAllocForeachCache(cachetune->alloc, ++ virResctrlAllocForeachCache(resctrl->alloc, + virDomainCachetuneDefFormatHelper, + &childrenBuf); + +@@ -27074,14 +27074,14 @@ virDomainCachetuneDefFormat(virBufferPtr buf, + goto cleanup; + } + +- vcpus = virBitmapFormat(cachetune->vcpus); ++ vcpus = virBitmapFormat(resctrl->vcpus); + if (!vcpus) + goto cleanup; + + virBufferAsprintf(buf, "alloc); ++ const char *alloc_id = virResctrlAllocGetID(resctrl->alloc); + if (!alloc_id) + goto cleanup; + +@@ -27202,8 +27202,8 @@ virDomainCputuneDefFormat(virBufferPtr buf, + def->iothreadids[i]->iothread_id); + } + +- for (i = 0; i < def->ncachetunes; i++) +- virDomainCachetuneDefFormat(&childrenBuf, def->cachetunes[i], flags); ++ for (i = 0; i < def->nresctrls; i++) ++ virDomainCachetuneDefFormat(&childrenBuf, def->resctrls[i], flags); + + if (virBufferCheckError(&childrenBuf) < 0) + return -1; +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index 390bd81aa0..65abe9cde6 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -2232,10 +2232,10 @@ struct _virDomainCputune { + }; + + +-typedef struct _virDomainCachetuneDef virDomainCachetuneDef; +-typedef virDomainCachetuneDef *virDomainCachetuneDefPtr; ++typedef struct _virDomainResctrlDef virDomainResctrlDef; ++typedef virDomainResctrlDef *virDomainResctrlDefPtr; + +-struct _virDomainCachetuneDef { ++struct _virDomainResctrlDef { + virBitmapPtr vcpus; + virResctrlAllocPtr alloc; + }; +@@ -2413,8 +2413,8 @@ struct _virDomainDef { + + virDomainCputune cputune; + +- virDomainCachetuneDefPtr *cachetunes; +- size_t ncachetunes; ++ virDomainResctrlDefPtr *resctrls; ++ size_t nresctrls; + + virDomainNumaPtr numa; + virDomainResourceDefPtr resource; +diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c +index d80f9b393e..112958f64a 100644 +--- a/src/qemu/qemu_domain.c ++++ b/src/qemu/qemu_domain.c +@@ -3999,7 +3999,7 @@ qemuDomainDefValidate(const virDomainDef *def, + } + } + +- if (def->ncachetunes && ++ if (def->nresctrls && + def->virtType != VIR_DOMAIN_VIRT_KVM) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("cachetune is only supported for KVM domains")); +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 208c64381c..a44f371346 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -2584,7 +2584,7 @@ qemuProcessResctrlCreate(virQEMUDriverPtr driver, + virCapsPtr caps = NULL; + qemuDomainObjPrivatePtr priv = vm->privateData; + +- if (!vm->def->ncachetunes) ++ if (!vm->def->nresctrls) + return 0; + + /* Force capability refresh since resctrl info can change +@@ -2593,9 +2593,9 @@ qemuProcessResctrlCreate(virQEMUDriverPtr driver, + if (!caps) + return -1; + +- for (i = 0; i < vm->def->ncachetunes; i++) { ++ for (i = 0; i < vm->def->nresctrls; i++) { + if (virResctrlAllocCreate(caps->host.resctrl, +- vm->def->cachetunes[i]->alloc, ++ vm->def->resctrls[i]->alloc, + priv->machineName) < 0) + goto cleanup; + } +@@ -5411,8 +5411,8 @@ qemuProcessSetupVcpu(virDomainObjPtr vm, + &vcpu->sched) < 0) + return -1; + +- for (i = 0; i < vm->def->ncachetunes; i++) { +- virDomainCachetuneDefPtr ct = vm->def->cachetunes[i]; ++ for (i = 0; i < vm->def->nresctrls; i++) { ++ virDomainResctrlDefPtr ct = vm->def->resctrls[i]; + + if (virBitmapIsBitSet(ct->vcpus, vcpuid)) { + if (virResctrlAllocAddPID(ct->alloc, vcpupid) < 0) +@@ -7108,8 +7108,8 @@ void qemuProcessStop(virQEMUDriverPtr driver, + /* Remove resctrl allocation after cgroups are cleaned up which makes it + * kind of safer (although removing the allocation should work even with + * pids in tasks file */ +- for (i = 0; i < vm->def->ncachetunes; i++) +- virResctrlAllocRemove(vm->def->cachetunes[i]->alloc); ++ for (i = 0; i < vm->def->nresctrls; i++) ++ virResctrlAllocRemove(vm->def->resctrls[i]->alloc); + + qemuProcessRemoveDomainStatus(driver, vm); + +@@ -7835,8 +7835,8 @@ qemuProcessReconnect(void *opaque) + if (qemuConnectAgent(driver, obj) < 0) + goto error; + +- for (i = 0; i < obj->def->ncachetunes; i++) { +- if (virResctrlAllocDeterminePath(obj->def->cachetunes[i]->alloc, ++ for (i = 0; i < obj->def->nresctrls; i++) { ++ if (virResctrlAllocDeterminePath(obj->def->resctrls[i]->alloc, + priv->machineName) < 0) + goto error; + } +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-Report-TSC-frequency-in-host-CPU-capabilities.patch b/SOURCES/libvirt-conf-Report-TSC-frequency-in-host-CPU-capabilities.patch new file mode 100644 index 0000000..722ff32 --- /dev/null +++ b/SOURCES/libvirt-conf-Report-TSC-frequency-in-host-CPU-capabilities.patch @@ -0,0 +1,149 @@ +From 5b07ca7c378a5e62fec0ed4808e8905fe447e85e Mon Sep 17 00:00:00 2001 +Message-Id: <5b07ca7c378a5e62fec0ed4808e8905fe447e85e@dist-git> +From: Jiri Denemark +Date: Tue, 4 Jun 2019 13:04:30 +0200 +Subject: [PATCH] conf: Report TSC frequency in host CPU capabilities +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch adds a new + + + +element into the host CPU capabilities XML. + +Signed-off-by: Jiri Denemark +(cherry picked from commit c277b9ad5c740bb4c4b915754ae74621f93f9d37) + +https://bugzilla.redhat.com/show_bug.cgi?id=1641702 + +Conflicts: + src/conf/cpu_conf.h + - virenum.h doesn't exist downstream + +Signed-off-by: Jiri Denemark +Message-Id: +Reviewed-by: Ján Tomko +--- + src/conf/cpu_conf.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ + src/conf/cpu_conf.h | 2 ++ + 2 files changed, 50 insertions(+) + +diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c +index 43a3ab5dcd..d0ad265fbe 100644 +--- a/src/conf/cpu_conf.c ++++ b/src/conf/cpu_conf.c +@@ -102,6 +102,7 @@ virCPUDefFree(virCPUDefPtr def) + + virCPUDefFreeModel(def); + VIR_FREE(def->cache); ++ VIR_FREE(def->tsc); + VIR_FREE(def); + } + +@@ -223,6 +224,13 @@ virCPUDefCopyWithoutModel(const virCPUDef *cpu) + *copy->cache = *cpu->cache; + } + ++ if (cpu->tsc) { ++ if (VIR_ALLOC(copy->tsc) < 0) ++ goto error; ++ ++ *copy->tsc = *cpu->tsc; ++ } ++ + return copy; + + error: +@@ -276,6 +284,8 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, + char *cpuMode; + char *fallback = NULL; + char *vendor_id = NULL; ++ char *tscScaling = NULL; ++ virHostCPUTscInfoPtr tsc = NULL; + int ret = -1; + + *cpu = NULL; +@@ -392,6 +402,32 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, + _("invalid microcode version")); + goto cleanup; + } ++ ++ if (virXPathBoolean("boolean(./counter[@name='tsc'])", ctxt) > 0) { ++ if (VIR_ALLOC(tsc) < 0) ++ goto cleanup; ++ ++ if (virXPathULongLong("./counter[@name='tsc']/@frequency", ctxt, ++ &tsc->frequency) < 0) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("Invalid TSC frequency")); ++ goto cleanup; ++ } ++ ++ tscScaling = virXPathString("string(./counter[@name='tsc']/@scaling)", ++ ctxt); ++ if (tscScaling) { ++ int scaling = virTristateBoolTypeFromString(tscScaling); ++ if (scaling < 0) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("Invalid TSC scaling attribute")); ++ goto cleanup; ++ } ++ tsc->scaling = scaling; ++ } ++ ++ VIR_STEAL_PTR(def->tsc, tsc); ++ } + } + + if (!(def->model = virXPathString("string(./model[1])", ctxt)) && +@@ -577,6 +613,8 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, + VIR_FREE(fallback); + VIR_FREE(vendor_id); + VIR_FREE(nodes); ++ VIR_FREE(tscScaling); ++ VIR_FREE(tsc); + virCPUDefFree(def); + return ret; + } +@@ -734,6 +772,16 @@ virCPUDefFormatBuf(virBufferPtr buf, + virBufferAsprintf(buf, "\n", + def->microcodeVersion); + ++ if (def->type == VIR_CPU_TYPE_HOST && def->tsc) { ++ virBufferAddLit(buf, "tsc->frequency); ++ if (def->tsc->scaling) { ++ virBufferAsprintf(buf, " scaling='%s'", ++ virTristateBoolTypeToString(def->tsc->scaling)); ++ } ++ virBufferAddLit(buf, "/>\n"); ++ } ++ + if (def->sockets && def->cores && def->threads) { + virBufferAddLit(buf, "sockets); +diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h +index 9f2e7ee264..5bda4d6961 100644 +--- a/src/conf/cpu_conf.h ++++ b/src/conf/cpu_conf.h +@@ -30,6 +30,7 @@ + # include "virbitmap.h" + # include "virarch.h" + # include "numa_conf.h" ++# include "virhostcpu.h" + + # define VIR_CPU_VENDOR_ID_LENGTH 12 + +@@ -141,6 +142,7 @@ struct _virCPUDef { + size_t nfeatures_max; + virCPUFeatureDefPtr features; + virCPUCacheDefPtr cache; ++ virHostCPUTscInfoPtr tsc; + }; + + +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-gfx-Add-egl-headless-as-a-member-to-virDomainGraphicsDef-struct.patch b/SOURCES/libvirt-conf-gfx-Add-egl-headless-as-a-member-to-virDomainGraphicsDef-struct.patch new file mode 100644 index 0000000..bc32606 --- /dev/null +++ b/SOURCES/libvirt-conf-gfx-Add-egl-headless-as-a-member-to-virDomainGraphicsDef-struct.patch @@ -0,0 +1,43 @@ +From 3af732efb21503e81d31ff600d024b240d6105f3 Mon Sep 17 00:00:00 2001 +Message-Id: <3af732efb21503e81d31ff600d024b240d6105f3@dist-git> +From: Erik Skultety +Date: Tue, 9 Apr 2019 08:34:30 +0200 +Subject: [PATCH] conf: gfx: Add egl-headless as a member to + virDomainGraphicsDef struct +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since we need to specify the rendernode option onto QEMU cmdline, we +need this union member to retain consistency in how we build the +cmdline. + +Signed-off-by: Erik Skultety +Reviewed-by: Ján Tomko +(cherry picked from commit 0a75de221984b971cb841c6918e6746eb22b1547) + +https: //bugzilla.redhat.com/show_bug.cgi?id=1628892 +Signed-off-by: Erik Skultety +Message-Id: <5dc5762e104b6a4729bf6fa9a470f10a6e6c256f.1554791287.git.eskultet@redhat.com> +Reviewed-by: Jiri Denemark +--- + src/conf/domain_conf.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h +index b1139812d5..2d272f907f 100644 +--- a/src/conf/domain_conf.h ++++ b/src/conf/domain_conf.h +@@ -1656,6 +1656,9 @@ struct _virDomainGraphicsDef { + virTristateBool gl; + char *rendernode; + } spice; ++ struct { ++ char *rendernode; ++ } egl_headless; + } data; + /* nListens, listens, and *port are only useful if type is vnc, + * rdp, or spice. They've been extracted from the union only to +-- +2.21.0 + diff --git a/SOURCES/libvirt-conf-gfx-egl-headless-Introduce-a-new-gl-subelement.patch b/SOURCES/libvirt-conf-gfx-egl-headless-Introduce-a-new-gl-subelement.patch new file mode 100644 index 0000000..db82645 --- /dev/null +++ b/SOURCES/libvirt-conf-gfx-egl-headless-Introduce-a-new-gl-subelement.patch @@ -0,0 +1,307 @@ +From a701d9ee0f3e5cd939356191f25d0ec378dbb5c4 Mon Sep 17 00:00:00 2001 +Message-Id: +From: Erik Skultety +Date: Tue, 9 Apr 2019 08:34:31 +0200 +Subject: [PATCH] conf: gfx: egl-headless: Introduce a new subelement +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Unlike with SPICE and SDL which use the subelement to enable OpenGL +acceleration, specifying egl-headless graphics in the XML has +essentially the same meaning, thus in case of egl-headless we don't have +a need for the 'enable' element attribute and we'll only be interested +in the 'rendernode' one further down the road. + +Signed-off-by: Erik Skultety +Reviewed-by: Ján Tomko +(cherry picked from commit 5f931fe39112129efb1204a1aac60b180ef31b42) + +https: //bugzilla.redhat.com/show_bug.cgi?id=1628892 +Signed-off-by: Erik Skultety +Message-Id: +Reviewed-by: Jiri Denemark +--- + docs/formatdomain.html.in | 11 +++-- + docs/schemas/domaincommon.rng | 17 +++++-- + src/conf/domain_conf.c | 45 ++++++++++++++++++- + src/qemu/qemu_process.c | 17 +++++-- + .../graphics-egl-headless-rendernode.xml | 33 ++++++++++++++ + .../graphics-egl-headless-rendernode.xml | 41 +++++++++++++++++ + tests/qemuxml2xmltest.c | 2 + + 7 files changed, 156 insertions(+), 10 deletions(-) + create mode 100644 tests/qemuxml2argvdata/graphics-egl-headless-rendernode.xml + create mode 100644 tests/qemuxml2xmloutdata/graphics-egl-headless-rendernode.xml + +diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in +index 8cf2c12524..e848dc1e0d 100644 +--- a/docs/formatdomain.html.in ++++ b/docs/formatdomain.html.in +@@ -6573,12 +6573,17 @@ qemu-kvm -net nic,model=? /dev/null + the other types, for practical reasons it should be paired with + either vnc or spice graphics types. + This display type is only supported by QEMU domains +- (needs QEMU 2.10 or newer) and doesn't +- accept any attributes. ++ (needs QEMU 2.10 or newer). ++ 5.0.0 this element accepts a ++ <gl/> sub-element with an optional attribute ++ rendernode which can be used to specify an absolute ++ path to a host's DRI device to be used for OpenGL rendering. +

+
+ <graphics type='spice' autoport='yes'/>
+-<graphics type='egl-headless'/>
++<graphics type='egl-headless'>
++  <gl rendernode='/dev/dri/renderD128'/>
++</graphics>
+             
+ + +diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng +index 48f0637cad..f37ee4d354 100644 +--- a/docs/schemas/domaincommon.rng ++++ b/docs/schemas/domaincommon.rng +@@ -3383,9 +3383,20 @@ + + + +- +- egl-headless +- ++ ++ ++ egl-headless ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + + + +diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c +index d079be2bb5..1aef0c76f8 100644 +--- a/src/conf/domain_conf.c ++++ b/src/conf/domain_conf.c +@@ -14274,6 +14274,24 @@ virDomainGraphicsDefParseXMLSpice(virDomainGraphicsDefPtr def, + } + + ++static int ++virDomainGraphicsDefParseXMLEGLHeadless(virDomainGraphicsDefPtr def, ++ xmlNodePtr node, ++ xmlXPathContextPtr ctxt) ++{ ++ xmlNodePtr save = ctxt->node; ++ xmlNodePtr glNode; ++ ++ ctxt->node = node; ++ ++ if ((glNode = virXPathNode("./gl", ctxt))) ++ def->data.egl_headless.rendernode = virXMLPropString(glNode, ++ "rendernode"); ++ ctxt->node = save; ++ return 0; ++} ++ ++ + /* Parse the XML definition for a graphics device */ + static virDomainGraphicsDefPtr + virDomainGraphicsDefParseXML(xmlNodePtr node, +@@ -14323,6 +14341,9 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, + goto error; + break; + case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: ++ if (virDomainGraphicsDefParseXMLEGLHeadless(def, node, ctxt) < 0) ++ goto error; ++ break; + case VIR_DOMAIN_GRAPHICS_TYPE_LAST: + break; + } +@@ -26724,6 +26745,20 @@ virDomainGraphicsDefFormat(virBufferPtr buf, + break; + + case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: ++ if (!def->data.egl_headless.rendernode) ++ break; ++ ++ if (!children) { ++ virBufferAddLit(buf, ">\n"); ++ virBufferAdjustIndent(buf, 2); ++ children = true; ++ } ++ ++ virBufferAddLit(buf, "data.egl_headless.rendernode); ++ virBufferAddLit(buf, "/>\n"); ++ break; + case VIR_DOMAIN_GRAPHICS_TYPE_LAST: + break; + } +@@ -30718,7 +30753,13 @@ virDomainGraphicsDefHasOpenGL(const virDomainDef *def) + bool + virDomainGraphicsSupportsRenderNode(const virDomainGraphicsDef *graphics) + { +- return graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE; ++ bool ret = false; ++ ++ if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE || ++ graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS) ++ ret = true; ++ ++ return ret; + } + + +@@ -30733,6 +30774,8 @@ virDomainGraphicsGetRenderNode(const virDomainGraphicsDef *graphics) + ret = graphics->data.spice.rendernode; + break; + case VIR_DOMAIN_GRAPHICS_TYPE_EGL_HEADLESS: ++ ret = graphics->data.egl_headless.rendernode; ++ break; + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + case VIR_DOMAIN_GRAPHICS_TYPE_RDP: +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 465dabd8e3..8811aefb95 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -4755,14 +4755,25 @@ static int + qemuProcessGraphicsSetupRenderNode(virDomainGraphicsDefPtr graphics, + virQEMUCapsPtr qemuCaps) + { ++ char **rendernode = NULL; ++ + if (!virDomainGraphicsNeedsAutoRenderNode(graphics)) + return 0; + + /* Don't bother picking a DRM node if QEMU doesn't support it. */ +- if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_RENDERNODE)) +- return 0; ++ if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SPICE) { ++ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SPICE_RENDERNODE)) ++ return 0; + +- if (!(graphics->data.spice.rendernode = virHostGetDRMRenderNode())) ++ rendernode = &graphics->data.spice.rendernode; ++ } else { ++ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_EGL_HEADLESS_RENDERNODE)) ++ return 0; ++ ++ rendernode = &graphics->data.egl_headless.rendernode; ++ } ++ ++ if (!(*rendernode = virHostGetDRMRenderNode())) + return -1; + + return 0; +diff --git a/tests/qemuxml2argvdata/graphics-egl-headless-rendernode.xml b/tests/qemuxml2argvdata/graphics-egl-headless-rendernode.xml +new file mode 100644 +index 0000000000..a8d54e75da +--- /dev/null ++++ b/tests/qemuxml2argvdata/graphics-egl-headless-rendernode.xml +@@ -0,0 +1,33 @@ ++ ++ QEMUGuest1 ++ c7a5fdbd-edaf-9455-926a-d65c16db1809 ++ 219100 ++ 219100 ++ 1 ++ ++ hvm ++ ++ ++ ++ destroy ++ restart ++ destroy ++ ++ /usr/bin/qemu-system-i686 ++ ++ ++ ++ ++
++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/qemuxml2xmloutdata/graphics-egl-headless-rendernode.xml b/tests/qemuxml2xmloutdata/graphics-egl-headless-rendernode.xml +new file mode 100644 +index 0000000000..9b7ac89928 +--- /dev/null ++++ b/tests/qemuxml2xmloutdata/graphics-egl-headless-rendernode.xml +@@ -0,0 +1,41 @@ ++ ++ QEMUGuest1 ++ c7a5fdbd-edaf-9455-926a-d65c16db1809 ++ 219100 ++ 219100 ++ 1 ++ ++ hvm ++ ++ ++ ++ destroy ++ restart ++ destroy ++ ++ /usr/bin/qemu-system-i686 ++ ++ ++ ++ ++
++ ++ ++
++ ++ ++
++ ++ ++ ++ ++ ++ ++ ++