diff --git a/SOURCES/libvirt-build-Only-install-libvirt-guests-when-building-libvirtd.patch b/SOURCES/libvirt-build-Only-install-libvirt-guests-when-building-libvirtd.patch
new file mode 100644
index 0000000..c02569a
--- /dev/null
+++ b/SOURCES/libvirt-build-Only-install-libvirt-guests-when-building-libvirtd.patch
@@ -0,0 +1,75 @@
+From b0fb5cbba2e03fbca8471487bf78931b3090b108 Mon Sep 17 00:00:00 2001
+Message-Id: <b0fb5cbba2e03fbca8471487bf78931b3090b108@dist-git>
+From: Jim Fehlig <jfehlig@suse.com>
+Date: Mon, 10 Jan 2022 11:42:58 -0700
+Subject: [PATCH] build: Only install libvirt-guests when building libvirtd
+
+libvirt-guests was already moved to the libvirt daemon package in commit
+d800c50349. It only needs to be installed when building libvirtd.
+
+Signed-off-by: Jim Fehlig <jfehlig@suse.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+(cherry picked from commit 3be5ba11a2c6fcb2dfdffa03ab4f847113f36b85)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2153688
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ tools/meson.build | 38 ++++++++++++++++++++------------------
+ 1 file changed, 20 insertions(+), 18 deletions(-)
+
+diff --git a/tools/meson.build b/tools/meson.build
+index 22fa3604ba..2d0aecb90b 100644
+--- a/tools/meson.build
++++ b/tools/meson.build
+@@ -297,29 +297,31 @@ if conf.has('WITH_SANLOCK')
+   )
+ endif
+ 
+-configure_file(
+-  input: 'libvirt-guests.sh.in',
+-  output: '@BASENAME@',
+-  configuration: tools_conf,
+-  install: true,
+-  install_dir: libexecdir,
+-  install_mode: 'rwxrwxr-x',
+-)
+-
+-if init_script == 'systemd'
+-  install_data(
+-    'libvirt-guests.sysconf',
+-    install_dir: sysconfdir / 'sysconfig',
+-    rename: 'libvirt-guests',
+-  )
+-
++if conf.has('WITH_LIBVIRTD')
+   configure_file(
+-    input: 'libvirt-guests.service.in',
++    input: 'libvirt-guests.sh.in',
+     output: '@BASENAME@',
+     configuration: tools_conf,
+     install: true,
+-    install_dir: prefix / 'lib' / 'systemd' / 'system',
++    install_dir: libexecdir,
++    install_mode: 'rwxrwxr-x',
+   )
++
++  if init_script == 'systemd'
++    install_data(
++      'libvirt-guests.sysconf',
++      install_dir: sysconfdir / 'sysconfig',
++      rename: 'libvirt-guests',
++    )
++
++    configure_file(
++      input: 'libvirt-guests.service.in',
++      output: '@BASENAME@',
++      configuration: tools_conf,
++      install: true,
++      install_dir: prefix / 'lib' / 'systemd' / 'system',
++    )
++  endif
+ endif
+ 
+ if bash_completion_dep.found()
+-- 
+2.39.0
+
diff --git a/SOURCES/libvirt-conf-adjust-method-name-virDomainDeviceCCWAddressParseXML.patch b/SOURCES/libvirt-conf-adjust-method-name-virDomainDeviceCCWAddressParseXML.patch
new file mode 100644
index 0000000..11e3e70
--- /dev/null
+++ b/SOURCES/libvirt-conf-adjust-method-name-virDomainDeviceCCWAddressParseXML.patch
@@ -0,0 +1,88 @@
+From 3c65b917f70d556fa1059b0400771c8159b8ca3b Mon Sep 17 00:00:00 2001
+Message-Id: <3c65b917f70d556fa1059b0400771c8159b8ca3b@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:08 +0200
+Subject: [PATCH] conf: adjust method name virDomainDeviceCCWAddressParseXML
+
+Adjust method name virDomainDeviceCCWAddressParseXML to
+virCCWDeviceAddressParseXML.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 2d9fd19bf5d7a3d33b94e464c335252682edd623)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/device_conf.c   | 4 ++--
+ src/conf/device_conf.h   | 4 ++--
+ src/conf/domain_conf.c   | 3 +--
+ src/libvirt_private.syms | 2 +-
+ 4 files changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
+index 958e2f43cc..e93fd57341 100644
+--- a/src/conf/device_conf.c
++++ b/src/conf/device_conf.c
+@@ -259,8 +259,8 @@ virPCIDeviceAddressFormat(virBuffer *buf,
+ }
+ 
+ int
+-virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
+-                                  virCCWDeviceAddress *addr)
++virCCWDeviceAddressParseXML(xmlNodePtr node,
++                            virCCWDeviceAddress *addr)
+ {
+     int cssid;
+     int ssid;
+diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
+index 01e2edccc9..910e6b7792 100644
+--- a/src/conf/device_conf.h
++++ b/src/conf/device_conf.h
+@@ -193,8 +193,8 @@ void virPCIDeviceAddressFormat(virBuffer *buf,
+                                virPCIDeviceAddress addr,
+                                bool includeTypeInAddr);
+ 
+-int virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
+-                                      virCCWDeviceAddress *addr);
++int virCCWDeviceAddressParseXML(xmlNodePtr node,
++                                virCCWDeviceAddress *addr);
+ 
+ int virDomainDeviceDriveAddressParseXML(xmlNodePtr node,
+                                         virDomainDeviceDriveAddress *addr);
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 1e1c7f01b1..401ddaa1a0 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -6630,8 +6630,7 @@ virDomainDeviceAddressParseXML(xmlNodePtr address,
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
+-        if (virDomainDeviceCCWAddressParseXML
+-                (address, &info->addr.ccw) < 0)
++        if (virCCWDeviceAddressParseXML(address, &info->addr.ccw) < 0)
+             return -1;
+         break;
+ 
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 0d3ee4c20a..44b551fb60 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -124,6 +124,7 @@ virCPUModeTypeToString;
+ 
+ 
+ # conf/device_conf.h
++virCCWDeviceAddressParseXML;
+ virDeviceInfoPCIAddressExtensionIsPresent;
+ virDeviceInfoPCIAddressExtensionIsWanted;
+ virDeviceInfoPCIAddressIsPresent;
+@@ -131,7 +132,6 @@ virDeviceInfoPCIAddressIsWanted;
+ virDomainDeviceAddressIsValid;
+ virDomainDeviceAddressTypeToString;
+ virDomainDeviceCcidAddressParseXML;
+-virDomainDeviceCCWAddressParseXML;
+ virDomainDeviceDriveAddressParseXML;
+ virDomainDeviceInfoAddressIsEqual;
+ virDomainDeviceSpaprVioAddressParseXML;
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-nodedev-add-optional-device-address-of-channel-device-to-css-device.patch b/SOURCES/libvirt-nodedev-add-optional-device-address-of-channel-device-to-css-device.patch
new file mode 100644
index 0000000..b867ca3
--- /dev/null
+++ b/SOURCES/libvirt-nodedev-add-optional-device-address-of-channel-device-to-css-device.patch
@@ -0,0 +1,151 @@
+From 5921eeddf0a284ccbec04896901c9bd4177de6dd Mon Sep 17 00:00:00 2001
+Message-Id: <5921eeddf0a284ccbec04896901c9bd4177de6dd@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:15 +0200
+Subject: [PATCH] nodedev: add optional device address of channel device to css
+ device
+
+Add the new introduced sysfs attribute dev_busid which provides the address
+of the device in the subchannel independent from the bound device driver.
+It is added if available in the sysfs as optional channel_dev_addr element into
+the css device capabilty providing the ccw deivce address attributes cssid,
+ssid and devno.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 122b975e4004c83b6fc442ec6cdfd71eb5b55cc4)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ docs/schemas/nodedev.rng           |  5 +++++
+ src/conf/node_device_conf.c        | 28 ++++++++++++++++++++++++++++
+ src/conf/node_device_conf.h        |  2 ++
+ src/node_device/node_device_udev.c |  8 ++++++++
+ 4 files changed, 43 insertions(+)
+
+diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng
+index 29515d2d7e..43f1abc247 100644
+--- a/docs/schemas/nodedev.rng
++++ b/docs/schemas/nodedev.rng
+@@ -677,6 +677,11 @@
+       <value>css</value>
+     </attribute>
+     <ref name="capccwaddress"/>
++    <optional>
++      <element name="channel_dev_addr">
++        <ref name="capccwaddress"/>
++      </element>
++    </optional>
+     <optional>
+       <ref name="mdev_types"/>
+     </optional>
+diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
+index fcb5be24e1..16b9497faf 100644
+--- a/src/conf/node_device_conf.c
++++ b/src/conf/node_device_conf.c
+@@ -643,6 +643,17 @@ virNodeDeviceCapCSSDefFormat(virBuffer *buf,
+ 
+     virNodeDeviceCapCCWDefFormat(buf, data);
+ 
++    if (ccw_dev.channel_dev_addr) {
++        virCCWDeviceAddress *ccw = ccw_dev.channel_dev_addr;
++        virBufferAddLit(buf, "<channel_dev_addr>\n");
++        virBufferAdjustIndent(buf, 2);
++        virBufferAsprintf(buf, "<cssid>0x%x</cssid>\n", ccw->cssid);
++        virBufferAsprintf(buf, "<ssid>0x%x</ssid>\n", ccw->ssid);
++        virBufferAsprintf(buf, "<devno>0x%04x</devno>\n", ccw->devno);
++        virBufferAdjustIndent(buf, -2);
++        virBufferAddLit(buf, "</channel_dev_addr>\n");
++    }
++
+     if (ccw_dev.flags & VIR_NODE_DEV_CAP_FLAG_CSS_MDEV)
+         virNodeDeviceCapMdevTypesFormat(buf,
+                                         ccw_dev.mdev_types,
+@@ -1255,6 +1266,7 @@ virNodeDevCapCSSParseXML(xmlXPathContextPtr ctxt,
+     g_autofree xmlNodePtr *nodes = NULL;
+     int n = 0;
+     size_t i = 0;
++    xmlNodePtr channel_ddno = NULL;
+ 
+     ctxt->node = node;
+ 
+@@ -1269,6 +1281,21 @@ virNodeDevCapCSSParseXML(xmlXPathContextPtr ctxt,
+             return -1;
+     }
+ 
++    /* channel_dev_addr is optional */
++    if ((channel_ddno = virXPathNode("./channel_dev_addr[1]", ctxt))) {
++        g_autofree virCCWDeviceAddress *channel_dev = NULL;
++
++        channel_dev = g_new0(virCCWDeviceAddress, 1);
++
++        if (virNodeDevCCWDeviceAddressParseXML(ctxt,
++                                               channel_ddno,
++                                               def->name,
++                                               channel_dev) < 0)
++            return -1;
++
++        ccw_dev->channel_dev_addr = g_steal_pointer(&channel_dev);
++    }
++
+     return 0;
+ }
+ 
+@@ -2637,6 +2664,7 @@ virNodeDevCapsDefFree(virNodeDevCapsDef *caps)
+         for (i = 0; i < data->ccw_dev.nmdev_types; i++)
+             virMediatedDeviceTypeFree(data->ccw_dev.mdev_types[i]);
+         g_free(data->ccw_dev.mdev_types);
++        g_free(data->ccw_dev.channel_dev_addr);
+         break;
+     case VIR_NODE_DEV_CAP_AP_MATRIX:
+         g_free(data->ap_matrix.addr);
+diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h
+index e4d1f67d53..d1751ed874 100644
+--- a/src/conf/node_device_conf.h
++++ b/src/conf/node_device_conf.h
+@@ -24,6 +24,7 @@
+ 
+ #include "internal.h"
+ #include "virbitmap.h"
++#include "virccw.h"
+ #include "virpcivpd.h"
+ #include "virscsihost.h"
+ #include "virpci.h"
+@@ -279,6 +280,7 @@ struct _virNodeDevCapCCW {
+     unsigned int flags; /* enum virNodeDevCCWCapFlags */
+     virMediatedDeviceType **mdev_types;
+     size_t nmdev_types;
++    virCCWDeviceAddress *channel_dev_addr;
+ };
+ 
+ typedef struct _virNodeDevCapVDPA virNodeDevCapVDPA;
+diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
+index ffcb3e8640..611a2592ca 100644
+--- a/src/node_device/node_device_udev.c
++++ b/src/node_device/node_device_udev.c
+@@ -1128,6 +1128,8 @@ static int
+ udevProcessCSS(struct udev_device *device,
+                virNodeDeviceDef *def)
+ {
++    g_autofree char *dev_busid = NULL;
++
+     /* only process IO subchannel and vfio-ccw devices to keep the list sane */
+     if (!def->driver ||
+         (STRNEQ(def->driver, "io_subchannel") &&
+@@ -1139,6 +1141,12 @@ udevProcessCSS(struct udev_device *device,
+ 
+     udevGenerateDeviceName(device, def, NULL);
+ 
++    /* process optional channel devices information */
++    udevGetStringSysfsAttr(device, "dev_busid", &dev_busid);
++
++    if (dev_busid != NULL)
++        def->caps->data.ccw_dev.channel_dev_addr = virCCWDeviceAddressFromString(dev_busid);
++
+     if (virNodeDeviceGetCSSDynamicCaps(def->sysfs_path, &def->caps->data.ccw_dev) < 0)
+         return -1;
+ 
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-nodedev-add-tests-for-optional-device-address-to-css-device.patch b/SOURCES/libvirt-nodedev-add-tests-for-optional-device-address-to-css-device.patch
new file mode 100644
index 0000000..2ee8544
--- /dev/null
+++ b/SOURCES/libvirt-nodedev-add-tests-for-optional-device-address-to-css-device.patch
@@ -0,0 +1,149 @@
+From ea4976de7bccfe8016950d040629a6818a58db4e Mon Sep 17 00:00:00 2001
+Message-Id: <ea4976de7bccfe8016950d040629a6818a58db4e@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:16 +0200
+Subject: [PATCH] nodedev: add tests for optional device address to css device
+
+Add nodedev schema parsing and format tests for the optional new device
+address on the css devices.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 127fda5e84790af2c5a16b61a87e339391cccb3b)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ .../css_0_0_10000-invalid.xml                 | 10 +++++++++
+ ...s_0_0_fffe_mdev_types_channel_dev_addr.xml | 22 +++++++++++++++++++
+ .../css_0_0_ffff_channel_dev_addr-invalid.xml | 15 +++++++++++++
+ .../css_0_0_ffff_channel_dev_addr.xml         | 15 +++++++++++++
+ ...s_0_0_fffe_mdev_types_channel_dev_addr.xml |  1 +
+ .../css_0_0_ffff_channel_dev_addr.xml         |  1 +
+ tests/nodedevxml2xmltest.c                    |  2 ++
+ 7 files changed, 66 insertions(+)
+ create mode 100644 tests/nodedevschemadata/css_0_0_10000-invalid.xml
+ create mode 100644 tests/nodedevschemadata/css_0_0_fffe_mdev_types_channel_dev_addr.xml
+ create mode 100644 tests/nodedevschemadata/css_0_0_ffff_channel_dev_addr-invalid.xml
+ create mode 100644 tests/nodedevschemadata/css_0_0_ffff_channel_dev_addr.xml
+ create mode 120000 tests/nodedevxml2xmlout/css_0_0_fffe_mdev_types_channel_dev_addr.xml
+ create mode 120000 tests/nodedevxml2xmlout/css_0_0_ffff_channel_dev_addr.xml
+
+diff --git a/tests/nodedevschemadata/css_0_0_10000-invalid.xml b/tests/nodedevschemadata/css_0_0_10000-invalid.xml
+new file mode 100644
+index 0000000000..740bb489a7
+--- /dev/null
++++ b/tests/nodedevschemadata/css_0_0_10000-invalid.xml
+@@ -0,0 +1,10 @@
++<device>
++  <name>css_0_0_10000</name>
++  <path>/sys/devices/css0/0.0.10000</path>
++  <parent>computer</parent>
++  <capability type='css'>
++    <cssid>0x0</cssid>
++    <ssid>0x0</ssid>
++    <devno>0x10000</devno>
++  </capability>
++</device>
+diff --git a/tests/nodedevschemadata/css_0_0_fffe_mdev_types_channel_dev_addr.xml b/tests/nodedevschemadata/css_0_0_fffe_mdev_types_channel_dev_addr.xml
+new file mode 100644
+index 0000000000..198dcb0cb0
+--- /dev/null
++++ b/tests/nodedevschemadata/css_0_0_fffe_mdev_types_channel_dev_addr.xml
+@@ -0,0 +1,22 @@
++<device>
++  <name>css_0_0_fffe</name>
++  <path>/sys/devices/css0/0.0.fffe</path>
++  <parent>computer</parent>
++  <capability type='css'>
++    <cssid>0x0</cssid>
++    <ssid>0x0</ssid>
++    <devno>0xfffe</devno>
++    <channel_dev_addr>
++      <cssid>0x0</cssid>
++      <ssid>0x0</ssid>
++      <devno>0x0815</devno>
++    </channel_dev_addr>
++    <capability type='mdev_types'>
++      <type id='vfio_ccw-io'>
++        <name>I/O subchannel (Non-QDIO)</name>
++        <deviceAPI>vfio-ccw</deviceAPI>
++        <availableInstances>1</availableInstances>
++      </type>
++    </capability>
++  </capability>
++</device>
+diff --git a/tests/nodedevschemadata/css_0_0_ffff_channel_dev_addr-invalid.xml b/tests/nodedevschemadata/css_0_0_ffff_channel_dev_addr-invalid.xml
+new file mode 100644
+index 0000000000..3f2c5558c7
+--- /dev/null
++++ b/tests/nodedevschemadata/css_0_0_ffff_channel_dev_addr-invalid.xml
+@@ -0,0 +1,15 @@
++<device>
++  <name>css_0_0_ffff</name>
++  <path>/sys/devices/css0/0.0.ffff</path>
++  <parent>computer</parent>
++  <capability type='css'>
++    <cssid>0x0</cssid>
++    <ssid>0x0</ssid>
++    <devno>0xffff</devno>
++    <channel_dev_addr>
++      <cssid>0x0</cssid>
++      <ssid>0x0</ssid>
++      <devno>0x10000</devno>
++    </channel_dev_addr>
++  </capability>
++</device>
+diff --git a/tests/nodedevschemadata/css_0_0_ffff_channel_dev_addr.xml b/tests/nodedevschemadata/css_0_0_ffff_channel_dev_addr.xml
+new file mode 100644
+index 0000000000..17a77cb282
+--- /dev/null
++++ b/tests/nodedevschemadata/css_0_0_ffff_channel_dev_addr.xml
+@@ -0,0 +1,15 @@
++<device>
++  <name>css_0_0_ffff</name>
++  <path>/sys/devices/css0/0.0.ffff</path>
++  <parent>computer</parent>
++  <capability type='css'>
++    <cssid>0x0</cssid>
++    <ssid>0x0</ssid>
++    <devno>0xffff</devno>
++    <channel_dev_addr>
++      <cssid>0x0</cssid>
++      <ssid>0x0</ssid>
++      <devno>0x0815</devno>
++    </channel_dev_addr>
++  </capability>
++</device>
+diff --git a/tests/nodedevxml2xmlout/css_0_0_fffe_mdev_types_channel_dev_addr.xml b/tests/nodedevxml2xmlout/css_0_0_fffe_mdev_types_channel_dev_addr.xml
+new file mode 120000
+index 0000000000..65ab582ee8
+--- /dev/null
++++ b/tests/nodedevxml2xmlout/css_0_0_fffe_mdev_types_channel_dev_addr.xml
+@@ -0,0 +1 @@
++../nodedevschemadata/css_0_0_fffe_mdev_types_channel_dev_addr.xml
+\ No newline at end of file
+diff --git a/tests/nodedevxml2xmlout/css_0_0_ffff_channel_dev_addr.xml b/tests/nodedevxml2xmlout/css_0_0_ffff_channel_dev_addr.xml
+new file mode 120000
+index 0000000000..cbfe719777
+--- /dev/null
++++ b/tests/nodedevxml2xmlout/css_0_0_ffff_channel_dev_addr.xml
+@@ -0,0 +1 @@
++../nodedevschemadata/css_0_0_ffff_channel_dev_addr.xml
+\ No newline at end of file
+diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c
+index 557347fb07..ad9562cc82 100644
+--- a/tests/nodedevxml2xmltest.c
++++ b/tests/nodedevxml2xmltest.c
+@@ -125,7 +125,9 @@ mymain(void)
+     DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b");
+     DO_TEST("ccw_0_0_ffff");
+     DO_TEST("css_0_0_ffff");
++    DO_TEST("css_0_0_ffff_channel_dev_addr");
+     DO_TEST("css_0_0_fffe_mdev_types");
++    DO_TEST("css_0_0_fffe_mdev_types_channel_dev_addr");
+     DO_TEST("ap_card07");
+     DO_TEST("ap_07_0038");
+     DO_TEST("ap_matrix");
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-nodedev-fix-reported-error-msg-in-css-cap-XML-parsing.patch b/SOURCES/libvirt-nodedev-fix-reported-error-msg-in-css-cap-XML-parsing.patch
new file mode 100644
index 0000000..952dd3f
--- /dev/null
+++ b/SOURCES/libvirt-nodedev-fix-reported-error-msg-in-css-cap-XML-parsing.patch
@@ -0,0 +1,32 @@
+From d82e4473a66da27d2c6f41f8ecadacbd00f44430 Mon Sep 17 00:00:00 2001
+Message-Id: <d82e4473a66da27d2c6f41f8ecadacbd00f44430@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:00 +0200
+Subject: [PATCH] nodedev: fix reported error msg in css cap XML parsing
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 78094a4bd1562fec73ae99c67ddcbedd83953d5c)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/node_device_conf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
+index 0bac0fde8d..a6ebf4b66f 100644
+--- a/src/conf/node_device_conf.c
++++ b/src/conf/node_device_conf.c
+@@ -1193,7 +1193,7 @@ virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
+     if (virStrToLong_uip(ssid, NULL, 0, &ccw_dev->ssid) < 0) {
+         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                        _("invalid ssid value '%s' for '%s'"),
+-                       cssid, def->name);
++                       ssid, def->name);
+         return -1;
+     }
+ 
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-nodedev-prevent-internal-error-on-dev_busid-parse.patch b/SOURCES/libvirt-nodedev-prevent-internal-error-on-dev_busid-parse.patch
new file mode 100644
index 0000000..144e29c
--- /dev/null
+++ b/SOURCES/libvirt-nodedev-prevent-internal-error-on-dev_busid-parse.patch
@@ -0,0 +1,35 @@
+From 7c60078d7a6442dc8cb5a711876d28f70d892bff Mon Sep 17 00:00:00 2001
+Message-Id: <7c60078d7a6442dc8cb5a711876d28f70d892bff@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Mon, 23 May 2022 17:56:21 +0200
+Subject: [PATCH] nodedev: prevent internal error on dev_busid parse
+
+As "none" is a legal value represented in the sysfs attribute dev_busid
+this patch prevents libvirt from incorrectly reporting an internal error.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Suggested-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit e37c39747be0792d03c450e56ddb3c78d08cbf3e)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/node_device/node_device_udev.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
+index 611a2592ca..b76e3de681 100644
+--- a/src/node_device/node_device_udev.c
++++ b/src/node_device/node_device_udev.c
+@@ -1144,7 +1144,7 @@ udevProcessCSS(struct udev_device *device,
+     /* process optional channel devices information */
+     udevGetStringSysfsAttr(device, "dev_busid", &dev_busid);
+ 
+-    if (dev_busid != NULL)
++    if (dev_busid != NULL && STRNEQ(dev_busid, "none"))
+         def->caps->data.ccw_dev.channel_dev_addr = virCCWDeviceAddressFromString(dev_busid);
+ 
+     if (virNodeDeviceGetCSSDynamicCaps(def->sysfs_path, &def->caps->data.ccw_dev) < 0)
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-nodedev-refactor-ccw-device-address-parsing-from-XML.patch b/SOURCES/libvirt-nodedev-refactor-ccw-device-address-parsing-from-XML.patch
new file mode 100644
index 0000000..ae4eba5
--- /dev/null
+++ b/SOURCES/libvirt-nodedev-refactor-ccw-device-address-parsing-from-XML.patch
@@ -0,0 +1,140 @@
+From ef8c30a091b5b0f08f9405878b49c21c5525dd0a Mon Sep 17 00:00:00 2001
+Message-Id: <ef8c30a091b5b0f08f9405878b49c21c5525dd0a@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:12 +0200
+Subject: [PATCH] nodedev: refactor ccw device address parsing from XML
+
+Move ccw device address XML parsing into new method for later reuse.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 4402295d371a62ab8632d23002283b8a7721e6a7)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/node_device_conf.c | 96 ++++++++++++++++++++++---------------
+ 1 file changed, 58 insertions(+), 38 deletions(-)
+
+diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
+index 1e00f65717..8982368465 100644
+--- a/src/conf/node_device_conf.c
++++ b/src/conf/node_device_conf.c
+@@ -1141,6 +1141,58 @@ virNodeDevAPMatrixCapabilityParseXML(xmlXPathContextPtr ctxt,
+ }
+ 
+ 
++static int
++virNodeDevCCWDeviceAddressParseXML(xmlXPathContextPtr ctxt,
++                                   xmlNodePtr node,
++                                   const char *dev_name,
++                                   virCCWDeviceAddress *ccw_addr)
++{
++    VIR_XPATH_NODE_AUTORESTORE(ctxt)
++    g_autofree char *cssid = NULL;
++    g_autofree char *ssid = NULL;
++    g_autofree char *devno = NULL;
++
++    ctxt->node = node;
++
++    if (!(cssid = virXPathString("string(./cssid[1])", ctxt))) {
++        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++                       _("missing cssid value for '%s'"), dev_name);
++        return -1;
++    }
++    if (virStrToLong_uip(cssid, NULL, 0, &ccw_addr->cssid) < 0) {
++        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++                       _("invalid cssid value '%s' for '%s'"),
++                       cssid, dev_name);
++        return -1;
++    }
++
++    if (!(ssid = virXPathString("string(./ssid[1])", ctxt))) {
++        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++                       _("missing ssid value for '%s'"), dev_name);
++        return -1;
++    }
++    if (virStrToLong_uip(ssid, NULL, 0, &ccw_addr->ssid) < 0) {
++        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++                       _("invalid ssid value '%s' for '%s'"),
++                       ssid, dev_name);
++        return -1;
++    }
++
++    if (!(devno = virXPathString("string(./devno[1])", ctxt))) {
++        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++                       _("missing devno value for '%s'"), dev_name);
++        return -1;
++    }
++    if (virStrToLong_uip(devno, NULL, 16, &ccw_addr->devno) < 0) {
++        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++                       _("invalid devno value '%s' for '%s'"),
++                       devno, dev_name);
++        return -1;
++    }
++
++    return 0;
++}
++
+ static int
+ virNodeDevCSSCapabilityParseXML(xmlXPathContextPtr ctxt,
+                                 xmlNodePtr node,
+@@ -1178,50 +1230,18 @@ virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
+     g_autofree xmlNodePtr *nodes = NULL;
+     int n = 0;
+     size_t i = 0;
+-    g_autofree char *cssid = NULL;
+-    g_autofree char *ssid = NULL;
+-    g_autofree char *devno = NULL;
++    g_autofree virCCWDeviceAddress *ccw_addr = NULL;
+ 
+     ctxt->node = node;
+ 
+-    if (!(cssid = virXPathString("string(./cssid[1])", ctxt))) {
+-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+-                       _("missing cssid value for '%s'"), def->name);
+-        return -1;
+-    }
+-
+-    if (virStrToLong_uip(cssid, NULL, 0, &ccw_dev->cssid) < 0) {
+-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+-                       _("invalid cssid value '%s' for '%s'"),
+-                       cssid, def->name);
+-        return -1;
+-    }
+-
+-    if (!(ssid = virXPathString("string(./ssid[1])", ctxt))) {
+-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+-                       _("missing ssid value for '%s'"), def->name);
+-        return -1;
+-    }
++    ccw_addr = g_new0(virCCWDeviceAddress, 1);
+ 
+-    if (virStrToLong_uip(ssid, NULL, 0, &ccw_dev->ssid) < 0) {
+-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+-                       _("invalid ssid value '%s' for '%s'"),
+-                       ssid, def->name);
++    if (virNodeDevCCWDeviceAddressParseXML(ctxt, node, def->name, ccw_addr) < 0)
+         return -1;
+-    }
+ 
+-    if (!(devno = virXPathString("string(./devno[1])", ctxt))) {
+-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+-                       _("missing devno value for '%s'"), def->name);
+-        return -1;
+-    }
+-
+-    if (virStrToLong_uip(devno, NULL, 16, &ccw_dev->devno) < 0) {
+-        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+-                       _("invalid devno value '%s' for '%s'"),
+-                       devno, def->name);
+-        return -1;
+-    }
++    ccw_dev->cssid = ccw_addr->cssid;
++    ccw_dev->ssid = ccw_addr->ssid;
++    ccw_dev->devno = ccw_addr->devno;
+ 
+     if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
+         return -1;
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-nodedev-refactor-css-XML-parsing-from-ccw-XML-parsing.patch b/SOURCES/libvirt-nodedev-refactor-css-XML-parsing-from-ccw-XML-parsing.patch
new file mode 100644
index 0000000..209f414
--- /dev/null
+++ b/SOURCES/libvirt-nodedev-refactor-css-XML-parsing-from-ccw-XML-parsing.patch
@@ -0,0 +1,99 @@
+From 286c821eee3b682d6aa4aeaa13aad92382708803 Mon Sep 17 00:00:00 2001
+Message-Id: <286c821eee3b682d6aa4aeaa13aad92382708803@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:13 +0200
+Subject: [PATCH] nodedev: refactor css XML parsing from ccw XML parsing
+
+In preparation for easier extension later.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 245ff2d6634b3afb0dbf0d295051e458095bfc80)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/node_device_conf.c | 40 +++++++++++++++++++++++++++----------
+ 1 file changed, 30 insertions(+), 10 deletions(-)
+
+diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
+index 8982368465..fcb5be24e1 100644
+--- a/src/conf/node_device_conf.c
++++ b/src/conf/node_device_conf.c
+@@ -1193,6 +1193,31 @@ virNodeDevCCWDeviceAddressParseXML(xmlXPathContextPtr ctxt,
+     return 0;
+ }
+ 
++
++static int
++virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
++                         virNodeDeviceDef *def,
++                         xmlNodePtr node,
++                         virNodeDevCapCCW *ccw_dev)
++{
++    VIR_XPATH_NODE_AUTORESTORE(ctxt)
++    g_autofree virCCWDeviceAddress *ccw_addr = NULL;
++
++    ctxt->node = node;
++
++    ccw_addr = g_new0(virCCWDeviceAddress, 1);
++
++    if (virNodeDevCCWDeviceAddressParseXML(ctxt, node, def->name, ccw_addr) < 0)
++        return -1;
++
++    ccw_dev->cssid = ccw_addr->cssid;
++    ccw_dev->ssid = ccw_addr->ssid;
++    ccw_dev->devno = ccw_addr->devno;
++
++    return 0;
++}
++
++
+ static int
+ virNodeDevCSSCapabilityParseXML(xmlXPathContextPtr ctxt,
+                                 xmlNodePtr node,
+@@ -1221,7 +1246,7 @@ virNodeDevCSSCapabilityParseXML(xmlXPathContextPtr ctxt,
+ 
+ 
+ static int
+-virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
++virNodeDevCapCSSParseXML(xmlXPathContextPtr ctxt,
+                          virNodeDeviceDef *def,
+                          xmlNodePtr node,
+                          virNodeDevCapCCW *ccw_dev)
+@@ -1230,19 +1255,12 @@ virNodeDevCapCCWParseXML(xmlXPathContextPtr ctxt,
+     g_autofree xmlNodePtr *nodes = NULL;
+     int n = 0;
+     size_t i = 0;
+-    g_autofree virCCWDeviceAddress *ccw_addr = NULL;
+ 
+     ctxt->node = node;
+ 
+-    ccw_addr = g_new0(virCCWDeviceAddress, 1);
+-
+-    if (virNodeDevCCWDeviceAddressParseXML(ctxt, node, def->name, ccw_addr) < 0)
++    if (virNodeDevCapCCWParseXML(ctxt, def, node, ccw_dev) < 0)
+         return -1;
+ 
+-    ccw_dev->cssid = ccw_addr->cssid;
+-    ccw_dev->ssid = ccw_addr->ssid;
+-    ccw_dev->devno = ccw_addr->devno;
+-
+     if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
+         return -1;
+ 
+@@ -2282,9 +2300,11 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
+         ret = virNodeDevCapMdevParseXML(ctxt, def, node, &caps->data.mdev);
+         break;
+     case VIR_NODE_DEV_CAP_CCW_DEV:
+-    case VIR_NODE_DEV_CAP_CSS_DEV:
+         ret = virNodeDevCapCCWParseXML(ctxt, def, node, &caps->data.ccw_dev);
+         break;
++    case VIR_NODE_DEV_CAP_CSS_DEV:
++        ret = virNodeDevCapCSSParseXML(ctxt, def, node, &caps->data.ccw_dev);
++        break;
+     case VIR_NODE_DEV_CAP_AP_CARD:
+         ret = virNodeDevCapAPCardParseXML(ctxt, def, node,
+                                           &caps->data.ap_card);
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-nodedev-refactor-css-format-from-ccw-format-method.patch b/SOURCES/libvirt-nodedev-refactor-css-format-from-ccw-format-method.patch
new file mode 100644
index 0000000..ff7dfc1
--- /dev/null
+++ b/SOURCES/libvirt-nodedev-refactor-css-format-from-ccw-format-method.patch
@@ -0,0 +1,62 @@
+From d370e2e984b4501060ea0d7a10629db0bfe51ef2 Mon Sep 17 00:00:00 2001
+Message-Id: <d370e2e984b4501060ea0d7a10629db0bfe51ef2@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:11 +0200
+Subject: [PATCH] nodedev: refactor css format from ccw format method
+
+In preparation for easier extension later.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit c5864885060b136214b4bcef25d604cc3d147014)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/node_device_conf.c | 21 +++++++++++++++++----
+ 1 file changed, 17 insertions(+), 4 deletions(-)
+
+diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
+index a6ebf4b66f..1e00f65717 100644
+--- a/src/conf/node_device_conf.c
++++ b/src/conf/node_device_conf.c
+@@ -632,10 +632,21 @@ virNodeDeviceCapCCWDefFormat(virBuffer *buf,
+                       data->ccw_dev.ssid);
+     virBufferAsprintf(buf, "<devno>0x%04x</devno>\n",
+                       data->ccw_dev.devno);
+-    if (data->ccw_dev.flags & VIR_NODE_DEV_CAP_FLAG_CSS_MDEV)
++}
++
++
++static void
++virNodeDeviceCapCSSDefFormat(virBuffer *buf,
++                             const virNodeDevCapData *data)
++{
++    virNodeDevCapCCW ccw_dev = data->ccw_dev;
++
++    virNodeDeviceCapCCWDefFormat(buf, data);
++
++    if (ccw_dev.flags & VIR_NODE_DEV_CAP_FLAG_CSS_MDEV)
+         virNodeDeviceCapMdevTypesFormat(buf,
+-                                        data->ccw_dev.mdev_types,
+-                                        data->ccw_dev.nmdev_types);
++                                        ccw_dev.mdev_types,
++                                        ccw_dev.nmdev_types);
+ }
+ 
+ 
+@@ -724,9 +735,11 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def)
+             virNodeDeviceCapMdevDefFormat(&buf, data);
+             break;
+         case VIR_NODE_DEV_CAP_CCW_DEV:
+-        case VIR_NODE_DEV_CAP_CSS_DEV:
+             virNodeDeviceCapCCWDefFormat(&buf, data);
+             break;
++        case VIR_NODE_DEV_CAP_CSS_DEV:
++            virNodeDeviceCapCSSDefFormat(&buf, data);
++            break;
+         case VIR_NODE_DEV_CAP_VDPA:
+             virNodeDeviceCapVDPADefFormat(&buf, data);
+             break;
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-qemu-Ignore-missing-vm.unprivileged_userfaultfd-sysctl.patch b/SOURCES/libvirt-qemu-Ignore-missing-vm.unprivileged_userfaultfd-sysctl.patch
new file mode 100644
index 0000000..0113c82
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Ignore-missing-vm.unprivileged_userfaultfd-sysctl.patch
@@ -0,0 +1,38 @@
+From 08fef741d85ecfb3493c47f5f1334f91c30e3233 Mon Sep 17 00:00:00 2001
+Message-Id: <08fef741d85ecfb3493c47f5f1334f91c30e3233@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Wed, 9 Feb 2022 11:08:42 +0100
+Subject: [PATCH] qemu: Ignore missing vm.unprivileged_userfaultfd sysctl
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Older kernels did not support this sysctl, but they did not restrict
+userfaultfd in any way so everything worked as if
+vm.unprivileged_userfaultfd was set to 1. Thus we can safely ignore
+errors when setting the value.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 558f00397a0d46ad22bf53a22a40ed6fc4fdb5eb)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=2148578
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/postcopy-migration.sysctl | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/qemu/postcopy-migration.sysctl b/src/qemu/postcopy-migration.sysctl
+index aa8f015ae0..db3f11e49f 100644
+--- a/src/qemu/postcopy-migration.sysctl
++++ b/src/qemu/postcopy-migration.sysctl
+@@ -3,4 +3,4 @@
+ # privileged processes.
+ # It can be safely overridden by a file in /etc/sysctl.d/ in case post-copy
+ # migration is not used on the host.
+-vm.unprivileged_userfaultfd = 1
++-vm.unprivileged_userfaultfd = 1
+-- 
+2.39.0
+
diff --git a/SOURCES/libvirt-qemu-gpu-Get-pid-without-binary-validation.patch b/SOURCES/libvirt-qemu-gpu-Get-pid-without-binary-validation.patch
new file mode 100644
index 0000000..9b31b4b
--- /dev/null
+++ b/SOURCES/libvirt-qemu-gpu-Get-pid-without-binary-validation.patch
@@ -0,0 +1,67 @@
+From c70b1a8d8a4bc34bcbf9ef4bccac678257b8c494 Mon Sep 17 00:00:00 2001
+Message-Id: <c70b1a8d8a4bc34bcbf9ef4bccac678257b8c494@dist-git>
+From: Vasiliy Ulyanov <vulyanov@suse.de>
+Date: Wed, 2 Feb 2022 17:28:17 +0100
+Subject: [PATCH] qemu: gpu: Get pid without binary validation
+
+The binary validation in virPidFileReadPathIfAlive may fail with EACCES
+if the calling process does not have CAP_SYS_PTRACE capability.
+Therefore instead do only the check that the pidfile is locked by the
+correct process.
+
+Fixes the same issue as with swtpm.
+
+Signed-off-by: Vasiliy Ulyanov <vulyanov@suse.de>
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit e3dfa52d260da8a41a0ec35767d08e37c825824a)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2152188
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/qemu/qemu_vhost_user_gpu.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/src/qemu/qemu_vhost_user_gpu.c b/src/qemu/qemu_vhost_user_gpu.c
+index ef198a4820..f7d444e851 100644
+--- a/src/qemu/qemu_vhost_user_gpu.c
++++ b/src/qemu/qemu_vhost_user_gpu.c
+@@ -54,7 +54,6 @@ qemuVhostUserGPUCreatePidFilename(const char *stateDir,
+ 
+ /*
+  * qemuVhostUserGPUGetPid:
+- * @binpath: path of executable associated with the pidfile
+  * @stateDir: the directory where vhost-user-gpu writes the pidfile into
+  * @shortName: short name of the domain
+  * @alias: video device alias
+@@ -65,8 +64,7 @@ qemuVhostUserGPUCreatePidFilename(const char *stateDir,
+  * set to -1;
+  */
+ static int
+-qemuVhostUserGPUGetPid(const char *binPath,
+-                       const char *stateDir,
++qemuVhostUserGPUGetPid(const char *stateDir,
+                        const char *shortName,
+                        const char *alias,
+                        pid_t *pid)
+@@ -76,7 +74,7 @@ qemuVhostUserGPUGetPid(const char *binPath,
+     if (!(pidfile = qemuVhostUserGPUCreatePidFilename(stateDir, shortName, alias)))
+         return -1;
+ 
+-    if (virPidFileReadPathIfAlive(pidfile, pid, binPath) < 0)
++    if (virPidFileReadPathIfLocked(pidfile, pid) < 0)
+         return -1;
+ 
+     return 0;
+@@ -253,8 +251,7 @@ qemuExtVhostUserGPUSetupCgroup(virQEMUDriver *driver,
+     if (!shortname)
+         return -1;
+ 
+-    rc = qemuVhostUserGPUGetPid(video->driver->vhost_user_binary,
+-                                cfg->stateDir, shortname, video->info.alias, &pid);
++    rc = qemuVhostUserGPUGetPid(cfg->stateDir, shortname, video->info.alias, &pid);
+     if (rc < 0 || (rc == 0 && pid == (pid_t)-1)) {
+         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("Could not get process id of vhost-user-gpu"));
+-- 
+2.39.0
+
diff --git a/SOURCES/libvirt-qemu-tpm-Get-swtpm-pid-without-binary-validation.patch b/SOURCES/libvirt-qemu-tpm-Get-swtpm-pid-without-binary-validation.patch
new file mode 100644
index 0000000..35c8459
--- /dev/null
+++ b/SOURCES/libvirt-qemu-tpm-Get-swtpm-pid-without-binary-validation.patch
@@ -0,0 +1,219 @@
+From e3487aab5319df05c5a06a83e4d3e4a87c1e51a9 Mon Sep 17 00:00:00 2001
+Message-Id: <e3487aab5319df05c5a06a83e4d3e4a87c1e51a9@dist-git>
+From: Vasiliy Ulyanov <vulyanov@suse.de>
+Date: Wed, 2 Feb 2022 17:28:16 +0100
+Subject: [PATCH] qemu: tpm: Get swtpm pid without binary validation
+
+Access to /proc/[pid]/exe may be restricted in certain environments (e.g.
+in containers) and any attempt to stat(2) or readlink(2) the file will
+result in 'permission denied' error if the calling process does not have
+CAP_SYS_PTRACE capability. According to proc(5) manpage:
+
+Permission to dereference or read (readlink(2)) this symbolic link is
+governed by a ptrace access mode PTRACE_MODE_READ_FSCREDS check; see
+ptrace(2).
+
+The binary validation in virPidFileReadPathIfAlive may fail with EACCES.
+Therefore instead do only the check that the pidfile is locked by the
+correct process. To ensure this is always the case the daemonization and
+pidfile handling of the swtpm command is now controlled by libvirt.
+
+Signed-off-by: Vasiliy Ulyanov <vulyanov@suse.de>
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit a9c500d2b50c5c041a1bb6ae9724402cf1cec8fe)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2152188
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/qemu/qemu_tpm.c | 94 ++++++++++++++++++++++++++-------------------
+ 1 file changed, 54 insertions(+), 40 deletions(-)
+
+diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
+index 7e7b01768e..9c5d1ffed4 100644
+--- a/src/qemu/qemu_tpm.c
++++ b/src/qemu/qemu_tpm.c
+@@ -44,6 +44,7 @@
+ #include "qemu_tpm.h"
+ #include "virtpm.h"
+ #include "virsecret.h"
++#include "virtime.h"
+ 
+ #define VIR_FROM_THIS VIR_FROM_NONE
+ 
+@@ -258,13 +259,13 @@ qemuTPMEmulatorGetPid(const char *swtpmStateDir,
+                       const char *shortName,
+                       pid_t *pid)
+ {
+-    g_autofree char *swtpm = virTPMGetSwtpm();
+     g_autofree char *pidfile = qemuTPMEmulatorCreatePidFilename(swtpmStateDir,
+                                                                 shortName);
++
+     if (!pidfile)
+         return -1;
+ 
+-    if (virPidFileReadPathIfAlive(pidfile, pid, swtpm) < 0)
++    if (virPidFileReadPathIfLocked(pidfile, pid) < 0)
+         return -1;
+ 
+     return 0;
+@@ -660,9 +661,6 @@ qemuTPMEmulatorReconfigure(const char *storagepath,
+  * @privileged: whether we are running in privileged mode
+  * @swtpm_user: The uid for the swtpm to run as (drop privileges to from root)
+  * @swtpm_group: The gid for the swtpm to run as
+- * @swtpmStateDir: the directory where swtpm writes the pid file and creates the
+- *                 Unix socket
+- * @shortName: the short name of the VM
+  * @incomingMigration: whether we have an incoming migration
+  *
+  * Create the virCommand use for starting the emulator
+@@ -676,13 +674,10 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
+                             bool privileged,
+                             uid_t swtpm_user,
+                             gid_t swtpm_group,
+-                            const char *swtpmStateDir,
+-                            const char *shortName,
+                             bool incomingMigration)
+ {
+     g_autoptr(virCommand) cmd = NULL;
+     bool created = false;
+-    g_autofree char *pidfile = NULL;
+     g_autofree char *swtpm = virTPMGetSwtpm();
+     int pwdfile_fd = -1;
+     int migpwdfile_fd = -1;
+@@ -721,7 +716,7 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
+ 
+     virCommandClearCaps(cmd);
+ 
+-    virCommandAddArgList(cmd, "socket", "--daemon", "--ctrl", NULL);
++    virCommandAddArgList(cmd, "socket", "--ctrl", NULL);
+     virCommandAddArgFormat(cmd, "type=unixio,path=%s,mode=0600",
+                            tpm->data.emulator.source->data.nix.path);
+ 
+@@ -748,12 +743,6 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm,
+         break;
+     }
+ 
+-    if (!(pidfile = qemuTPMEmulatorCreatePidFilename(swtpmStateDir, shortName)))
+-        goto error;
+-
+-    virCommandAddArg(cmd, "--pid");
+-    virCommandAddArgFormat(cmd, "file=%s", pidfile);
+-
+     if (tpm->data.emulator.hassecretuuid) {
+         if (!virTPMSwtpmCapsGet(VIR_TPM_SWTPM_FEATURE_CMDARG_PWD_FD)) {
+             virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
+@@ -904,12 +893,14 @@ qemuExtTPMStartEmulator(virQEMUDriver *driver,
+                         bool incomingMigration)
+ {
+     g_autoptr(virCommand) cmd = NULL;
+-    int exitstatus = 0;
+-    g_autofree char *errbuf = NULL;
++    VIR_AUTOCLOSE errfd = -1;
+     g_autoptr(virQEMUDriverConfig) cfg = NULL;
+     g_autofree char *shortName = virDomainDefGetShortName(vm->def);
+-    int cmdret = 0, timeout, rc;
+-    pid_t pid;
++    g_autofree char *pidfile = NULL;
++    virTimeBackOffVar timebackoff;
++    const unsigned long long timeout = 1000; /* ms */
++    int cmdret = 0;
++    pid_t pid = -1;
+ 
+     if (!shortName)
+         return -1;
+@@ -923,48 +914,71 @@ qemuExtTPMStartEmulator(virQEMUDriver *driver,
+                                             driver->privileged,
+                                             cfg->swtpm_user,
+                                             cfg->swtpm_group,
+-                                            cfg->swtpmStateDir, shortName,
+                                             incomingMigration)))
+         return -1;
+ 
+     if (qemuExtDeviceLogCommand(driver, vm, cmd, "TPM Emulator") < 0)
+         return -1;
+ 
+-    virCommandSetErrorBuffer(cmd, &errbuf);
++    if (!(pidfile = qemuTPMEmulatorCreatePidFilename(cfg->swtpmStateDir, shortName)))
++        return -1;
++
++    virCommandDaemonize(cmd);
++    virCommandSetPidFile(cmd, pidfile);
++    virCommandSetErrorFD(cmd, &errfd);
+ 
+     if (qemuSecurityStartTPMEmulator(driver, vm, cmd,
+                                      cfg->swtpm_user, cfg->swtpm_group,
+-                                     &exitstatus, &cmdret) < 0)
++                                     NULL, &cmdret) < 0)
+         return -1;
+ 
+-    if (cmdret < 0 || exitstatus != 0) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Could not start 'swtpm'. exitstatus: %d, "
+-                         "error: %s"), exitstatus, errbuf);
+-        return -1;
++    if (cmdret < 0) {
++        /* virCommandRun() hidden in qemuSecurityStartTPMEmulator()
++         * already reported error. */
++        goto error;
+     }
+ 
+-    /* check that the swtpm has written its pid into the file */
+-    timeout = 1000; /* ms */
+-    while (timeout > 0) {
+-        rc = qemuTPMEmulatorGetPid(cfg->swtpmStateDir, shortName, &pid);
+-        if (rc < 0) {
+-            timeout -= 50;
+-            g_usleep(50 * 1000);
++    if (virPidFileReadPath(pidfile, &pid) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                       _("swtpm didn't show up"));
++        goto error;
++    }
++
++    if (virTimeBackOffStart(&timebackoff, 1, timeout) < 0)
++        goto error;
++    while (virTimeBackOffWait(&timebackoff)) {
++        char errbuf[1024] = { 0 };
++
++        if (virFileExists(tpm->data.emulator.source->data.nix.path))
++            break;
++
++        if (virProcessKill(pid, 0) == 0)
+             continue;
++
++        if (saferead(errfd, errbuf, sizeof(errbuf) - 1) < 0) {
++            virReportSystemError(errno, "%s",
++                                 _("swtpm died unexpectedly"));
++        } else {
++            virReportError(VIR_ERR_OPERATION_FAILED,
++                           _("swtpm died and reported: %s"), errbuf);
+         }
+-        if (rc == 0 && pid == (pid_t)-1)
+-            goto error;
+-        break;
++        goto error;
+     }
+-    if (timeout <= 0)
++
++    if (!virFileExists(tpm->data.emulator.source->data.nix.path)) {
++        virReportError(VIR_ERR_OPERATION_TIMEOUT, "%s",
++                       _("swtpm socket did not show up"));
+         goto error;
++    }
+ 
+     return 0;
+ 
+  error:
+-    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+-                   _("swtpm failed to start"));
++    virCommandAbort(cmd);
++    if (pid >= 0)
++        virProcessKillPainfully(pid, true);
++    if (pidfile)
++        unlink(pidfile);
+     return -1;
+ }
+ 
+-- 
+2.39.0
+
diff --git a/SOURCES/libvirt-qemuAgentGetDisks-Don-t-use-virJSONValueObjectGetStringArray-for-optional-data.patch b/SOURCES/libvirt-qemuAgentGetDisks-Don-t-use-virJSONValueObjectGetStringArray-for-optional-data.patch
new file mode 100644
index 0000000..2ed40d8
--- /dev/null
+++ b/SOURCES/libvirt-qemuAgentGetDisks-Don-t-use-virJSONValueObjectGetStringArray-for-optional-data.patch
@@ -0,0 +1,57 @@
+From 1ad707f19e570b76c1f6517194d9cc86b084014d Mon Sep 17 00:00:00 2001
+Message-Id: <1ad707f19e570b76c1f6517194d9cc86b084014d@dist-git>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 1 Dec 2022 17:02:42 +0100
+Subject: [PATCH] qemuAgentGetDisks: Don't use virJSONValueObjectGetStringArray
+ for optional data
+
+The 'dependencies' field in the return data may be missing in some
+cases. Historically 'virJSONValueObjectGetStringArray' didn't report
+error in such case, but later refactor (commit 043b50b948ef3c2 ) added
+an error in order to use it in other places too.
+
+Unfortunately this results in the error log being spammed with an
+irrelevant error in case when qemuAgentGetDisks is invoked on a VM
+running windows.
+
+Replace the use of virJSONValueObjectGetStringArray by fetching the
+array first and calling virJSONValueArrayToStringList only when we have
+an array.
+
+Fixes: 043b50b948ef3c2a4adf5fa32a93ec2589851ac6
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2149752
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 3b576601dfb924bb518870a01de5d1a421cbb467)
+---
+ src/qemu/qemu_agent.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
+index f33cd47078..8a55044c9e 100644
+--- a/src/qemu/qemu_agent.c
++++ b/src/qemu/qemu_agent.c
+@@ -2550,6 +2550,7 @@ int qemuAgentGetDisks(qemuAgent *agent,
+     for (i = 0; i < ndata; i++) {
+         virJSONValue *addr;
+         virJSONValue *entry = virJSONValueArrayGet(data, i);
++        virJSONValue *dependencies;
+         qemuAgentDiskInfo *disk;
+ 
+         if (!entry) {
+@@ -2575,7 +2576,11 @@ int qemuAgentGetDisks(qemuAgent *agent,
+             goto error;
+         }
+ 
+-        disk->dependencies = virJSONValueObjectGetStringArray(entry, "dependencies");
++        if ((dependencies = virJSONValueObjectGetArray(entry, "dependencies"))) {
++            if (!(disk->dependencies = virJSONValueArrayToStringList(dependencies)))
++                goto error;
++        }
++
+         disk->alias = g_strdup(virJSONValueObjectGetString(entry, "alias"));
+         addr = virJSONValueObjectGetObject(entry, "address");
+         if (addr) {
+-- 
+2.39.0
+
diff --git a/SOURCES/libvirt-qemuProcessReconnect-Don-t-build-memory-paths.patch b/SOURCES/libvirt-qemuProcessReconnect-Don-t-build-memory-paths.patch
new file mode 100644
index 0000000..8185b76
--- /dev/null
+++ b/SOURCES/libvirt-qemuProcessReconnect-Don-t-build-memory-paths.patch
@@ -0,0 +1,57 @@
+From c5c8bb4aafc8f247e6da146a6683174038611600 Mon Sep 17 00:00:00 2001
+Message-Id: <c5c8bb4aafc8f247e6da146a6683174038611600@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Wed, 28 Sep 2022 10:12:36 +0200
+Subject: [PATCH] qemuProcessReconnect: Don't build memory paths
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Let me take you on a short trip to history. A long time ago,
+libvirt would configure all QEMUs to use $hugetlbfs/libvirt/qemu
+for their hugepages setup. This was problematic, because it did
+not allow enough separation between guests. Therefore in
+v3.0.0-rc1~367 the path changed to a per-domain basis:
+
+  $hugetlbfs/libvirt/qemu/$domainShortName
+
+And to help with migration on daemon restart a call to
+qemuProcessBuildDestroyMemoryPaths() was added to
+qemuProcessReconnect() (well, it was named
+qemuProcessBuildDestroyHugepagesPath() back then, see
+v3.10.0-rc1~174). This was desirable then, because the memory
+hotplug code did not call the function, it simply assumes
+per-domain paths to exist. But this changed in v3.5.0-rc1~92
+after which the per-domain paths are created on memory hotplug
+too.
+
+Therefore, it's no longer necessary to create these paths in
+qemuProcessReconnect(). They are created exactly when needed
+(domain startup and memory hotplug).
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 3478cca80ea7382cfdbff836d5d0b92aa014297b)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2123196
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/qemu/qemu_process.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 1164340aa9..0fb665bc82 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -8869,9 +8869,6 @@ qemuProcessReconnect(void *opaque)
+         goto cleanup;
+     }
+ 
+-    if (qemuProcessBuildDestroyMemoryPaths(driver, obj, NULL, true) < 0)
+-        goto error;
+-
+     if ((qemuDomainAssignAddresses(obj->def, priv->qemuCaps,
+                                    driver, obj, false)) < 0) {
+         goto error;
+-- 
+2.38.0
+
diff --git a/SOURCES/libvirt-qemu_namespace-Don-t-leak-memory-in-qemuDomainGetPreservedMounts.patch b/SOURCES/libvirt-qemu_namespace-Don-t-leak-memory-in-qemuDomainGetPreservedMounts.patch
new file mode 100644
index 0000000..10419d6
--- /dev/null
+++ b/SOURCES/libvirt-qemu_namespace-Don-t-leak-memory-in-qemuDomainGetPreservedMounts.patch
@@ -0,0 +1,57 @@
+From 77b0485ba92fe5f0520321385af8a7581c286df1 Mon Sep 17 00:00:00 2001
+Message-Id: <77b0485ba92fe5f0520321385af8a7581c286df1@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 31 Oct 2022 15:38:13 +0100
+Subject: [PATCH] qemu_namespace: Don't leak memory in
+ qemuDomainGetPreservedMounts()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The aim of qemuDomainGetPreservedMounts() is to get a list of
+filesystems mounted under /dev and optionally generate a path for
+each one where they are moved temporarily when building the
+namespace. And the function tries to be a bit clever about it.
+For instance, if /dev/shm mount point exists, there's no need to
+consider /dev/shm/a nor /dev/shm/b as preserving just 'top level'
+/dev/shm gives the same result. To achieve this, the function
+iterates over the list of filesystem as returned by
+virFileGetMountSubtree() and removes the nested ones. However, it
+does so in a bit clumsy way: plain VIR_DELETE_ELEMENT() is used
+without freeing the string itself. Therefore, if all three
+aforementioned example paths appeared on the list, /dev/shm/a and
+/dev/shm/b strings would be leaked.
+
+And when I think about it more, there's no real need to shrink
+the array down (realloc()). It's going to be free()-d when
+returning from the function. Switch to
+VIR_DELETE_ELEMENT_INPLACE() then.
+
+Fixes: cdd9205dfffa3aaed935446a41f0d2dd1357c268
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Peter Krempa <pkrempa@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit bca7a53333ead7c1afd178728de74c2977cd4b5e)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2166573
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/qemu/qemu_namespace.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
+index 74ffd6fb90..2f50087c1d 100644
+--- a/src/qemu/qemu_namespace.c
++++ b/src/qemu/qemu_namespace.c
+@@ -160,7 +160,8 @@ qemuDomainGetPreservedMounts(virQEMUDriverConfig *cfg,
+ 
+             if (c && (*c == '/' || *c == '\0')) {
+                 VIR_DEBUG("Dropping path %s because of %s", mounts[j], mounts[i]);
+-                VIR_DELETE_ELEMENT(mounts, j, nmounts);
++                VIR_FREE(mounts[j]);
++                VIR_DELETE_ELEMENT_INPLACE(mounts, j, nmounts);
+             } else {
+                 j++;
+             }
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-qemu_namespace-Fix-a-corner-case-in-qemuDomainGetPreservedMounts.patch b/SOURCES/libvirt-qemu_namespace-Fix-a-corner-case-in-qemuDomainGetPreservedMounts.patch
new file mode 100644
index 0000000..3df3a96
--- /dev/null
+++ b/SOURCES/libvirt-qemu_namespace-Fix-a-corner-case-in-qemuDomainGetPreservedMounts.patch
@@ -0,0 +1,80 @@
+From 215adedb16aa082d052f84705338de0d77721fe0 Mon Sep 17 00:00:00 2001
+Message-Id: <215adedb16aa082d052f84705338de0d77721fe0@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 6 Sep 2022 13:43:22 +0200
+Subject: [PATCH] qemu_namespace: Fix a corner case in
+ qemuDomainGetPreservedMounts()
+
+When setting up namespace for QEMU we look at mount points under
+/dev (like /dev/pts, /dev/mqueue/, etc.) because we want to
+preserve those (which is done by moving them to a temp location,
+unshare(), and then moving them back). We have a convenience
+helper - qemuDomainGetPreservedMounts() - that processes the
+mount table and (optionally) moves the other filesystems too.
+This helper is also used when attempting to create a path in NS,
+because the path, while starting with "/dev/" prefix, may
+actually lead to one of those filesystems that we preserved.
+
+And here comes the corner case: while we require the parent mount
+table to be in shared mode (equivalent of `mount --make-rshared /'),
+these mount events propagate iff the target path exist inside the
+slave mount table (= QEMU's private namespace). And since we
+create only a subset of /dev nodes, well, that assumption is not
+always the case.
+
+For instance, assume that a domain is already running, no
+hugepages were configured for it nor any hugetlbfs is mounted.
+Now, when a hugetlbfs is mounted into '/dev/hugepages', this is
+propagated into the QEMU's namespace, but since the target dir
+does not exist in the private /dev, the FS is not mounted in the
+namespace.
+
+Fortunately, this difference between namespaces is visible when
+comparing /proc/mounts and /proc/$PID/mounts (where PID is the
+QEMU's PID). Therefore, if possible we should look at the latter.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
+(cherry picked from commit 46b03819ae8d833b11c2aaccb2c2a0361727f51b)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2123196
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/qemu/qemu_namespace.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
+index 4bff325a2c..fc286ab0be 100644
+--- a/src/qemu/qemu_namespace.c
++++ b/src/qemu/qemu_namespace.c
+@@ -110,6 +110,8 @@ qemuDomainGetPreservedMountPath(virQEMUDriverConfig *cfg,
+  * b) generate backup path for all the entries in a)
+  *
+  * Any of the return pointers can be NULL. Both arrays are NULL-terminated.
++ * Get the mount table either from @vm's PID (if running), or from the
++ * namespace we're in (if @vm's not running).
+  *
+  * Returns 0 on success, -1 otherwise (with error reported)
+  */
+@@ -124,12 +126,18 @@ qemuDomainGetPreservedMounts(virQEMUDriverConfig *cfg,
+     size_t nmounts = 0;
+     g_auto(GStrv) paths = NULL;
+     g_auto(GStrv) savePaths = NULL;
++    g_autofree char *mountsPath = NULL;
+     size_t i;
+ 
+     if (ndevPath)
+         *ndevPath = 0;
+ 
+-    if (virFileGetMountSubtree(QEMU_PROC_MOUNTS, "/dev", &mounts, &nmounts) < 0)
++    if (vm->pid > 0)
++        mountsPath = g_strdup_printf("/proc/%lld/mounts", (long long) vm->pid);
++    else
++        mountsPath = g_strdup(QEMU_PROC_MOUNTS);
++
++    if (virFileGetMountSubtree(mountsPath, "/dev", &mounts, &nmounts) < 0)
+         return -1;
+ 
+     if (nmounts == 0)
+-- 
+2.38.0
+
diff --git a/SOURCES/libvirt-qemu_namespace-Introduce-qemuDomainNamespaceSetupPath.patch b/SOURCES/libvirt-qemu_namespace-Introduce-qemuDomainNamespaceSetupPath.patch
new file mode 100644
index 0000000..bb83813
--- /dev/null
+++ b/SOURCES/libvirt-qemu_namespace-Introduce-qemuDomainNamespaceSetupPath.patch
@@ -0,0 +1,68 @@
+From d515c964d740274d01bb8de1e5b0351490d6b9d3 Mon Sep 17 00:00:00 2001
+Message-Id: <d515c964d740274d01bb8de1e5b0351490d6b9d3@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 6 Sep 2022 13:43:58 +0200
+Subject: [PATCH] qemu_namespace: Introduce qemuDomainNamespaceSetupPath()
+
+Sometimes it may come handy to just bind mount a directory/file
+into domain's namespace. Implement a thin wrapper over
+qemuNamespaceMknodPaths() which has all the logic we need.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
+(cherry picked from commit 5853d707189005a4ea5b2215e80853867b822fd9)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2123196
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/qemu/qemu_namespace.c | 19 +++++++++++++++++++
+ src/qemu/qemu_namespace.h |  4 ++++
+ 2 files changed, 23 insertions(+)
+
+diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
+index fc286ab0be..74ffd6fb90 100644
+--- a/src/qemu/qemu_namespace.c
++++ b/src/qemu/qemu_namespace.c
+@@ -1398,6 +1398,25 @@ qemuNamespaceUnlinkPaths(virDomainObj *vm,
+ }
+ 
+ 
++int
++qemuDomainNamespaceSetupPath(virDomainObj *vm,
++                             const char *path,
++                             bool *created)
++{
++    g_autoptr(virGSListString) paths = NULL;
++
++    if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
++        return 0;
++
++    paths = g_slist_prepend(paths, g_strdup(path));
++
++    if (qemuNamespaceMknodPaths(vm, paths, created) < 0)
++        return -1;
++
++    return 0;
++}
++
++
+ int
+ qemuDomainNamespaceSetupDisk(virDomainObj *vm,
+                              virStorageSource *src,
+diff --git a/src/qemu/qemu_namespace.h b/src/qemu/qemu_namespace.h
+index 020aca13d8..1ab9322061 100644
+--- a/src/qemu/qemu_namespace.h
++++ b/src/qemu/qemu_namespace.h
+@@ -49,6 +49,10 @@ void qemuDomainDestroyNamespace(virQEMUDriver *driver,
+ 
+ bool qemuDomainNamespaceAvailable(qemuDomainNamespace ns);
+ 
++int qemuDomainNamespaceSetupPath(virDomainObj *vm,
++                                 const char *path,
++                                 bool *created);
++
+ int qemuDomainNamespaceSetupDisk(virDomainObj *vm,
+                                  virStorageSource *src,
+                                  bool *created);
+-- 
+2.38.0
+
diff --git a/SOURCES/libvirt-qemu_namespace-Tolerate-missing-ACLs-when-creating-a-path-in-namespace.patch b/SOURCES/libvirt-qemu_namespace-Tolerate-missing-ACLs-when-creating-a-path-in-namespace.patch
new file mode 100644
index 0000000..ceccc0b
--- /dev/null
+++ b/SOURCES/libvirt-qemu_namespace-Tolerate-missing-ACLs-when-creating-a-path-in-namespace.patch
@@ -0,0 +1,45 @@
+From 7c7ec6e6c20675a99abe8685c715dc95e7e8dbff Mon Sep 17 00:00:00 2001
+Message-Id: <7c7ec6e6c20675a99abe8685c715dc95e7e8dbff@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 6 Sep 2022 13:37:23 +0200
+Subject: [PATCH] qemu_namespace: Tolerate missing ACLs when creating a path in
+ namespace
+
+When creating a path in a domain's mount namespace we try to set
+ACLs on it, so that it's a verbatim copy of the path in parent's
+namespace. The ACLs are queried upfront (by
+qemuNamespaceMknodItemInit()) but this is fault tolerant so the
+pointer to ACLs might be NULL (meaning no ACLs were queried, for
+instance because the underlying filesystem does not support
+them). But then we take this NULL and pass it to virFileSetACLs()
+which immediately returns an error because NULL is invalid value.
+
+Mimic what we do with SELinux label - only set ACLs if they are
+non-NULL which includes symlinks.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
+(cherry picked from commit 687374959e160dc566bd4b6d43c7bf1beb470c59)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2123196
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/qemu/qemu_namespace.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_namespace.c b/src/qemu/qemu_namespace.c
+index 94453033f5..4bff325a2c 100644
+--- a/src/qemu/qemu_namespace.c
++++ b/src/qemu/qemu_namespace.c
+@@ -1023,8 +1023,7 @@ qemuNamespaceMknodOne(qemuNamespaceMknodItem *data)
+         goto cleanup;
+     }
+ 
+-    /* Symlinks don't have ACLs. */
+-    if (!isLink &&
++    if (data->acl &&
+         virFileSetACLs(data->file, data->acl) < 0 &&
+         errno != ENOTSUP) {
+         virReportSystemError(errno,
+-- 
+2.38.0
+
diff --git a/SOURCES/libvirt-qemu_process-Don-t-require-a-hugetlbfs-mount-for-memfd.patch b/SOURCES/libvirt-qemu_process-Don-t-require-a-hugetlbfs-mount-for-memfd.patch
new file mode 100644
index 0000000..5552bf4
--- /dev/null
+++ b/SOURCES/libvirt-qemu_process-Don-t-require-a-hugetlbfs-mount-for-memfd.patch
@@ -0,0 +1,50 @@
+From f745b9ae2d12df0c0f2253c295f3d411a8a4165d Mon Sep 17 00:00:00 2001
+Message-Id: <f745b9ae2d12df0c0f2253c295f3d411a8a4165d@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 5 Sep 2022 10:34:44 +0200
+Subject: [PATCH] qemu_process: Don't require a hugetlbfs mount for memfd
+
+The aim of qemuProcessNeedHugepagesPath() is to determine whether
+a hugetlbfs mount point is required for given domain (as in
+whether qemuBuildMemoryBackendProps() picks up
+memory-backend-file pointing to a hugetlbfs mount point). Well,
+when domain is configured to use memfd backend then that
+condition can never be true. Therefore, skip creating domain's
+private path under hugetlbfs mount points.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
+(cherry picked from commit f14f8dff9330ed51d817f190a2ee9ac76dfac00b)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2123196
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/qemu/qemu_process.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 5c6657a876..540eee9ff0 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -3810,8 +3810,18 @@ qemuProcessNeedHugepagesPath(virDomainDef *def,
+     const long system_pagesize = virGetSystemPageSizeKB();
+     size_t i;
+ 
+-    if (def->mem.source == VIR_DOMAIN_MEMORY_SOURCE_FILE)
++    switch ((virDomainMemorySource)def->mem.source) {
++    case VIR_DOMAIN_MEMORY_SOURCE_FILE:
++        /* This needs a hugetlbfs mount. */
+         return true;
++    case VIR_DOMAIN_MEMORY_SOURCE_MEMFD:
++        /* memfd works without a hugetlbfs mount */
++        return false;
++    case VIR_DOMAIN_MEMORY_SOURCE_NONE:
++    case VIR_DOMAIN_MEMORY_SOURCE_ANONYMOUS:
++    case VIR_DOMAIN_MEMORY_SOURCE_LAST:
++        break;
++    }
+ 
+     for (i = 0; i < def->mem.nhugepages; i++) {
+         if (def->mem.hugepages[i].size != system_pagesize)
+-- 
+2.38.0
+
diff --git a/SOURCES/libvirt-qemu_process.c-Propagate-hugetlbfs-mounts-on-reconnect.patch b/SOURCES/libvirt-qemu_process.c-Propagate-hugetlbfs-mounts-on-reconnect.patch
new file mode 100644
index 0000000..be102cd
--- /dev/null
+++ b/SOURCES/libvirt-qemu_process.c-Propagate-hugetlbfs-mounts-on-reconnect.patch
@@ -0,0 +1,65 @@
+From 2aeb222d9d61868ef40932b4349af84696415e11 Mon Sep 17 00:00:00 2001
+Message-Id: <2aeb222d9d61868ef40932b4349af84696415e11@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 6 Sep 2022 13:45:51 +0200
+Subject: [PATCH] qemu_process.c: Propagate hugetlbfs mounts on reconnect
+
+When reconnecting to a running QEMU process, we construct the
+per-domain path in all hugetlbfs mounts. This is a relict from
+the past (v3.4.0-100-g5b24d25062) where we switched to a
+per-domain path and we want to create those paths when libvirtd
+restarts on upgrade.
+
+And with namespaces enabled there is one corner case where the
+path is not created. In fact an error is reported and the
+reconnect fails. Ideally, all mount events are propagated into
+the QEMU's namespace. And they probably are, except when the
+target path does not exist inside the namespace. Now, it's pretty
+common for users to mount hugetlbfs under /dev (e.g.
+/dev/hugepages), but if domain is started without hugepages (or
+more specifically - private hugetlbfs path wasn't created on
+domain startup), then the reconnect code tries to create it.
+But it fails to do so, well, it fails to set seclabels on the
+path because, because the path does not exist in the private
+namespace. And it doesn't exist because we specifically create
+only a subset of all possible /dev nodes. Therefore, the mount
+event, whilst propagated, is not successful and hence the
+filesystem is not mounted. We have to do it ourselves.
+
+If hugetlbfs is mount anywhere else there's no problem and this
+is effectively a dead code.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2123196
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
+(cherry picked from commit 0377177c7856bb87a9d8aa1324b54f5fbe9f1e5b)
+
+Conflicts:
+- docs/kbase/qemu-passthrough-security.rst: Well, v8.8.0-rc1~32
+  isn't backported, thus we can't remove a paragraph that the
+  backported commit did. It's a documentation after all, so no
+  harm.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2123196
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/qemu/qemu_process.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 540eee9ff0..1164340aa9 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -3906,6 +3906,9 @@ qemuProcessBuildDestroyMemoryPathsImpl(virQEMUDriver *driver,
+             return -1;
+         }
+ 
++        if (qemuDomainNamespaceSetupPath(vm, path, NULL) < 0)
++            return -1;
++
+         if (qemuSecurityDomainSetPathLabel(driver, vm, path, true) < 0)
+             return -1;
+     } else {
+-- 
+2.38.0
+
diff --git a/SOURCES/libvirt-qemu_tpm-Do-async-IO-when-starting-swtpm-emulator.patch b/SOURCES/libvirt-qemu_tpm-Do-async-IO-when-starting-swtpm-emulator.patch
new file mode 100644
index 0000000..6ee2c59
--- /dev/null
+++ b/SOURCES/libvirt-qemu_tpm-Do-async-IO-when-starting-swtpm-emulator.patch
@@ -0,0 +1,49 @@
+From 87b0f241db1eba0e9db1fd233c5ab8a8d0115979 Mon Sep 17 00:00:00 2001
+Message-Id: <87b0f241db1eba0e9db1fd233c5ab8a8d0115979@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 21 Mar 2022 13:33:06 +0100
+Subject: [PATCH] qemu_tpm: Do async IO when starting swtpm emulator
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When vTPM is secured via virSecret libvirt passes the secret
+value via an FD when swtpm is started (arguments --key and
+--migration-key). The writing of the secret into the FDs is
+handled via virCommand, specifically qemu_tpm calls
+virCommandSetSendBuffer()) and then virCommandRunAsync() spawns a
+thread to handle writing into the FD via
+virCommandDoAsyncIOHelper. But the thread is not created unless
+VIR_EXEC_ASYNC_IO flag is set, which it isn't. In order to fix
+it, virCommandDoAsyncIO() must be called.
+
+The credit goes to Marc-André Lureau
+<marcandre.lureau@redhat.com> who has done all the debugging and
+proposed fix in the bugzilla.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2064115
+Fixes: a9c500d2b50c5c041a1bb6ae9724402cf1cec8fe
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit 4d7bb0177a33c4e90fd001edfe27bc030354d875)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2152188
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/qemu/qemu_tpm.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
+index 9c5d1ffed4..29dcb2ac0f 100644
+--- a/src/qemu/qemu_tpm.c
++++ b/src/qemu/qemu_tpm.c
+@@ -923,6 +923,7 @@ qemuExtTPMStartEmulator(virQEMUDriver *driver,
+     if (!(pidfile = qemuTPMEmulatorCreatePidFilename(cfg->swtpmStateDir, shortName)))
+         return -1;
+ 
++    virCommandDoAsyncIO(cmd);
+     virCommandDaemonize(cmd);
+     virCommandSetPidFile(cmd, pidfile);
+     virCommandSetErrorFD(cmd, &errfd);
+-- 
+2.39.0
+
diff --git a/SOURCES/libvirt-rpc-Fix-memory-leak-of-fds.patch b/SOURCES/libvirt-rpc-Fix-memory-leak-of-fds.patch
new file mode 100644
index 0000000..c54e1ff
--- /dev/null
+++ b/SOURCES/libvirt-rpc-Fix-memory-leak-of-fds.patch
@@ -0,0 +1,36 @@
+From 0f6009e5a8ca63388772597f3e42c71b50635a02 Mon Sep 17 00:00:00 2001
+Message-Id: <0f6009e5a8ca63388772597f3e42c71b50635a02@dist-git>
+From: Peng Liang <liangpeng10@huawei.com>
+Date: Wed, 2 Mar 2022 17:22:05 +0800
+Subject: [PATCH] rpc: Fix memory leak of fds
+
+In virSystemdActivationClaimFDs, the memory of ent->fds has been stolen
+and stored in fds, but fds is never freed, which causes a memory leak.
+Fix it by declaring fds as g_autofree.
+
+Reported-by: Jie Tang <tangjie18@huawei.com>
+Signed-off-by: Peng Liang <liangpeng10@huawei.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 8a1915c4d6c33669dcb390d0708cb6e5d651770d)
+https://bugzilla.redhat.com/show_bug.cgi?id=2165428
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/rpc/virnetserver.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
+index ad581a36dd..d9430a2cfa 100644
+--- a/src/rpc/virnetserver.c
++++ b/src/rpc/virnetserver.c
+@@ -655,7 +655,7 @@ virNetServerAddServiceActivation(virNetServer *srv,
+                                  size_t max_queued_clients,
+                                  size_t nrequests_client_max)
+ {
+-    int *fds;
++    g_autofree int *fds = NULL;
+     size_t nfds;
+ 
+     if (act == NULL)
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-schemas-refactor-out-nodedev-ccw-address-schema.patch b/SOURCES/libvirt-schemas-refactor-out-nodedev-ccw-address-schema.patch
new file mode 100644
index 0000000..e26ca09
--- /dev/null
+++ b/SOURCES/libvirt-schemas-refactor-out-nodedev-ccw-address-schema.patch
@@ -0,0 +1,64 @@
+From eb17cd2553366491b54c834b00fd953e94ef0bd2 Mon Sep 17 00:00:00 2001
+Message-Id: <eb17cd2553366491b54c834b00fd953e94ef0bd2@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:14 +0200
+Subject: [PATCH] schemas: refactor out nodedev ccw address schema
+
+Refactor out nodedev ccw address schema for easy reuse later.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit e9ba2ced0b6bdcf6ed4c4b38d8f3fc63b6fa6d59)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ docs/schemas/nodedev.rng | 22 +++++++++-------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng
+index e4733f0804..29515d2d7e 100644
+--- a/docs/schemas/nodedev.rng
++++ b/docs/schemas/nodedev.rng
+@@ -653,10 +653,7 @@
+     </interleave>
+   </define>
+ 
+-  <define name="capccwdev">
+-    <attribute name="type">
+-      <value>ccw</value>
+-    </attribute>
++  <define name="capccwaddress">
+     <element name="cssid">
+       <ref name="ccwCssidRange"/>
+     </element>
+@@ -668,19 +665,18 @@
+     </element>
+   </define>
+ 
++  <define name="capccwdev">
++    <attribute name="type">
++      <value>ccw</value>
++    </attribute>
++    <ref name="capccwaddress"/>
++  </define>
++
+   <define name="capcssdev">
+     <attribute name="type">
+       <value>css</value>
+     </attribute>
+-    <element name="cssid">
+-      <ref name="ccwCssidRange"/>
+-    </element>
+-    <element name="ssid">
+-      <ref name="ccwSsidRange"/>
+-    </element>
+-    <element name="devno">
+-      <ref name="ccwDevnoRange"/>
+-    </element>
++    <ref name="capccwaddress"/>
+     <optional>
+       <ref name="mdev_types"/>
+     </optional>
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-tools-Fix-install_mode-for-some-scripts.patch b/SOURCES/libvirt-tools-Fix-install_mode-for-some-scripts.patch
new file mode 100644
index 0000000..7cea092
--- /dev/null
+++ b/SOURCES/libvirt-tools-Fix-install_mode-for-some-scripts.patch
@@ -0,0 +1,65 @@
+From 48f4d21cf73e15e145258bf1d590ca279838168c Mon Sep 17 00:00:00 2001
+Message-Id: <48f4d21cf73e15e145258bf1d590ca279838168c@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 8 Dec 2022 08:39:24 +0100
+Subject: [PATCH] tools: Fix install_mode for some scripts
+
+Scripts from the following list were installed with group write
+bit set: virt-xml-validate, virt-pki-validate,
+virt-sanlock-cleanup, libvirt-guests.sh. This is very unusual and
+in contrast with the way other scripts/binaries are installed.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2151202
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Peter Krempa <pkrempa@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit e771e32f15ff2b263ca70306d93080541a96792b)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2153688
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ tools/meson.build | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/tools/meson.build b/tools/meson.build
+index 2d0aecb90b..7c6e527939 100644
+--- a/tools/meson.build
++++ b/tools/meson.build
+@@ -247,7 +247,7 @@ configure_file(
+   configuration: tools_conf,
+   install: true,
+   install_dir: bindir,
+-  install_mode: 'rwxrwxr-x',
++  install_mode: 'rwxr-xr-x',
+ )
+ 
+ configure_file(
+@@ -256,7 +256,7 @@ configure_file(
+   configuration: tools_conf,
+   install: true,
+   install_dir: bindir,
+-  install_mode: 'rwxrwxr-x',
++  install_mode: 'rwxr-xr-x',
+ )
+ 
+ executable(
+@@ -293,7 +293,7 @@ if conf.has('WITH_SANLOCK')
+     configuration: tools_conf,
+     install: true,
+     install_dir: sbindir,
+-    install_mode: 'rwxrwxr-x',
++    install_mode: 'rwxr-xr-x',
+   )
+ endif
+ 
+@@ -304,7 +304,7 @@ if conf.has('WITH_LIBVIRTD')
+     configuration: tools_conf,
+     install: true,
+     install_dir: libexecdir,
+-    install_mode: 'rwxrwxr-x',
++    install_mode: 'rwxr-xr-x',
+   )
+ 
+   if init_script == 'systemd'
+-- 
+2.39.0
+
diff --git a/SOURCES/libvirt-util-add-ccw-device-address-parsing-into-virccw.patch b/SOURCES/libvirt-util-add-ccw-device-address-parsing-into-virccw.patch
new file mode 100644
index 0000000..a778644
--- /dev/null
+++ b/SOURCES/libvirt-util-add-ccw-device-address-parsing-into-virccw.patch
@@ -0,0 +1,107 @@
+From 6d9fc3310cedf321f54530c0652998b67979e613 Mon Sep 17 00:00:00 2001
+Message-Id: <6d9fc3310cedf321f54530c0652998b67979e613@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:09 +0200
+Subject: [PATCH] util: add ccw device address parsing into virccw
+
+Add virCCWDeviceAddressParseFromString and use it in nodedev udev.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 8d52f99f0b55ddfee4e0c00e756ca6c01250107d)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/libvirt_private.syms           |  1 +
+ src/node_device/node_device_udev.c |  8 +++++---
+ src/util/virccw.c                  | 18 ++++++++++++++++++
+ src/util/virccw.h                  |  5 +++++
+ 4 files changed, 29 insertions(+), 3 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 44b551fb60..6f1292e0c4 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1904,6 +1904,7 @@ virCCWDeviceAddressAsString;
+ virCCWDeviceAddressEqual;
+ virCCWDeviceAddressIncrement;
+ virCCWDeviceAddressIsValid;
++virCCWDeviceAddressParseFromString;
+ 
+ 
+ # util/vircgroup.h
+diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
+index a9e8bf10da..ffcb3e8640 100644
+--- a/src/node_device/node_device_udev.c
++++ b/src/node_device/node_device_udev.c
+@@ -36,6 +36,7 @@
+ #include "viruuid.h"
+ #include "virbuffer.h"
+ #include "virfile.h"
++#include "virccw.h"
+ #include "virpci.h"
+ #include "virpidfile.h"
+ #include "virstring.h"
+@@ -1090,9 +1091,10 @@ udevGetCCWAddress(const char *sysfs_path,
+     char *p;
+ 
+     if ((p = strrchr(sysfs_path, '/')) == NULL ||
+-        virStrToLong_ui(p + 1, &p, 16, &data->ccw_dev.cssid) < 0 || p == NULL ||
+-        virStrToLong_ui(p + 1, &p, 16, &data->ccw_dev.ssid) < 0 || p == NULL ||
+-        virStrToLong_ui(p + 1, &p, 16, &data->ccw_dev.devno) < 0) {
++        virCCWDeviceAddressParseFromString(p + 1,
++                                           &data->ccw_dev.cssid,
++                                           &data->ccw_dev.ssid,
++                                           &data->ccw_dev.devno) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("failed to parse the CCW address from sysfs path: '%s'"),
+                        sysfs_path);
+diff --git a/src/util/virccw.c b/src/util/virccw.c
+index e2785bd9ab..33df1c2428 100644
+--- a/src/util/virccw.c
++++ b/src/util/virccw.c
+@@ -20,6 +20,7 @@
+ 
+ #include <config.h>
+ #include "virccw.h"
++#include "virstring.h"
+ 
+ 
+ bool
+@@ -60,3 +61,20 @@ virCCWDeviceAddressIncrement(virCCWDeviceAddress *addr)
+     *addr = ccwaddr;
+     return 0;
+ }
++
++int
++virCCWDeviceAddressParseFromString(const char *address,
++                                   unsigned int *cssid,
++                                   unsigned int *ssid,
++                                   unsigned int *devno)
++{
++    char *p;
++
++    if (address == NULL || virStrToLong_ui(address, &p, 16, cssid) < 0 ||
++        p == NULL || virStrToLong_ui(p + 1, &p, 16, ssid) < 0 ||
++        p == NULL || virStrToLong_ui(p + 1, &p, 16, devno) < 0) {
++        return -1;
++    }
++
++    return 0;
++}
+diff --git a/src/util/virccw.h b/src/util/virccw.h
+index aebbd4ab6d..df0273bcac 100644
+--- a/src/util/virccw.h
++++ b/src/util/virccw.h
+@@ -42,3 +42,8 @@ bool virCCWDeviceAddressEqual(virCCWDeviceAddress *addr1,
+ char* virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
+     ATTRIBUTE_NONNULL(1);
+ int virCCWDeviceAddressIncrement(virCCWDeviceAddress *addr);
++
++int virCCWDeviceAddressParseFromString(const char *address,
++                                       unsigned int *cssid,
++                                       unsigned int *ssid,
++                                       unsigned int *devno);
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-util-add-virCCWDeviceAddressFromString-to-virccw.patch b/SOURCES/libvirt-util-add-virCCWDeviceAddressFromString-to-virccw.patch
new file mode 100644
index 0000000..5d2e729
--- /dev/null
+++ b/SOURCES/libvirt-util-add-virCCWDeviceAddressFromString-to-virccw.patch
@@ -0,0 +1,107 @@
+From e5e849999b1d615c6a371839aeead37275599cf0 Mon Sep 17 00:00:00 2001
+Message-Id: <e5e849999b1d615c6a371839aeead37275599cf0@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:10 +0200
+Subject: [PATCH] util: add virCCWDeviceAddressFromString to virccw
+
+Add a method to parse a ccw device address from a string.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 9453eb458a5c3ed6687188233d7e389c3e20c266)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Conflicts:
+	po/POTFILES (file is called POTFILES.in in downstream)
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ po/POTFILES.in           |  1 +
+ src/libvirt_private.syms |  1 +
+ src/util/virccw.c        | 23 +++++++++++++++++++++++
+ src/util/virccw.h        |  3 +++
+ 4 files changed, 28 insertions(+)
+
+diff --git a/po/POTFILES.in b/po/POTFILES.in
+index bf0a3b3529..327e20ec11 100644
+--- a/po/POTFILES.in
++++ b/po/POTFILES.in
+@@ -246,6 +246,7 @@
+ @SRCDIR@src/util/virauth.c
+ @SRCDIR@src/util/virauthconfig.c
+ @SRCDIR@src/util/virbitmap.c
++@SRCDIR@src/util/virccw.c
+ @SRCDIR@src/util/vircgroup.c
+ @SRCDIR@src/util/vircgroupbackend.c
+ @SRCDIR@src/util/vircgroupbackend.h
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 6f1292e0c4..7c558ad364 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1902,6 +1902,7 @@ virBufferVasprintf;
+ # util/virccw.h
+ virCCWDeviceAddressAsString;
+ virCCWDeviceAddressEqual;
++virCCWDeviceAddressFromString;
+ virCCWDeviceAddressIncrement;
+ virCCWDeviceAddressIsValid;
+ virCCWDeviceAddressParseFromString;
+diff --git a/src/util/virccw.c b/src/util/virccw.c
+index 33df1c2428..d741743050 100644
+--- a/src/util/virccw.c
++++ b/src/util/virccw.c
+@@ -20,8 +20,11 @@
+ 
+ #include <config.h>
+ #include "virccw.h"
++#include "virerror.h"
+ #include "virstring.h"
+ 
++#define VIR_FROM_THIS VIR_FROM_NONE
++
+ 
+ bool
+ virCCWDeviceAddressIsValid(virCCWDeviceAddress *addr)
+@@ -49,6 +52,26 @@ virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
+     return g_strdup_printf(VIR_CCW_DEVICE_ADDRESS_FMT, addr->cssid, addr->ssid, addr->devno);
+ }
+ 
++virCCWDeviceAddress *
++virCCWDeviceAddressFromString(const char *address)
++{
++    g_autofree virCCWDeviceAddress *ccw = NULL;
++
++    ccw = g_new0(virCCWDeviceAddress, 1);
++
++    if (virCCWDeviceAddressParseFromString(address,
++                                           &ccw->cssid,
++                                           &ccw->ssid,
++                                           &ccw->devno) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Failed to parse CCW address '%s'"),
++                       address);
++        return NULL;
++    }
++
++    return g_steal_pointer(&ccw);
++}
++
+ int
+ virCCWDeviceAddressIncrement(virCCWDeviceAddress *addr)
+ {
+diff --git a/src/util/virccw.h b/src/util/virccw.h
+index df0273bcac..80cc716811 100644
+--- a/src/util/virccw.h
++++ b/src/util/virccw.h
+@@ -41,6 +41,9 @@ bool virCCWDeviceAddressEqual(virCCWDeviceAddress *addr1,
+ 
+ char* virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
+     ATTRIBUTE_NONNULL(1);
++virCCWDeviceAddress *virCCWDeviceAddressFromString(const char *address)
++    ATTRIBUTE_NONNULL(1);
++
+ int virCCWDeviceAddressIncrement(virCCWDeviceAddress *addr);
+ 
+ int virCCWDeviceAddressParseFromString(const char *address,
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-util-json-Split-out-array-strinlist-conversion-from-virJSONValueObjectGetStringArray.patch b/SOURCES/libvirt-util-json-Split-out-array-strinlist-conversion-from-virJSONValueObjectGetStringArray.patch
new file mode 100644
index 0000000..11146b6
--- /dev/null
+++ b/SOURCES/libvirt-util-json-Split-out-array-strinlist-conversion-from-virJSONValueObjectGetStringArray.patch
@@ -0,0 +1,124 @@
+From b7d9527c9d9cc782933a5b852869cbd10e370a3a Mon Sep 17 00:00:00 2001
+Message-Id: <b7d9527c9d9cc782933a5b852869cbd10e370a3a@dist-git>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Thu, 1 Dec 2022 13:32:07 +0100
+Subject: [PATCH] util: json: Split out array->strinlist conversion from
+ virJSONValueObjectGetStringArray
+
+Introduce virJSONValueArrayToStringList which does only the conversion
+from an array to a stringlist.
+
+This will allow refactoring the callers to be more careful in case when
+they want to handle the existance of the member in the parent object
+differently.
+
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 6765bdeaf7e9cbdb4c39d47f3b77fb28a498408a)
+https://bugzilla.redhat.com/show_bug.cgi?id=2149752
+---
+ src/libvirt_private.syms |  1 +
+ src/util/virjson.c       | 43 ++++++++++++++++++++++------------------
+ src/util/virjson.h       |  2 ++
+ 3 files changed, 27 insertions(+), 19 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 5b7a056151..fa734dfd33 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -2513,6 +2513,7 @@ virJSONValueArrayForeachSteal;
+ virJSONValueArrayGet;
+ virJSONValueArraySize;
+ virJSONValueArraySteal;
++virJSONValueArrayToStringList;
+ virJSONValueCopy;
+ virJSONValueFree;
+ virJSONValueFromString;
+diff --git a/src/util/virjson.c b/src/util/virjson.c
+index 6e13e97e15..5f1565107d 100644
+--- a/src/util/virjson.c
++++ b/src/util/virjson.c
+@@ -1312,10 +1312,7 @@ virJSONValueObjectStealObject(virJSONValue *object,
+ char **
+ virJSONValueObjectGetStringArray(virJSONValue *object, const char *key)
+ {
+-    g_auto(GStrv) ret = NULL;
+     virJSONValue *data;
+-    size_t n;
+-    size_t i;
+ 
+     data = virJSONValueObjectGetArray(object, key);
+     if (!data) {
+@@ -1325,32 +1322,40 @@ virJSONValueObjectGetStringArray(virJSONValue *object, const char *key)
+         return NULL;
+     }
+ 
+-    n = virJSONValueArraySize(data);
+-    ret = g_new0(char *, n + 1);
++    return virJSONValueArrayToStringList(data);
++}
++
++
++/**
++ * virJSONValueArrayToStringList:
++ * @data: a JSON array containing strings to convert
++ *
++ * Converts @data a JSON array containing strings to a NULL-terminated string
++ * list. @data must be a JSON array. In case @data is doesn't contain only
++ * strings an error is reported.
++ */
++char **
++virJSONValueArrayToStringList(virJSONValue *data)
++{
++    size_t n = virJSONValueArraySize(data);
++    g_auto(GStrv) ret = g_new0(char *, n + 1);
++    size_t i;
++
+     for (i = 0; i < n; i++) {
+         virJSONValue *child = virJSONValueArrayGet(data, i);
+-        const char *tmp;
+ 
+-        if (!child) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("%s array element is missing item %zu"),
+-                           key, i);
++        if (!child ||
++            !(ret[i] = g_strdup(virJSONValueGetString(child)))) {
++            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                           _("JSON string array contains non-string element"));
+             return NULL;
+         }
+-
+-        if (!(tmp = virJSONValueGetString(child))) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("%s array element does not contain a string"),
+-                           key);
+-            return NULL;
+-        }
+-
+-        ret[i] = g_strdup(tmp);
+     }
+ 
+     return g_steal_pointer(&ret);
+ }
+ 
++
+ /**
+  * virJSONValueObjectForeachKeyValue:
+  * @object: JSON object to iterate
+diff --git a/src/util/virjson.h b/src/util/virjson.h
+index aced48a538..c9f83ab2bc 100644
+--- a/src/util/virjson.h
++++ b/src/util/virjson.h
+@@ -172,6 +172,8 @@ virJSONValueObjectGetString(virJSONValue *object,
+ char **
+ virJSONValueObjectGetStringArray(virJSONValue *object,
+                                  const char *key);
++char **
++virJSONValueArrayToStringList(virJSONValue *data);
+ const char *
+ virJSONValueObjectGetStringOrNumber(virJSONValue *object,
+                                     const char *key);
+-- 
+2.39.0
+
diff --git a/SOURCES/libvirt-util-make-reuse-of-ccw-device-address-format-constant.patch b/SOURCES/libvirt-util-make-reuse-of-ccw-device-address-format-constant.patch
new file mode 100644
index 0000000..89b1ac8
--- /dev/null
+++ b/SOURCES/libvirt-util-make-reuse-of-ccw-device-address-format-constant.patch
@@ -0,0 +1,70 @@
+From 94a416e1b67c72c69c19944937acc619503484b3 Mon Sep 17 00:00:00 2001
+Message-Id: <94a416e1b67c72c69c19944937acc619503484b3@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:03 +0200
+Subject: [PATCH] util: make reuse of ccw device address format constant
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit b41163005c0874b1d4809523227cd1921f4852d2)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/device_conf.h  | 1 -
+ src/qemu/qemu_command.c | 2 +-
+ src/util/virccw.c       | 2 +-
+ src/util/virccw.h       | 2 ++
+ 4 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
+index 60d90bbf19..950d333e2e 100644
+--- a/src/conf/device_conf.h
++++ b/src/conf/device_conf.h
+@@ -202,7 +202,6 @@ int virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
+                                       virCCWDeviceAddress *addr);
+ bool virDomainDeviceCCWAddressEqual(virCCWDeviceAddress *addr1,
+                                     virCCWDeviceAddress *addr2);
+-#define VIR_CCW_DEVICE_ADDRESS_FMT "%x.%x.%04x"
+ 
+ int virDomainDeviceDriveAddressParseXML(xmlNodePtr node,
+                                         virDomainDeviceDriveAddress *addr);
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index d23af97e0c..a7855d3370 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -613,7 +613,7 @@ qemuBuildDeviceAddressProps(virJSONValue *props,
+         return 0;
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW: {
+-        g_autofree char *devno = g_strdup_printf("%x.%x.%04x",
++        g_autofree char *devno = g_strdup_printf(VIR_CCW_DEVICE_ADDRESS_FMT,
+                                                  info->addr.ccw.cssid,
+                                                  info->addr.ccw.ssid,
+                                                  info->addr.ccw.devno);
+diff --git a/src/util/virccw.c b/src/util/virccw.c
+index 409287b380..5a19d3a112 100644
+--- a/src/util/virccw.c
++++ b/src/util/virccw.c
+@@ -25,5 +25,5 @@
+ char*
+ virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
+ {
+-    return g_strdup_printf("%x.%x.%04x", addr->cssid, addr->ssid, addr->devno);
++    return g_strdup_printf(VIR_CCW_DEVICE_ADDRESS_FMT, addr->cssid, addr->ssid, addr->devno);
+ }
+diff --git a/src/util/virccw.h b/src/util/virccw.h
+index 21a03406fa..127359c299 100644
+--- a/src/util/virccw.h
++++ b/src/util/virccw.h
+@@ -22,6 +22,8 @@
+ 
+ #include "internal.h"
+ 
++#define VIR_CCW_DEVICE_ADDRESS_FMT "%x.%x.%04x"
++
+ typedef struct _virCCWDeviceAddress virCCWDeviceAddress;
+ struct _virCCWDeviceAddress {
+     unsigned int cssid;
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-util-refactor-ccw-address-constants-into-virccw.patch b/SOURCES/libvirt-util-refactor-ccw-address-constants-into-virccw.patch
new file mode 100644
index 0000000..6ee54f7
--- /dev/null
+++ b/SOURCES/libvirt-util-refactor-ccw-address-constants-into-virccw.patch
@@ -0,0 +1,80 @@
+From 58d2890501a5a58eefa0500e1340112bc2264a70 Mon Sep 17 00:00:00 2001
+Message-Id: <58d2890501a5a58eefa0500e1340112bc2264a70@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:04 +0200
+Subject: [PATCH] util: refactor ccw address constants into virccw
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 5fe90d471a312a5c94668f8ed4bb397fdc894c58)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/device_conf.c | 6 +++---
+ src/conf/device_conf.h | 4 ----
+ src/conf/domain_addr.c | 2 +-
+ src/util/virccw.h      | 3 +++
+ 4 files changed, 7 insertions(+), 8 deletions(-)
+
+diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
+index 92b908b2e6..bdc9219f84 100644
+--- a/src/conf/device_conf.c
++++ b/src/conf/device_conf.c
+@@ -261,9 +261,9 @@ virPCIDeviceAddressFormat(virBuffer *buf,
+ bool
+ virDomainDeviceCCWAddressIsValid(virCCWDeviceAddress *addr)
+ {
+-    return addr->cssid <= VIR_DOMAIN_DEVICE_CCW_MAX_CSSID &&
+-           addr->ssid <= VIR_DOMAIN_DEVICE_CCW_MAX_SSID &&
+-           addr->devno <= VIR_DOMAIN_DEVICE_CCW_MAX_DEVNO;
++    return addr->cssid <= VIR_CCW_DEVICE_MAX_CSSID &&
++           addr->ssid <= VIR_CCW_DEVICE_MAX_SSID &&
++           addr->devno <= VIR_CCW_DEVICE_MAX_DEVNO;
+ }
+ 
+ int
+diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
+index 950d333e2e..5c4b7b2f8e 100644
+--- a/src/conf/device_conf.h
++++ b/src/conf/device_conf.h
+@@ -70,10 +70,6 @@ struct _virDomainDeviceVirtioSerialAddress {
+     unsigned int port;
+ };
+ 
+-#define VIR_DOMAIN_DEVICE_CCW_MAX_CSSID    254
+-#define VIR_DOMAIN_DEVICE_CCW_MAX_SSID       3
+-#define VIR_DOMAIN_DEVICE_CCW_MAX_DEVNO  65535
+-
+ typedef struct _virDomainDeviceCcidAddress virDomainDeviceCcidAddress;
+ struct _virDomainDeviceCcidAddress {
+     unsigned int controller;
+diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
+index bf51ef5e5a..655f3cc09e 100644
+--- a/src/conf/domain_addr.c
++++ b/src/conf/domain_addr.c
+@@ -1292,7 +1292,7 @@ virDomainCCWAddressIncrement(virCCWDeviceAddress *addr)
+     virCCWDeviceAddress ccwaddr = *addr;
+ 
+     /* We are not touching subchannel sets and channel subsystems */
+-    if (++ccwaddr.devno > VIR_DOMAIN_DEVICE_CCW_MAX_DEVNO)
++    if (++ccwaddr.devno > VIR_CCW_DEVICE_MAX_DEVNO)
+         return -1;
+ 
+     *addr = ccwaddr;
+diff --git a/src/util/virccw.h b/src/util/virccw.h
+index 127359c299..c3a47127f1 100644
+--- a/src/util/virccw.h
++++ b/src/util/virccw.h
+@@ -22,6 +22,9 @@
+ 
+ #include "internal.h"
+ 
++#define VIR_CCW_DEVICE_MAX_CSSID    254
++#define VIR_CCW_DEVICE_MAX_SSID       3
++#define VIR_CCW_DEVICE_MAX_DEVNO  65535
+ #define VIR_CCW_DEVICE_ADDRESS_FMT "%x.%x.%04x"
+ 
+ typedef struct _virCCWDeviceAddress virCCWDeviceAddress;
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-util-refactor-virDomainCCWAddressAsString-into-virccw.patch b/SOURCES/libvirt-util-refactor-virDomainCCWAddressAsString-into-virccw.patch
new file mode 100644
index 0000000..1aa7b98
--- /dev/null
+++ b/SOURCES/libvirt-util-refactor-virDomainCCWAddressAsString-into-virccw.patch
@@ -0,0 +1,194 @@
+From 531244b8147f8972e56b6ba2c7ecf04c072f296a Mon Sep 17 00:00:00 2001
+Message-Id: <531244b8147f8972e56b6ba2c7ecf04c072f296a@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:02 +0200
+Subject: [PATCH] util: refactor virDomainCCWAddressAsString into virccw
+
+Move virDomainCCWAddressAsString into virccw and rename method as
+virCCWDeviceAddressAsString.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 1df0a1986978dcb7d1fc139f14adbc4f85b1851f)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/domain_addr.c               | 12 +++---------
+ src/conf/domain_addr.h               |  3 ---
+ src/conf/domain_conf.c               |  2 +-
+ src/libvirt_private.syms             |  5 ++++-
+ src/node_device/node_device_driver.c |  2 +-
+ src/util/meson.build                 |  1 +
+ src/util/virccw.c                    | 29 ++++++++++++++++++++++++++++
+ src/util/virccw.h                    |  3 +++
+ 8 files changed, 42 insertions(+), 15 deletions(-)
+ create mode 100644 src/util/virccw.c
+
+diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
+index d584d3b8a8..bf51ef5e5a 100644
+--- a/src/conf/domain_addr.c
++++ b/src/conf/domain_addr.c
+@@ -1286,12 +1286,6 @@ virDomainPCIAddressSetAllMulti(virDomainDef *def)
+ }
+ 
+ 
+-char*
+-virDomainCCWAddressAsString(virCCWDeviceAddress *addr)
+-{
+-    return g_strdup_printf("%x.%x.%04x", addr->cssid, addr->ssid, addr->devno);
+-}
+-
+ static int
+ virDomainCCWAddressIncrement(virCCWDeviceAddress *addr)
+ {
+@@ -1317,7 +1311,7 @@ virDomainCCWAddressAssign(virDomainDeviceInfo *dev,
+         return 0;
+ 
+     if (!autoassign && dev->addr.ccw.assigned) {
+-        if (!(addr = virDomainCCWAddressAsString(&dev->addr.ccw)))
++        if (!(addr = virCCWDeviceAddressAsString(&dev->addr.ccw)))
+             return -1;
+ 
+         if (virHashLookup(addrs->defined, addr)) {
+@@ -1327,7 +1321,7 @@ virDomainCCWAddressAssign(virDomainDeviceInfo *dev,
+             return -1;
+         }
+     } else if (autoassign && !dev->addr.ccw.assigned) {
+-        if (!(addr = virDomainCCWAddressAsString(&addrs->next)))
++        if (!(addr = virCCWDeviceAddressAsString(&addrs->next)))
+             return -1;
+ 
+         while (virHashLookup(addrs->defined, addr)) {
+@@ -1337,7 +1331,7 @@ virDomainCCWAddressAssign(virDomainDeviceInfo *dev,
+                 return -1;
+             }
+             VIR_FREE(addr);
+-            if (!(addr = virDomainCCWAddressAsString(&addrs->next)))
++            if (!(addr = virCCWDeviceAddressAsString(&addrs->next)))
+                 return -1;
+         }
+         dev->addr.ccw = addrs->next;
+diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
+index c8d069e07e..a67851c327 100644
+--- a/src/conf/domain_addr.h
++++ b/src/conf/domain_addr.h
+@@ -205,9 +205,6 @@ int virDomainCCWAddressAssign(virDomainDeviceInfo *dev,
+     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+ void virDomainCCWAddressSetFree(virDomainCCWAddressSet *addrs);
+ 
+-char* virDomainCCWAddressAsString(virCCWDeviceAddress *addr)
+-    ATTRIBUTE_NONNULL(1);
+-
+ virDomainCCWAddressSet *
+ virDomainCCWAddressSetCreateFromDomain(virDomainDef *def)
+     ATTRIBUTE_NONNULL(1);
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index ad3bd56da0..17383fc878 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -15793,7 +15793,7 @@ virDomainNetFindIdx(virDomainDef *def, virDomainNetDef *net)
+         alias = net->info.alias;
+ 
+     if (CCWAddrSpecified)
+-        addr = virDomainCCWAddressAsString(&net->info.addr.ccw);
++        addr = virCCWDeviceAddressAsString(&net->info.addr.ccw);
+     else if (PCIAddrSpecified)
+         addr = virPCIDeviceAddressAsString(&net->info.addr.pci);
+     else
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 568b0f34a1..e8d3edb0fe 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -147,7 +147,6 @@ virPCIDeviceAddressParseXML;
+ 
+ # conf/domain_addr.h
+ virDomainCCWAddressAssign;
+-virDomainCCWAddressAsString;
+ virDomainCCWAddressSetCreateFromDomain;
+ virDomainCCWAddressSetFree;
+ virDomainPCIAddressBusIsFullyReserved;
+@@ -1902,6 +1901,10 @@ virBufferUse;
+ virBufferVasprintf;
+ 
+ 
++# util/virccw.h
++virCCWDeviceAddressAsString;
++
++
+ # util/vircgroup.h
+ virCgroupAddMachineProcess;
+ virCgroupAddProcess;
+diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
+index b0abf59618..e6ab4bb94c 100644
+--- a/src/node_device/node_device_driver.c
++++ b/src/node_device/node_device_driver.c
+@@ -682,7 +682,7 @@ nodeDeviceObjFormatAddress(virNodeDeviceObj *obj)
+                 .devno = caps->data.ccw_dev.devno
+             };
+ 
+-            addr = virDomainCCWAddressAsString(&ccw_addr);
++            addr = virCCWDeviceAddressAsString(&ccw_addr);
+             break;
+             }
+ 
+diff --git a/src/util/meson.build b/src/util/meson.build
+index 24350a3e67..13ed105798 100644
+--- a/src/util/meson.build
++++ b/src/util/meson.build
+@@ -9,6 +9,7 @@ util_sources = [
+   'virbitmap.c',
+   'virbpf.c',
+   'virbuffer.c',
++  'virccw.c',
+   'vircgroup.c',
+   'vircgroupbackend.c',
+   'vircgroupv1.c',
+diff --git a/src/util/virccw.c b/src/util/virccw.c
+new file mode 100644
+index 0000000000..409287b380
+--- /dev/null
++++ b/src/util/virccw.c
+@@ -0,0 +1,29 @@
++/*
++ * virccw.c: helper APIs for managing host CCW devices
++ *
++ * Copyright (C) 2022 IBM Corporation
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++
++#include <config.h>
++#include "virccw.h"
++
++
++char*
++virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
++{
++    return g_strdup_printf("%x.%x.%04x", addr->cssid, addr->ssid, addr->devno);
++}
+diff --git a/src/util/virccw.h b/src/util/virccw.h
+index 701e13284b..21a03406fa 100644
+--- a/src/util/virccw.h
++++ b/src/util/virccw.h
+@@ -29,3 +29,6 @@ struct _virCCWDeviceAddress {
+     unsigned int devno;
+     bool         assigned;
+ };
++
++char* virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
++    ATTRIBUTE_NONNULL(1);
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-util-refactor-virDomainCCWAddressIncrement-into-virccw.patch b/SOURCES/libvirt-util-refactor-virDomainCCWAddressIncrement-into-virccw.patch
new file mode 100644
index 0000000..0af50a1
--- /dev/null
+++ b/SOURCES/libvirt-util-refactor-virDomainCCWAddressIncrement-into-virccw.patch
@@ -0,0 +1,100 @@
+From fcb45d357cc3b6e9ee413014e21de1ab2d20273f Mon Sep 17 00:00:00 2001
+Message-Id: <fcb45d357cc3b6e9ee413014e21de1ab2d20273f@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:05 +0200
+Subject: [PATCH] util: refactor virDomainCCWAddressIncrement into virccw
+
+Refactor virDomainCCWAddressIncrement into virccw and rename method as
+virCCWDeviceAddressIncrement.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit be1e16ed1161173b07f2e8f20f2ca3294ac49406)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/domain_addr.c   | 16 +---------------
+ src/libvirt_private.syms |  1 +
+ src/util/virccw.c        | 13 +++++++++++++
+ src/util/virccw.h        |  1 +
+ 4 files changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
+index 655f3cc09e..b04ab0628b 100644
+--- a/src/conf/domain_addr.c
++++ b/src/conf/domain_addr.c
+@@ -1286,20 +1286,6 @@ virDomainPCIAddressSetAllMulti(virDomainDef *def)
+ }
+ 
+ 
+-static int
+-virDomainCCWAddressIncrement(virCCWDeviceAddress *addr)
+-{
+-    virCCWDeviceAddress ccwaddr = *addr;
+-
+-    /* We are not touching subchannel sets and channel subsystems */
+-    if (++ccwaddr.devno > VIR_CCW_DEVICE_MAX_DEVNO)
+-        return -1;
+-
+-    *addr = ccwaddr;
+-    return 0;
+-}
+-
+-
+ int
+ virDomainCCWAddressAssign(virDomainDeviceInfo *dev,
+                           virDomainCCWAddressSet *addrs,
+@@ -1325,7 +1311,7 @@ virDomainCCWAddressAssign(virDomainDeviceInfo *dev,
+             return -1;
+ 
+         while (virHashLookup(addrs->defined, addr)) {
+-            if (virDomainCCWAddressIncrement(&addrs->next) < 0) {
++            if (virCCWDeviceAddressIncrement(&addrs->next) < 0) {
+                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                _("There are no more free CCW devnos."));
+                 return -1;
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index e8d3edb0fe..eb56292b34 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1903,6 +1903,7 @@ virBufferVasprintf;
+ 
+ # util/virccw.h
+ virCCWDeviceAddressAsString;
++virCCWDeviceAddressIncrement;
+ 
+ 
+ # util/vircgroup.h
+diff --git a/src/util/virccw.c b/src/util/virccw.c
+index 5a19d3a112..d14d432414 100644
+--- a/src/util/virccw.c
++++ b/src/util/virccw.c
+@@ -27,3 +27,16 @@ virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
+ {
+     return g_strdup_printf(VIR_CCW_DEVICE_ADDRESS_FMT, addr->cssid, addr->ssid, addr->devno);
+ }
++
++int
++virCCWDeviceAddressIncrement(virCCWDeviceAddress *addr)
++{
++    virCCWDeviceAddress ccwaddr = *addr;
++
++    /* We are not touching subchannel sets and channel subsystems */
++    if (++ccwaddr.devno > VIR_CCW_DEVICE_MAX_DEVNO)
++        return -1;
++
++    *addr = ccwaddr;
++    return 0;
++}
+diff --git a/src/util/virccw.h b/src/util/virccw.h
+index c3a47127f1..4c48c9605e 100644
+--- a/src/util/virccw.h
++++ b/src/util/virccw.h
+@@ -37,3 +37,4 @@ struct _virCCWDeviceAddress {
+ 
+ char* virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
+     ATTRIBUTE_NONNULL(1);
++int virCCWDeviceAddressIncrement(virCCWDeviceAddress *addr);
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-util-refactor-virDomainDeviceCCWAddress-into-virccw.h.patch b/SOURCES/libvirt-util-refactor-virDomainDeviceCCWAddress-into-virccw.h.patch
new file mode 100644
index 0000000..03afcc6
--- /dev/null
+++ b/SOURCES/libvirt-util-refactor-virDomainDeviceCCWAddress-into-virccw.h.patch
@@ -0,0 +1,299 @@
+From a259f2fc77dac6fa2fd7910d4c96d231b0ea3182 Mon Sep 17 00:00:00 2001
+Message-Id: <a259f2fc77dac6fa2fd7910d4c96d231b0ea3182@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:01 +0200
+Subject: [PATCH] util: refactor virDomainDeviceCCWAddress into virccw.h
+
+Refactor ccw data structure virDomainDeviceCCWAddress into util virccw.h
+and rename it as virCCWDeviceAddress.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 45a8e3988f7b087b3b721e74ce5e6b5658b2b424)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/device_conf.c               |  8 +++----
+ src/conf/device_conf.h               | 19 ++++++-----------
+ src/conf/domain_addr.c               |  6 +++---
+ src/conf/domain_addr.h               |  4 ++--
+ src/conf/domain_conf.c               |  6 +++---
+ src/conf/domain_conf.h               |  6 +++---
+ src/node_device/node_device_driver.c |  2 +-
+ src/qemu/qemu_agent.c                |  4 ++--
+ src/qemu/qemu_agent.h                |  2 +-
+ src/util/virccw.h                    | 31 ++++++++++++++++++++++++++++
+ 10 files changed, 56 insertions(+), 32 deletions(-)
+ create mode 100644 src/util/virccw.h
+
+diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
+index cb523d3a0d..92b908b2e6 100644
+--- a/src/conf/device_conf.c
++++ b/src/conf/device_conf.c
+@@ -259,7 +259,7 @@ virPCIDeviceAddressFormat(virBuffer *buf,
+ }
+ 
+ bool
+-virDomainDeviceCCWAddressIsValid(virDomainDeviceCCWAddress *addr)
++virDomainDeviceCCWAddressIsValid(virCCWDeviceAddress *addr)
+ {
+     return addr->cssid <= VIR_DOMAIN_DEVICE_CCW_MAX_CSSID &&
+            addr->ssid <= VIR_DOMAIN_DEVICE_CCW_MAX_SSID &&
+@@ -268,7 +268,7 @@ virDomainDeviceCCWAddressIsValid(virDomainDeviceCCWAddress *addr)
+ 
+ int
+ virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
+-                                  virDomainDeviceCCWAddress *addr)
++                                  virCCWDeviceAddress *addr)
+ {
+     int cssid;
+     int ssid;
+@@ -307,8 +307,8 @@ virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
+ }
+ 
+ bool
+-virDomainDeviceCCWAddressEqual(virDomainDeviceCCWAddress *addr1,
+-                               virDomainDeviceCCWAddress *addr2)
++virDomainDeviceCCWAddressEqual(virCCWDeviceAddress *addr1,
++                               virCCWDeviceAddress *addr2)
+ {
+     if (addr1->cssid == addr2->cssid &&
+         addr1->ssid == addr2->ssid &&
+diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
+index b6b710d313..60d90bbf19 100644
+--- a/src/conf/device_conf.h
++++ b/src/conf/device_conf.h
+@@ -27,6 +27,7 @@
+ #include "internal.h"
+ #include "virthread.h"
+ #include "virbuffer.h"
++#include "virccw.h"
+ #include "virpci.h"
+ #include "virnetdev.h"
+ #include "virenum.h"
+@@ -73,14 +74,6 @@ struct _virDomainDeviceVirtioSerialAddress {
+ #define VIR_DOMAIN_DEVICE_CCW_MAX_SSID       3
+ #define VIR_DOMAIN_DEVICE_CCW_MAX_DEVNO  65535
+ 
+-typedef struct _virDomainDeviceCCWAddress virDomainDeviceCCWAddress;
+-struct _virDomainDeviceCCWAddress {
+-    unsigned int cssid;
+-    unsigned int ssid;
+-    unsigned int devno;
+-    bool         assigned;
+-};
+-
+ typedef struct _virDomainDeviceCcidAddress virDomainDeviceCcidAddress;
+ struct _virDomainDeviceCcidAddress {
+     unsigned int controller;
+@@ -136,7 +129,7 @@ struct _virDomainDeviceInfo {
+         virDomainDeviceCcidAddress ccid;
+         virDomainDeviceUSBAddress usb;
+         virDomainDeviceSpaprVioAddress spaprvio;
+-        virDomainDeviceCCWAddress ccw;
++        virCCWDeviceAddress ccw;
+         virDomainDeviceISAAddress isa;
+         virDomainDeviceDimmAddress dimm;
+     } addr;
+@@ -204,11 +197,11 @@ void virPCIDeviceAddressFormat(virBuffer *buf,
+                                virPCIDeviceAddress addr,
+                                bool includeTypeInAddr);
+ 
+-bool virDomainDeviceCCWAddressIsValid(virDomainDeviceCCWAddress *addr);
++bool virDomainDeviceCCWAddressIsValid(virCCWDeviceAddress *addr);
+ int virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
+-                                      virDomainDeviceCCWAddress *addr);
+-bool virDomainDeviceCCWAddressEqual(virDomainDeviceCCWAddress *addr1,
+-                                    virDomainDeviceCCWAddress *addr2);
++                                      virCCWDeviceAddress *addr);
++bool virDomainDeviceCCWAddressEqual(virCCWDeviceAddress *addr1,
++                                    virCCWDeviceAddress *addr2);
+ #define VIR_CCW_DEVICE_ADDRESS_FMT "%x.%x.%04x"
+ 
+ int virDomainDeviceDriveAddressParseXML(xmlNodePtr node,
+diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
+index 49745ba881..d584d3b8a8 100644
+--- a/src/conf/domain_addr.c
++++ b/src/conf/domain_addr.c
+@@ -1287,15 +1287,15 @@ virDomainPCIAddressSetAllMulti(virDomainDef *def)
+ 
+ 
+ char*
+-virDomainCCWAddressAsString(virDomainDeviceCCWAddress *addr)
++virDomainCCWAddressAsString(virCCWDeviceAddress *addr)
+ {
+     return g_strdup_printf("%x.%x.%04x", addr->cssid, addr->ssid, addr->devno);
+ }
+ 
+ static int
+-virDomainCCWAddressIncrement(virDomainDeviceCCWAddress *addr)
++virDomainCCWAddressIncrement(virCCWDeviceAddress *addr)
+ {
+-    virDomainDeviceCCWAddress ccwaddr = *addr;
++    virCCWDeviceAddress ccwaddr = *addr;
+ 
+     /* We are not touching subchannel sets and channel subsystems */
+     if (++ccwaddr.devno > VIR_DOMAIN_DEVICE_CCW_MAX_DEVNO)
+diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
+index 814b556024..c8d069e07e 100644
+--- a/src/conf/domain_addr.h
++++ b/src/conf/domain_addr.h
+@@ -195,7 +195,7 @@ void virDomainPCIAddressSetAllMulti(virDomainDef *def)
+ 
+ struct _virDomainCCWAddressSet {
+     GHashTable *defined;
+-    virDomainDeviceCCWAddress next;
++    virCCWDeviceAddress next;
+ };
+ typedef struct _virDomainCCWAddressSet virDomainCCWAddressSet;
+ 
+@@ -205,7 +205,7 @@ int virDomainCCWAddressAssign(virDomainDeviceInfo *dev,
+     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+ void virDomainCCWAddressSetFree(virDomainCCWAddressSet *addrs);
+ 
+-char* virDomainCCWAddressAsString(virDomainDeviceCCWAddress *addr)
++char* virDomainCCWAddressAsString(virCCWDeviceAddress *addr)
+     ATTRIBUTE_NONNULL(1);
+ 
+ virDomainCCWAddressSet *
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 95afd9226e..ad3bd56da0 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -15541,7 +15541,7 @@ virDomainDiskControllerMatch(int controller_type, int disk_bus)
+ int
+ virDomainDiskIndexByAddress(virDomainDef *def,
+                             virPCIDeviceAddress *pci_address,
+-                            virDomainDeviceCCWAddress *ccw_addr,
++                            virCCWDeviceAddress *ccw_addr,
+                             unsigned int bus, unsigned int target,
+                             unsigned int unit)
+ {
+@@ -15585,7 +15585,7 @@ virDomainDiskIndexByAddress(virDomainDef *def,
+ virDomainDiskDef *
+ virDomainDiskByAddress(virDomainDef *def,
+                        virPCIDeviceAddress *pci_address,
+-                       virDomainDeviceCCWAddress *ccw_addr,
++                       virCCWDeviceAddress *ccw_addr,
+                        unsigned int bus,
+                        unsigned int target,
+                        unsigned int unit)
+@@ -16184,7 +16184,7 @@ virDomainControllerFindByType(virDomainDef *def,
+ 
+ int
+ virDomainControllerFindByCCWAddress(virDomainDef *def,
+-                                    virDomainDeviceCCWAddress *addr)
++                                    virCCWDeviceAddress *addr)
+ {
+     size_t i;
+ 
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index 45976beb2b..930af36868 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -3622,12 +3622,12 @@ void virDomainRNGDefFree(virDomainRNGDef *def);
+ 
+ int virDomainDiskIndexByAddress(virDomainDef *def,
+                                 virPCIDeviceAddress *pci_controller,
+-                                virDomainDeviceCCWAddress *ccw_addr,
++                                virCCWDeviceAddress *ccw_addr,
+                                 unsigned int bus, unsigned int target,
+                                 unsigned int unit);
+ virDomainDiskDef *virDomainDiskByAddress(virDomainDef *def,
+                                          virPCIDeviceAddress *pci_controller,
+-                                         virDomainDeviceCCWAddress *ccw_addr,
++                                         virCCWDeviceAddress *ccw_addr,
+                                          unsigned int bus,
+                                          unsigned int target,
+                                          unsigned int unit);
+@@ -3712,7 +3712,7 @@ void virDomainControllerInsertPreAlloced(virDomainDef *def,
+ int virDomainControllerFind(const virDomainDef *def, int type, int idx);
+ int virDomainControllerFindByType(virDomainDef *def, int type);
+ int virDomainControllerFindByCCWAddress(virDomainDef *def,
+-                                        virDomainDeviceCCWAddress *addr);
++                                        virCCWDeviceAddress *addr);
+ int virDomainControllerFindByPCIAddress(virDomainDef *def,
+                                         virPCIDeviceAddress *addr);
+ int virDomainControllerFindUnusedIndex(virDomainDef const *def, int type);
+diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
+index d19ed7d948..b0abf59618 100644
+--- a/src/node_device/node_device_driver.c
++++ b/src/node_device/node_device_driver.c
+@@ -676,7 +676,7 @@ nodeDeviceObjFormatAddress(virNodeDeviceObj *obj)
+             }
+ 
+         case VIR_NODE_DEV_CAP_CSS_DEV: {
+-            virDomainDeviceCCWAddress ccw_addr = {
++            virCCWDeviceAddress ccw_addr = {
+                 .cssid = caps->data.ccw_dev.cssid,
+                 .ssid = caps->data.ccw_dev.ssid,
+                 .devno = caps->data.ccw_dev.devno
+diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
+index 8a55044c9e..db844148a6 100644
+--- a/src/qemu/qemu_agent.c
++++ b/src/qemu/qemu_agent.c
+@@ -1769,9 +1769,9 @@ qemuAgentGetDiskAddress(virJSONValue *json)
+     GET_DISK_ADDR(pci, &addr->pci_controller.function, "function");
+ 
+     if ((ccw = virJSONValueObjectGet(json, "ccw-address"))) {
+-        g_autofree virDomainDeviceCCWAddress *ccw_addr = NULL;
++        g_autofree virCCWDeviceAddress *ccw_addr = NULL;
+ 
+-        ccw_addr = g_new0(virDomainDeviceCCWAddress, 1);
++        ccw_addr = g_new0(virCCWDeviceAddress, 1);
+ 
+         GET_DISK_ADDR(ccw, &ccw_addr->cssid, "cssid");
+         if (ccw_addr->cssid == 0)  /* Guest CSSID 0 is 0xfe on host */
+diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
+index 862f6b0a95..c07d8507ba 100644
+--- a/src/qemu/qemu_agent.h
++++ b/src/qemu/qemu_agent.h
+@@ -72,7 +72,7 @@ struct _qemuAgentDiskAddress {
+     unsigned int target;
+     unsigned int unit;
+     char *devnode;
+-    virDomainDeviceCCWAddress *ccw_addr;
++    virCCWDeviceAddress *ccw_addr;
+ };
+ void qemuAgentDiskAddressFree(qemuAgentDiskAddress *addr);
+ G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuAgentDiskAddress, qemuAgentDiskAddressFree);
+diff --git a/src/util/virccw.h b/src/util/virccw.h
+new file mode 100644
+index 0000000000..701e13284b
+--- /dev/null
++++ b/src/util/virccw.h
+@@ -0,0 +1,31 @@
++/*
++ * virccw.h: helper APIs for managing host CCW devices
++ *
++ * Copyright (C) 2022 IBM Corporation
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++
++#pragma once
++
++#include "internal.h"
++
++typedef struct _virCCWDeviceAddress virCCWDeviceAddress;
++struct _virCCWDeviceAddress {
++    unsigned int cssid;
++    unsigned int ssid;
++    unsigned int devno;
++    bool         assigned;
++};
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-util-refactor-virDomainDeviceCCWAddressEqual-into-virccw.patch b/SOURCES/libvirt-util-refactor-virDomainDeviceCCWAddressEqual-into-virccw.patch
new file mode 100644
index 0000000..4ab216e
--- /dev/null
+++ b/SOURCES/libvirt-util-refactor-virDomainDeviceCCWAddressEqual-into-virccw.patch
@@ -0,0 +1,151 @@
+From 71f605aed8cb1f27eef21953005b3251e41e1925 Mon Sep 17 00:00:00 2001
+Message-Id: <71f605aed8cb1f27eef21953005b3251e41e1925@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:07 +0200
+Subject: [PATCH] util: refactor virDomainDeviceCCWAddressEqual into virccw
+
+Refactor virDomainDeviceCCWAddressEqual into virccw and rename method as
+virCCWDeviceAddressEqual.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 784b87603517bd920910ccfb69daae8980a21d8d)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/device_conf.c   | 12 ------------
+ src/conf/device_conf.h   |  2 --
+ src/conf/domain_conf.c   |  8 ++++----
+ src/libvirt_private.syms |  2 +-
+ src/util/virccw.c        | 12 ++++++++++++
+ src/util/virccw.h        |  2 ++
+ 6 files changed, 19 insertions(+), 19 deletions(-)
+
+diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
+index 2385e81994..958e2f43cc 100644
+--- a/src/conf/device_conf.c
++++ b/src/conf/device_conf.c
+@@ -298,18 +298,6 @@ virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
+     return 0;
+ }
+ 
+-bool
+-virDomainDeviceCCWAddressEqual(virCCWDeviceAddress *addr1,
+-                               virCCWDeviceAddress *addr2)
+-{
+-    if (addr1->cssid == addr2->cssid &&
+-        addr1->ssid == addr2->ssid &&
+-        addr1->devno == addr2->devno) {
+-        return true;
+-    }
+-    return false;
+-}
+-
+ int
+ virDomainDeviceDriveAddressParseXML(xmlNodePtr node,
+                                     virDomainDeviceDriveAddress *addr)
+diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
+index 0ed6991c23..01e2edccc9 100644
+--- a/src/conf/device_conf.h
++++ b/src/conf/device_conf.h
+@@ -195,8 +195,6 @@ void virPCIDeviceAddressFormat(virBuffer *buf,
+ 
+ int virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
+                                       virCCWDeviceAddress *addr);
+-bool virDomainDeviceCCWAddressEqual(virCCWDeviceAddress *addr1,
+-                                    virCCWDeviceAddress *addr2);
+ 
+ int virDomainDeviceDriveAddressParseXML(xmlNodePtr node,
+                                         virDomainDeviceDriveAddress *addr);
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index 17383fc878..1e1c7f01b1 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -15566,7 +15566,7 @@ virDomainDiskIndexByAddress(virDomainDef *def,
+             return i;
+         if (vdisk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
+             ccw_addr &&
+-            virDomainDeviceCCWAddressEqual(&vdisk->info.addr.ccw, ccw_addr)) {
++            virCCWDeviceAddressEqual(&vdisk->info.addr.ccw, ccw_addr)) {
+             return i;
+         }
+         if (vdisk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) {
+@@ -15755,8 +15755,8 @@ virDomainNetFindIdx(virDomainDef *def, virDomainNetDef *net)
+             continue;
+ 
+         if (CCWAddrSpecified &&
+-            !virDomainDeviceCCWAddressEqual(&def->nets[i]->info.addr.ccw,
+-                                            &net->info.addr.ccw))
++            !virCCWDeviceAddressEqual(&def->nets[i]->info.addr.ccw,
++                                      &net->info.addr.ccw))
+             continue;
+ 
+         if (net->info.alias && def->nets[i]->info.alias &&
+@@ -16192,7 +16192,7 @@ virDomainControllerFindByCCWAddress(virDomainDef *def,
+         virDomainDeviceInfo *info = &def->controllers[i]->info;
+ 
+         if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
+-            virDomainDeviceCCWAddressEqual(&info->addr.ccw, addr))
++            virCCWDeviceAddressEqual(&info->addr.ccw, addr))
+             return i;
+     }
+ 
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 9ed367d427..0d3ee4c20a 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -131,7 +131,6 @@ virDeviceInfoPCIAddressIsWanted;
+ virDomainDeviceAddressIsValid;
+ virDomainDeviceAddressTypeToString;
+ virDomainDeviceCcidAddressParseXML;
+-virDomainDeviceCCWAddressEqual;
+ virDomainDeviceCCWAddressParseXML;
+ virDomainDeviceDriveAddressParseXML;
+ virDomainDeviceInfoAddressIsEqual;
+@@ -1902,6 +1901,7 @@ virBufferVasprintf;
+ 
+ # util/virccw.h
+ virCCWDeviceAddressAsString;
++virCCWDeviceAddressEqual;
+ virCCWDeviceAddressIncrement;
+ virCCWDeviceAddressIsValid;
+ 
+diff --git a/src/util/virccw.c b/src/util/virccw.c
+index c3dfda2613..e2785bd9ab 100644
+--- a/src/util/virccw.c
++++ b/src/util/virccw.c
+@@ -30,6 +30,18 @@ virCCWDeviceAddressIsValid(virCCWDeviceAddress *addr)
+            addr->devno <= VIR_CCW_DEVICE_MAX_DEVNO;
+ }
+ 
++bool
++virCCWDeviceAddressEqual(virCCWDeviceAddress *addr1,
++                         virCCWDeviceAddress *addr2)
++{
++    if (addr1->cssid == addr2->cssid &&
++        addr1->ssid == addr2->ssid &&
++        addr1->devno == addr2->devno) {
++        return true;
++    }
++    return false;
++}
++
+ char*
+ virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
+ {
+diff --git a/src/util/virccw.h b/src/util/virccw.h
+index c4daaff7b3..aebbd4ab6d 100644
+--- a/src/util/virccw.h
++++ b/src/util/virccw.h
+@@ -36,6 +36,8 @@ struct _virCCWDeviceAddress {
+ };
+ 
+ bool virCCWDeviceAddressIsValid(virCCWDeviceAddress *addr);
++bool virCCWDeviceAddressEqual(virCCWDeviceAddress *addr1,
++                              virCCWDeviceAddress *addr2);
+ 
+ char* virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
+     ATTRIBUTE_NONNULL(1);
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-util-refactor-virDomainDeviceCCWAddressIsValid-into-virccw.patch b/SOURCES/libvirt-util-refactor-virDomainDeviceCCWAddressIsValid-into-virccw.patch
new file mode 100644
index 0000000..5529038
--- /dev/null
+++ b/SOURCES/libvirt-util-refactor-virDomainDeviceCCWAddressIsValid-into-virccw.patch
@@ -0,0 +1,126 @@
+From 3de657416726803a56fb5b025396bccdd8bfa955 Mon Sep 17 00:00:00 2001
+Message-Id: <3de657416726803a56fb5b025396bccdd8bfa955@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Fri, 13 May 2022 12:31:06 +0200
+Subject: [PATCH] util: refactor virDomainDeviceCCWAddressIsValid into virccw
+
+Refactor virDomainDeviceCCWAddressIsValid into virccw and rename method
+as virCCWDeviceAddressIsValid.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 38756ce5ba17d31597a3470d07708a21bf460c9b)
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2165011
+Signed-off-by: Thomas Huth <thuth@redhat.com>
+---
+ src/conf/device_conf.c   | 12 ++----------
+ src/conf/device_conf.h   |  1 -
+ src/libvirt_private.syms |  2 +-
+ src/util/virccw.c        |  8 ++++++++
+ src/util/virccw.h        |  2 ++
+ 5 files changed, 13 insertions(+), 12 deletions(-)
+
+diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
+index bdc9219f84..2385e81994 100644
+--- a/src/conf/device_conf.c
++++ b/src/conf/device_conf.c
+@@ -258,14 +258,6 @@ virPCIDeviceAddressFormat(virBuffer *buf,
+                       addr.function);
+ }
+ 
+-bool
+-virDomainDeviceCCWAddressIsValid(virCCWDeviceAddress *addr)
+-{
+-    return addr->cssid <= VIR_CCW_DEVICE_MAX_CSSID &&
+-           addr->ssid <= VIR_CCW_DEVICE_MAX_SSID &&
+-           addr->devno <= VIR_CCW_DEVICE_MAX_DEVNO;
+-}
+-
+ int
+ virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
+                                   virCCWDeviceAddress *addr)
+@@ -288,7 +280,7 @@ virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
+                                 &addr->devno)) < 0)
+         return -1;
+ 
+-    if (!virDomainDeviceCCWAddressIsValid(addr)) {
++    if (!virCCWDeviceAddressIsValid(addr)) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Invalid specification for virtio ccw address: cssid='0x%x' ssid='0x%x' devno='0x%04x'"),
+                        addr->cssid, addr->ssid, addr->devno);
+@@ -453,7 +445,7 @@ virDomainDeviceAddressIsValid(virDomainDeviceInfo *info,
+         return true;
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
+-        return virDomainDeviceCCWAddressIsValid(&info->addr.ccw);
++        return virCCWDeviceAddressIsValid(&info->addr.ccw);
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB:
+         return true;
+diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
+index 5c4b7b2f8e..0ed6991c23 100644
+--- a/src/conf/device_conf.h
++++ b/src/conf/device_conf.h
+@@ -193,7 +193,6 @@ void virPCIDeviceAddressFormat(virBuffer *buf,
+                                virPCIDeviceAddress addr,
+                                bool includeTypeInAddr);
+ 
+-bool virDomainDeviceCCWAddressIsValid(virCCWDeviceAddress *addr);
+ int virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
+                                       virCCWDeviceAddress *addr);
+ bool virDomainDeviceCCWAddressEqual(virCCWDeviceAddress *addr1,
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index eb56292b34..9ed367d427 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -132,7 +132,6 @@ virDomainDeviceAddressIsValid;
+ virDomainDeviceAddressTypeToString;
+ virDomainDeviceCcidAddressParseXML;
+ virDomainDeviceCCWAddressEqual;
+-virDomainDeviceCCWAddressIsValid;
+ virDomainDeviceCCWAddressParseXML;
+ virDomainDeviceDriveAddressParseXML;
+ virDomainDeviceInfoAddressIsEqual;
+@@ -1904,6 +1903,7 @@ virBufferVasprintf;
+ # util/virccw.h
+ virCCWDeviceAddressAsString;
+ virCCWDeviceAddressIncrement;
++virCCWDeviceAddressIsValid;
+ 
+ 
+ # util/vircgroup.h
+diff --git a/src/util/virccw.c b/src/util/virccw.c
+index d14d432414..c3dfda2613 100644
+--- a/src/util/virccw.c
++++ b/src/util/virccw.c
+@@ -22,6 +22,14 @@
+ #include "virccw.h"
+ 
+ 
++bool
++virCCWDeviceAddressIsValid(virCCWDeviceAddress *addr)
++{
++    return addr->cssid <= VIR_CCW_DEVICE_MAX_CSSID &&
++           addr->ssid <= VIR_CCW_DEVICE_MAX_SSID &&
++           addr->devno <= VIR_CCW_DEVICE_MAX_DEVNO;
++}
++
+ char*
+ virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
+ {
+diff --git a/src/util/virccw.h b/src/util/virccw.h
+index 4c48c9605e..c4daaff7b3 100644
+--- a/src/util/virccw.h
++++ b/src/util/virccw.h
+@@ -35,6 +35,8 @@ struct _virCCWDeviceAddress {
+     bool         assigned;
+ };
+ 
++bool virCCWDeviceAddressIsValid(virCCWDeviceAddress *addr);
++
+ char* virCCWDeviceAddressAsString(virCCWDeviceAddress *addr)
+     ATTRIBUTE_NONNULL(1);
+ int virCCWDeviceAddressIncrement(virCCWDeviceAddress *addr);
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-vircpi-Add-PCIe-5.0-and-6.0-link-speeds.patch b/SOURCES/libvirt-vircpi-Add-PCIe-5.0-and-6.0-link-speeds.patch
new file mode 100644
index 0000000..0efd778
--- /dev/null
+++ b/SOURCES/libvirt-vircpi-Add-PCIe-5.0-and-6.0-link-speeds.patch
@@ -0,0 +1,65 @@
+From 0a192b453da043cfb3679a07b55c1628b56efdde Mon Sep 17 00:00:00 2001
+Message-Id: <0a192b453da043cfb3679a07b55c1628b56efdde@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 8 Jul 2022 14:29:32 +0200
+Subject: [PATCH] vircpi: Add PCIe 5.0 and 6.0 link speeds
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The PCIe 5.0 and PCIe 6.0 standards define new link speeds:
+32GT/s and 64GT/s, respectively. Update our internal enum to
+include these new speeds. Otherwise we format incorrect XML:
+
+  <pci-express>
+    <link validity='cap' port='0' speed='(null)' width='16'/>
+    <link validity='sta' speed='16' width='16'/>
+  </pci-express>
+
+Like all "good" specifications, these are also locked behind a
+login portal. But we can look at pciutils' source code: [1] and
+[2].
+
+1: https://git.kernel.org/pub/scm/utils/pciutils/pciutils.git/commit/ls-caps.c?id=caca31a0eea41c7b051705704c1158fddc02fbd2
+2: https://git.kernel.org/pub/scm/utils/pciutils/pciutils.git/commit/ls-caps.c?id=5bdf63b6b1bc35b59c4b3f47f7ca83ca1868155b
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2105231
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit d33c2a9e2f933b31f8e96e9938c237bdffe27f84)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2168116
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/util/virpci.c | 2 +-
+ src/util/virpci.h | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/virpci.c b/src/util/virpci.c
+index 0d476cd8b4..4949d1a3d4 100644
+--- a/src/util/virpci.c
++++ b/src/util/virpci.c
+@@ -46,7 +46,7 @@ VIR_LOG_INIT("util.pci");
+ 
+ VIR_ENUM_IMPL(virPCIELinkSpeed,
+               VIR_PCIE_LINK_SPEED_LAST,
+-              "", "2.5", "5", "8", "16",
++              "", "2.5", "5", "8", "16", "32", "64"
+ );
+ 
+ VIR_ENUM_IMPL(virPCIStubDriver,
+diff --git a/src/util/virpci.h b/src/util/virpci.h
+index b9b9cd7b34..4d9193f24e 100644
+--- a/src/util/virpci.h
++++ b/src/util/virpci.h
+@@ -83,6 +83,8 @@ typedef enum {
+     VIR_PCIE_LINK_SPEED_5,
+     VIR_PCIE_LINK_SPEED_8,
+     VIR_PCIE_LINK_SPEED_16,
++    VIR_PCIE_LINK_SPEED_32,
++    VIR_PCIE_LINK_SPEED_64,
+     VIR_PCIE_LINK_SPEED_LAST
+ } virPCIELinkSpeed;
+ 
+-- 
+2.39.1
+
diff --git a/SOURCES/libvirt-virpidfile-Add-virPidFileReadPathIfLocked-func.patch b/SOURCES/libvirt-virpidfile-Add-virPidFileReadPathIfLocked-func.patch
new file mode 100644
index 0000000..b3b154f
--- /dev/null
+++ b/SOURCES/libvirt-virpidfile-Add-virPidFileReadPathIfLocked-func.patch
@@ -0,0 +1,96 @@
+From 9d0247153a70ab1909d0690ec9b7f4d20e8cb602 Mon Sep 17 00:00:00 2001
+Message-Id: <9d0247153a70ab1909d0690ec9b7f4d20e8cb602@dist-git>
+From: Vasiliy Ulyanov <vulyanov@suse.de>
+Date: Wed, 2 Feb 2022 17:28:15 +0100
+Subject: [PATCH] virpidfile: Add virPidFileReadPathIfLocked func
+
+The function will attempt to read a pid from @path, and store it in
+@pid. The @pid will only be set, however, if @path is locked by
+virFileLock() at byte 0 and the pid in @path is running.
+
+Signed-off-by: Vasiliy Ulyanov <vulyanov@suse.de>
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 013ab22f79d1345daf6b2778ca498acb16939011)
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2152188
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/libvirt_private.syms |  1 +
+ src/util/virpidfile.c    | 35 +++++++++++++++++++++++++++++++++++
+ src/util/virpidfile.h    |  2 ++
+ 3 files changed, 38 insertions(+)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index fa734dfd33..568b0f34a1 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -3061,6 +3061,7 @@ virPidFileRead;
+ virPidFileReadIfAlive;
+ virPidFileReadPath;
+ virPidFileReadPathIfAlive;
++virPidFileReadPathIfLocked;
+ virPidFileRelease;
+ virPidFileReleasePath;
+ virPidFileWrite;
+diff --git a/src/util/virpidfile.c b/src/util/virpidfile.c
+index 7069f8343d..9d194f7336 100644
+--- a/src/util/virpidfile.c
++++ b/src/util/virpidfile.c
+@@ -302,6 +302,41 @@ int virPidFileReadIfAlive(const char *dir,
+     return 0;
+ }
+ 
++/**
++ * virPidFileReadPathIfLocked:
++ * @path: path to pidfile
++ * @pid: variable to return pid in
++ *
++ * This will attempt to read a pid from @path, and store it in
++ * @pid. The @pid will only be set, however, if the pid in @path
++ * is running, and @path is locked by virFileLock() at byte 0
++ * (which is exactly what virCommandSetPidFile() results in).
++ * This adds protection against returning a stale pid.
++ *
++ * Returns -1 upon error, or zero on successful
++ * reading of the pidfile. If @path is not locked
++ * or if the PID was not still alive, zero will
++ * be returned, but @pid will be set to -1.
++ */
++int virPidFileReadPathIfLocked(const char *path, pid_t *pid)
++{
++    VIR_AUTOCLOSE fd = -1;
++
++    if ((fd = open(path, O_RDWR)) < 0)
++        return -1;
++
++    if (virFileLock(fd, false, 0, 1, false) >= 0) {
++        /* The file isn't locked. PID is stale. */
++        *pid = -1;
++        return 0;
++    }
++
++    if (virPidFileReadPathIfAlive(path, pid, NULL) < 0)
++        return -1;
++
++    return 0;
++}
++
+ 
+ int virPidFileDeletePath(const char *pidfile)
+ {
+diff --git a/src/util/virpidfile.h b/src/util/virpidfile.h
+index fd8013c41e..e84542f298 100644
+--- a/src/util/virpidfile.h
++++ b/src/util/virpidfile.h
+@@ -48,6 +48,8 @@ int virPidFileReadIfAlive(const char *dir,
+                           const char *name,
+                           pid_t *pid,
+                           const char *binpath) G_GNUC_WARN_UNUSED_RESULT;
++int virPidFileReadPathIfLocked(const char *path,
++                               pid_t *pid)  G_GNUC_WARN_UNUSED_RESULT;
+ 
+ int virPidFileDeletePath(const char *path);
+ int virPidFileDelete(const char *dir,
+-- 
+2.39.0
+
diff --git a/SPECS/libvirt.spec b/SPECS/libvirt.spec
index 530b2cb..0627d96 100644
--- a/SPECS/libvirt.spec
+++ b/SPECS/libvirt.spec
@@ -210,7 +210,7 @@
 Summary: Library providing a simple virtualization API
 Name: libvirt
 Version: 8.0.0
-Release: 10%{?dist}%{?extra_release}
+Release: 17%{?dist}%{?extra_release}
 License: LGPLv2+
 URL: https://libvirt.org/
 
@@ -267,6 +267,42 @@ Patch44: libvirt-virsh-Add-support-for-VIR_MIGRATE_ZEROCOPY-flag.patch
 Patch45: libvirt-qemu_migration-Implement-VIR_MIGRATE_ZEROCOPY-flag.patch
 Patch46: libvirt-security_selinux.c-Relabel-existing-mode-bind-UNIX-sockets.patch
 Patch47: libvirt-RHEL-qemu_migration-Fix-restoring-memlock-limit-on-destination.patch
+Patch48: libvirt-qemu_process-Don-t-require-a-hugetlbfs-mount-for-memfd.patch
+Patch49: libvirt-qemu_namespace-Tolerate-missing-ACLs-when-creating-a-path-in-namespace.patch
+Patch50: libvirt-qemu_namespace-Fix-a-corner-case-in-qemuDomainGetPreservedMounts.patch
+Patch51: libvirt-qemu_namespace-Introduce-qemuDomainNamespaceSetupPath.patch
+Patch52: libvirt-qemu_process.c-Propagate-hugetlbfs-mounts-on-reconnect.patch
+Patch53: libvirt-qemuProcessReconnect-Don-t-build-memory-paths.patch
+Patch54: libvirt-util-json-Split-out-array-strinlist-conversion-from-virJSONValueObjectGetStringArray.patch
+Patch55: libvirt-qemuAgentGetDisks-Don-t-use-virJSONValueObjectGetStringArray-for-optional-data.patch
+Patch56: libvirt-virpidfile-Add-virPidFileReadPathIfLocked-func.patch
+Patch57: libvirt-qemu-tpm-Get-swtpm-pid-without-binary-validation.patch
+Patch58: libvirt-qemu_tpm-Do-async-IO-when-starting-swtpm-emulator.patch
+Patch59: libvirt-qemu-gpu-Get-pid-without-binary-validation.patch
+Patch60: libvirt-build-Only-install-libvirt-guests-when-building-libvirtd.patch
+Patch61: libvirt-tools-Fix-install_mode-for-some-scripts.patch
+Patch62: libvirt-qemu-Ignore-missing-vm.unprivileged_userfaultfd-sysctl.patch
+Patch63: libvirt-nodedev-fix-reported-error-msg-in-css-cap-XML-parsing.patch
+Patch64: libvirt-util-refactor-virDomainDeviceCCWAddress-into-virccw.h.patch
+Patch65: libvirt-util-refactor-virDomainCCWAddressAsString-into-virccw.patch
+Patch66: libvirt-util-make-reuse-of-ccw-device-address-format-constant.patch
+Patch67: libvirt-util-refactor-ccw-address-constants-into-virccw.patch
+Patch68: libvirt-util-refactor-virDomainCCWAddressIncrement-into-virccw.patch
+Patch69: libvirt-util-refactor-virDomainDeviceCCWAddressIsValid-into-virccw.patch
+Patch70: libvirt-util-refactor-virDomainDeviceCCWAddressEqual-into-virccw.patch
+Patch71: libvirt-conf-adjust-method-name-virDomainDeviceCCWAddressParseXML.patch
+Patch72: libvirt-util-add-ccw-device-address-parsing-into-virccw.patch
+Patch73: libvirt-util-add-virCCWDeviceAddressFromString-to-virccw.patch
+Patch74: libvirt-nodedev-refactor-css-format-from-ccw-format-method.patch
+Patch75: libvirt-nodedev-refactor-ccw-device-address-parsing-from-XML.patch
+Patch76: libvirt-nodedev-refactor-css-XML-parsing-from-ccw-XML-parsing.patch
+Patch77: libvirt-schemas-refactor-out-nodedev-ccw-address-schema.patch
+Patch78: libvirt-nodedev-add-optional-device-address-of-channel-device-to-css-device.patch
+Patch79: libvirt-nodedev-add-tests-for-optional-device-address-to-css-device.patch
+Patch80: libvirt-nodedev-prevent-internal-error-on-dev_busid-parse.patch
+Patch81: libvirt-rpc-Fix-memory-leak-of-fds.patch
+Patch82: libvirt-qemu_namespace-Don-t-leak-memory-in-qemuDomainGetPreservedMounts.patch
+Patch83: libvirt-vircpi-Add-PCIe-5.0-and-6.0-link-speeds.patch
 
 Requires: libvirt-daemon = %{version}-%{release}
 Requires: libvirt-daemon-config-network = %{version}-%{release}
@@ -447,6 +483,12 @@ Summary: Server side daemon and supporting files for libvirt library
 # The client side, i.e. shared libs are in a subpackage
 Requires: %{name}-libs = %{version}-%{release}
 
+# The libvirt-guests.sh script requires virsh from libvirt-client subpackage,
+# but not every deployment wants to use libvirt-guests service. Using
+# Recommends here will install libvirt-client by default (if available), but
+# RPM won't complain if the package is unavailable, masked, or removed later.
+Recommends: %{name}-client = %{version}-%{release}
+
 # netcat is needed on the server side so that clients that have
 # libvirt < 6.9.0 can connect, but newer versions will prefer
 # virt-ssh-helper. Making this a Recommends means that it gets
@@ -2140,6 +2182,57 @@ exit 0
 
 
 %changelog
+* Thu Feb  9 2023 Jiri Denemark <jdenemar@redhat.com> - 8.0.0-17
+- vircpi: Add PCIe 5.0 and 6.0 link speeds (rhbz#2168116)
+
+* Wed Feb  8 2023 Jiri Denemark <jdenemar@redhat.com> - 8.0.0-16
+- qemu_namespace: Don't leak memory in qemuDomainGetPreservedMounts() (rhbz#2166573)
+
+* Tue Jan 31 2023 Jiri Denemark <jdenemar@redhat.com> - 8.0.0-15
+- nodedev: fix reported error msg in css cap XML parsing (rhbz#2165011)
+- util: refactor virDomainDeviceCCWAddress into virccw.h (rhbz#2165011)
+- util: refactor virDomainCCWAddressAsString into virccw (rhbz#2165011)
+- util: make reuse of ccw device address format constant (rhbz#2165011)
+- util: refactor ccw address constants into virccw (rhbz#2165011)
+- util: refactor virDomainCCWAddressIncrement into virccw (rhbz#2165011)
+- util: refactor virDomainDeviceCCWAddressIsValid into virccw (rhbz#2165011)
+- util: refactor virDomainDeviceCCWAddressEqual into virccw (rhbz#2165011)
+- conf: adjust method name virDomainDeviceCCWAddressParseXML (rhbz#2165011)
+- util: add ccw device address parsing into virccw (rhbz#2165011)
+- util: add virCCWDeviceAddressFromString to virccw (rhbz#2165011)
+- nodedev: refactor css format from ccw format method (rhbz#2165011)
+- nodedev: refactor ccw device address parsing from XML (rhbz#2165011)
+- nodedev: refactor css XML parsing from ccw XML parsing (rhbz#2165011)
+- schemas: refactor out nodedev ccw address schema (rhbz#2165011)
+- nodedev: add optional device address of channel device to css device (rhbz#2165011)
+- nodedev: add tests for optional device address to css device (rhbz#2165011)
+- nodedev: prevent internal error on dev_busid parse (rhbz#2165011)
+- rpc: Fix memory leak of fds (rhbz#2165428)
+
+* Wed Jan 11 2023 Jiri Denemark <jdenemar@redhat.com> - 8.0.0-14
+- qemu: Ignore missing vm.unprivileged_userfaultfd sysctl (rhbz#2148578)
+
+* Wed Jan  4 2023 Jiri Denemark <jdenemar@redhat.com> - 8.0.0-13
+- build: Only install libvirt-guests when building libvirtd (rhbz#2153688)
+- tools: Fix install_mode for some scripts (rhbz#2153688)
+
+* Tue Dec 13 2022 Jiri Denemark <jdenemar@redhat.com> - 8.0.0-12
+- util: json: Split out array->strinlist conversion from virJSONValueObjectGetStringArray (rhbz#2149752)
+- qemuAgentGetDisks: Don't use virJSONValueObjectGetStringArray for optional data (rhbz#2149752)
+- virpidfile: Add virPidFileReadPathIfLocked func (rhbz#2152188)
+- qemu: tpm: Get swtpm pid without binary validation (rhbz#2152188)
+- qemu_tpm: Do async IO when starting swtpm emulator (rhbz#2152188)
+- qemu: gpu: Get pid without binary validation (rhbz#2152188)
+- spec: libvirt-daemon: Add optional dependency on *-client (rhbz#2136591)
+
+* Fri Oct  7 2022 Jiri Denemark <jdenemar@redhat.com> - 8.0.0-11
+- qemu_process: Don't require a hugetlbfs mount for memfd (rhbz#2123196)
+- qemu_namespace: Tolerate missing ACLs when creating a path in namespace (rhbz#2123196)
+- qemu_namespace: Fix a corner case in qemuDomainGetPreservedMounts() (rhbz#2123196)
+- qemu_namespace: Introduce qemuDomainNamespaceSetupPath() (rhbz#2123196)
+- qemu_process.c: Propagate hugetlbfs mounts on reconnect (rhbz#2123196)
+- qemuProcessReconnect: Don't build memory paths (rhbz#2123196)
+
 * Mon Jul 25 2022 Jiri Denemark <jdenemar@redhat.com> - 8.0.0-10
 - security_selinux.c: Relabel existing mode="bind" UNIX sockets (rhbz#2101575)
 - RHEL: qemu_migration: Fix restoring memlock limit on destination (rhbz#2107954)