Enable building for ppc64le

This commit is contained in:
Eduard Abdullin 2026-02-18 02:32:00 +00:00 committed by root
commit 51275dda3b
14 changed files with 9618 additions and 2 deletions

View File

@ -0,0 +1,248 @@
From 48f5933f6cd6f53997823cfe2a277b822b00264f Mon Sep 17 00:00:00 2001
Message-ID: <48f5933f6cd6f53997823cfe2a277b822b00264f.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 29 Jan 2026 18:10:26 +0100
Subject: [PATCH] Expose latency histograms via 'virConnectGetAllDomainStats'
Add documentation and constants for constructing the stats field names
for latency histograms and expose them in the qemu driver:
Example:
block.1.latency_histogram.read.bin.count=9
block.1.latency_histogram.read.bin.0.start=0
block.1.latency_histogram.read.bin.0.value=0
block.1.latency_histogram.read.bin.1.start=10
block.1.latency_histogram.read.bin.1.value=0
block.1.latency_histogram.read.bin.2.start=100
block.1.latency_histogram.read.bin.2.value=0
block.1.latency_histogram.read.bin.3.start=1000
block.1.latency_histogram.read.bin.3.value=1047
block.1.latency_histogram.read.bin.4.start=10000
block.1.latency_histogram.read.bin.4.value=2131
block.1.latency_histogram.read.bin.5.start=100000
block.1.latency_histogram.read.bin.5.value=0
block.1.latency_histogram.read.bin.6.start=1000000
block.1.latency_histogram.read.bin.6.value=0
block.1.latency_histogram.read.bin.7.start=10000000
block.1.latency_histogram.read.bin.7.value=0
block.1.latency_histogram.read.bin.8.start=100000000
block.1.latency_histogram.read.bin.8.value=0
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 237e49127a9390f054e33e689ba9db1587cdc9f1)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
docs/manpages/virsh.rst | 7 ++
include/libvirt/libvirt-domain.h | 113 +++++++++++++++++++++++++++++++
src/qemu/qemu_driver.c | 43 ++++++++++++
3 files changed, 163 insertions(+)
diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst
index a9d691824e..ff0cf1a715 100644
--- a/docs/manpages/virsh.rst
+++ b/docs/manpages/virsh.rst
@@ -2811,6 +2811,13 @@ Information listed includes:
pending write operations in the defined interval
* ``block.<num>.timed_group.<num>.zone_append_queue_depth_avg`` - average number
of pending zone append operations in the defined interval
+* ``block.<num>.latency_histogram.<type>.bin.count`` - number of bins in
+ latency histogram. <type> is one of ``read``, ``write``, ``zone_append``, or
+ ``flush``
+* ``block.<num>.latency_histogram.<type>.bin.<num>.start`` start boundary of
+ a latency histogram bin in nanoseconds of given operation duration
+* ``block.<num>.latency_histogram.<type>.bin.<num>.value`` current number of
+ events corresponding to the given bin and type
*--iothread* returns information about IOThreads on the running guest
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 16fac6b085..8e62bd23d4 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -3815,6 +3815,119 @@ struct _virDomainStatsRecord {
*/
# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_SUFFIX_ZONE_APPEND_QUEUE_DEPTH_AVG ".zone_append_queue_depth_avg"
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_READ_PREFIX:
+ *
+ * The parameter name prefix to access 'read' latency histograms. Concatenate
+ * the prefix with either:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT
+ * to get the number of bins in given histogram
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX and
+ * entry number formatted as an unsigned integer and one of the latency
+ * histogram suffix parameters to compelte a full bin parameter name
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_READ_PREFIX ".latency_histogram.read."
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_WRITE_PREFIX:
+ *
+ * The parameter name prefix to access 'write' latency histograms. Concatenate
+ * the prefix with either:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT
+ * to get the number of bins in given histogram
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX and
+ * entry number formatted as an unsigned integer and one of the latency
+ * histogram suffix parameters to compelte a full bin parameter name
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_WRITE_PREFIX ".latency_histogram.write."
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_ZONE_APPEND_PREFIX:
+ *
+ * The parameter name prefix to access 'zone_append' latency histograms. Concatenate
+ * the prefix with either:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT
+ * to get the number of bins in given histogram
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX and
+ * entry number formatted as an unsigned integer and one of the latency
+ * histogram suffix parameters to compelte a full bin parameter name
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_ZONE_APPEND_PREFIX ".latency_histogram.zone_append."
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_FLUSH_PREFIX:
+ *
+ * The parameter name prefix to access 'flush' latency histograms. Concatenate
+ * the prefix with either:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT
+ * to get the number of bins in given histogram
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX and
+ * entry number formatted as an unsigned integer and one of the latency
+ * histogram suffix parameters to compelte a full bin parameter name
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_FLUSH_PREFIX ".latency_histogram.flush."
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT:
+ *
+ * The parameter name suffix to access number of bins in one of the following
+ * latency histogram types:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_READ_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_WRITE_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_ZONE_APPEND_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_FLUSH_PREFIX
+ *
+ * Number of bins in latency histogram as unsigned long long.
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT "bin.count"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX:
+ *
+ * The parameter name suffix to access a latency histogram bin in one of the
+ * following latency histogram types:
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_READ_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_WRITE_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_ZONE_APPEND_PREFIX
+ * - VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_FLUSH_PREFIX
+ *
+ * Concatenate with a bin number as unsigned int and one of the other field
+ * suffixes to access bin parameters.
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX "bin."
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_START:
+ *
+ * Start of the current latency histogram bin in nanoseconds as unsigned long long.
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_START ".start"
+
+/**
+ * VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_VALUE:
+ *
+ * Current value of the number of occurences of the latency within this bin
+ * as unsigned long long.
+ *
+ * Since: 12.1.0
+ */
+# define VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_VALUE ".value"
+
+
/**
* VIR_DOMAIN_STATS_PERF_CMT:
*
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 08a547c546..f3e7410f9e 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -17597,6 +17597,36 @@ qemuDomainGetStatsBlockExportBackendStorage(const char *entryname,
}
+static void
+qemuDomainGetStatsBlockExportFrontendLatencyHistogram(struct qemuBlockStatsLatencyHistogram *h,
+ size_t disk_idx,
+ const char *prefix_hist,
+ virTypedParamList *par)
+{
+ size_t i;
+
+ if (!h)
+ return;
+
+ virTypedParamListAddULLong(par, h->nbins,
+ VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu%s" VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_COUNT,
+ disk_idx, prefix_hist);
+
+ for (i = 0; i < h->nbins; i++) {
+ virTypedParamListAddULLong(par, h->bins[i].start,
+ VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu%s"
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX "%zu"
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_START,
+ disk_idx, prefix_hist, i);
+ virTypedParamListAddULLong(par, h->bins[i].value,
+ VIR_DOMAIN_STATS_BLOCK_PREFIX "%zu%s"
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_PREFIX "%zu"
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_SUFFIX_BIN_SUFFIX_VALUE,
+ disk_idx, prefix_hist, i);
+ }
+}
+
+
static void
qemuDomainGetStatsBlockExportFrontend(const char *frontendname,
GHashTable *stats,
@@ -17721,6 +17751,19 @@ qemuDomainGetStatsBlockExportFrontend(const char *frontendname,
idx, i);
}
}
+
+ qemuDomainGetStatsBlockExportFrontendLatencyHistogram(en->histogram_read, idx,
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_READ_PREFIX,
+ par);
+ qemuDomainGetStatsBlockExportFrontendLatencyHistogram(en->histogram_write, idx,
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_WRITE_PREFIX,
+ par);
+ qemuDomainGetStatsBlockExportFrontendLatencyHistogram(en->histogram_zone, idx,
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_ZONE_APPEND_PREFIX,
+ par);
+ qemuDomainGetStatsBlockExportFrontendLatencyHistogram(en->histogram_flush, idx,
+ VIR_DOMAIN_STATS_BLOCK_SUFFIX_LATENCY_HISTOGRAM_FLUSH_PREFIX,
+ par);
}
--
2.53.0

View File

@ -0,0 +1,422 @@
From 8fbea435edb1635ec98c9419e9249223e5c3b2b6 Mon Sep 17 00:00:00 2001
Message-ID: <8fbea435edb1635ec98c9419e9249223e5c3b2b6.1771336682.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 23 Jan 2026 17:09:27 +0100
Subject: [PATCH] Introduce support for disk operation latency histogram
collection
Add config and docs allowing enabling latency histogram collection for
block device operations.
This patch sets up the docs, schema and XML infrastructure.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit b874c944bd8c4ffa6c51394557587c8c203f1656)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
docs/formatdomain.rst | 41 ++++++
src/conf/domain_conf.c | 133 +++++++++++++++++-
src/conf/domain_conf.h | 7 +
src/conf/schemas/domaincommon.rng | 37 ++++-
...isk-statistics-intervals.x86_64-latest.xml | 29 ++++
.../disk-statistics-intervals.xml | 25 ++++
6 files changed, 262 insertions(+), 10 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 70882c6820..31232deb3c 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -3628,6 +3628,47 @@ paravirtualized driver is specified via the ``disk`` element.
:since:`Since 11.9.0 (QEMU 10.2, virtio, ide, scsi disks only)`.
+ Block operation latency histogram collection can be configured using
+ ``<latency-histogram>`` sub-element. The histogram is collected for
+ the whole runtime of the VM, but can be re-started or reconfigured using
+ the `virDomainUpdateDeviceFlags <html/libvirt-libvirt-domain.html#virDomainUpdateDeviceFlags>`__
+ API. Using the same config re-starts histogram collection.
+
+ The optional ``type`` attribute configures specific operation to collect
+ the histogram for. Supported types are ``read``, ``write``, ``zone``, and
+ ``flush``. If the ``type`` attribute is omitted the histogram collection
+ bins bins apply to all of the aforementioned types, which can be overriden
+ with specific config.
+
+ The ``<latency-histogram>`` has multiple mandatory ``<bin>`` sub-elements
+ with mandatory ``start`` attribute configuring the starting boundary of
+ the histogram bin configured in nanosecods of the operation duration and
+ the intervals must be properly ordered and non-duplicate.
+
+ Example::
+
+ <driver name='qemu'>
+ <statistics>
+
+ <latency-histogram>
+ <bin start='0'/>
+ <bin start='1000'/>
+ <bin start='100000'/>
+ </latency-histogram>
+
+ [or for specific operation types]
+
+ <latency-histogram type='read'>
+ <bin start='0'/>
+ <bin start='1000'/>
+ <bin start='100000'/>
+ </latency-histogram>
+
+ </statistics>
+ </driver>
+
+ :since:`Since 12.1.0`.
+
- The optional ``queues`` attribute specifies the number of virt queues for
virtio-blk ( :since:`Since 3.9.0` ) or vhost-user-blk
( :since:`Since 7.1.0` )
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f5c4d135a9..83c58ab5ff 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2445,6 +2445,11 @@ virDomainDiskDefFree(virDomainDiskDef *def)
virObjectUnref(def->privateData);
g_slist_free_full(def->iothreads, (GDestroyNotify) virDomainIothreadMappingDefFree);
g_free(def->statistics);
+ g_free(def->histogram_boundaries);
+ g_free(def->histogram_boundaries_read);
+ g_free(def->histogram_boundaries_write);
+ g_free(def->histogram_boundaries_zone);
+ g_free(def->histogram_boundaries_flush);
if (def->throttlefilters) {
size_t i;
@@ -8307,6 +8312,91 @@ virDomainIothreadMappingDefParse(xmlNodePtr driverNode,
}
+static int
+virDomainDiskDefDriverParseXMLHistogramOne(virDomainDiskDef *def,
+ xmlNodePtr cur)
+{
+ g_autofree char *histogram_type = NULL;
+ unsigned int **histogram_config = NULL;
+ g_autoptr(GPtrArray) binNodes = virXMLNodeGetSubelementList(cur, "bin");
+ size_t nbins = 0;
+ size_t i;
+
+ if ((histogram_type = virXMLPropString(cur, "type"))) {
+ if (STREQ(histogram_type, "read")) {
+ histogram_config = &def->histogram_boundaries_read;
+ } else if (STREQ(histogram_type, "write")) {
+ histogram_config = &def->histogram_boundaries_write;
+ } else if (STREQ(histogram_type, "zone")) {
+ histogram_config = &def->histogram_boundaries_zone;
+ } else if (STREQ(histogram_type, "flush")) {
+ histogram_config = &def->histogram_boundaries_flush;
+ } else {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("unknown latency_histogram type '%1$s'"),
+ histogram_type);
+ return -1;
+ }
+ } else {
+ histogram_config = &def->histogram_boundaries;
+ }
+
+ if (*histogram_config) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("only one latency-histogram of a given type is supported"));
+ return -1;
+ }
+
+ if (binNodes->len == 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("missing 'bin' elements for 'latency-histogram'"));
+ return -1;
+ }
+
+ *histogram_config = g_new0(unsigned int, binNodes->len + 1);
+
+ for (i = 0; i < binNodes->len; i++) {
+ unsigned int val;
+
+ if (virXMLPropUInt(g_ptr_array_index(binNodes, i),
+ "start", 10,
+ VIR_XML_PROP_REQUIRED,
+ &val) < 0)
+ return -1;
+
+ if (nbins > 0 &&
+ (val == 0 ||
+ val <= (*histogram_config)[nbins-1])) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("the values of 'start' attribute of a 'latency-histogram' 'bin' configuration must be sorted and non-overlapping"));
+ return -1;
+ }
+
+ if (val > 0)
+ (*histogram_config)[nbins++] = val;
+ }
+
+ return 0;
+}
+
+
+static int
+virDomainDiskDefDriverParseXMLHistograms(virDomainDiskDef *def,
+ xmlNodePtr cur)
+{
+ g_autoptr(GPtrArray) histogramNodes = virXMLNodeGetSubelementList(cur, "latency-histogram");
+ size_t i;
+
+ for (i = 0; i < histogramNodes->len; i++) {
+ if (virDomainDiskDefDriverParseXMLHistogramOne(def,
+ g_ptr_array_index(histogramNodes, i)) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
virDomainDiskDefDriverParseXML(virDomainDiskDef *def,
xmlNodePtr cur)
@@ -8380,6 +8470,9 @@ virDomainDiskDefDriverParseXML(virDomainDiskDef *def,
return -1;
}
}
+
+ if (virDomainDiskDefDriverParseXMLHistograms(def, statisticsNode) < 0)
+ return -1;
}
if (virXMLPropEnum(cur, "detect_zeroes",
@@ -23961,12 +24054,37 @@ virDomainDiskDefFormatThrottleFilters(virBuffer *buf,
}
+static void
+virDomainDiskDefFormatDriverHistogram(virBuffer *buf,
+ const char *type,
+ unsigned int *bins)
+{
+ g_auto(virBuffer) histogramAttrBuf = VIR_BUFFER_INITIALIZER;
+ g_auto(virBuffer) histogramChildBuf = VIR_BUFFER_INIT_CHILD(buf);
+
+ if (!bins || bins[0] == 0)
+ return;
+
+ if (type)
+ virBufferAsprintf(&histogramAttrBuf, " type='%s'", type);
+
+ /* we dont store the start boundary of the first bin but it's always there */
+ virBufferAddLit(&histogramChildBuf, "<bin start='0'/>\n");
+
+ for (; *bins > 0; bins++)
+ virBufferAsprintf(&histogramChildBuf, "<bin start='%u'/>\n", *bins);
+
+ virXMLFormatElement(buf, "latency-histogram", &histogramAttrBuf, &histogramChildBuf);
+}
+
+
static void
virDomainDiskDefFormatDriver(virBuffer *buf,
virDomainDiskDef *disk)
{
g_auto(virBuffer) attrBuf = VIR_BUFFER_INITIALIZER;
g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf);
+ g_auto(virBuffer) statisticsChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
virBufferEscapeString(&attrBuf, " name='%s'", virDomainDiskGetDriver(disk));
@@ -24038,16 +24156,25 @@ virDomainDiskDefFormatDriver(virBuffer *buf,
virDomainIothreadMappingDefFormat(&childBuf, disk->iothreads);
if (disk->statistics) {
- g_auto(virBuffer) statisticsChildBuf = VIR_BUFFER_INIT_CHILD(&childBuf);
size_t i;
for (i = 0; disk->statistics[i] > 0; i++)
virBufferAsprintf(&statisticsChildBuf, "<statistic interval='%u'/>\n",
disk->statistics[i]);
-
- virXMLFormatElement(&childBuf, "statistics", NULL, &statisticsChildBuf);
}
+ virDomainDiskDefFormatDriverHistogram(&statisticsChildBuf, NULL,
+ disk->histogram_boundaries);
+ virDomainDiskDefFormatDriverHistogram(&statisticsChildBuf, "read",
+ disk->histogram_boundaries_read);
+ virDomainDiskDefFormatDriverHistogram(&statisticsChildBuf, "write",
+ disk->histogram_boundaries_write);
+ virDomainDiskDefFormatDriverHistogram(&statisticsChildBuf, "zone",
+ disk->histogram_boundaries_zone);
+ virDomainDiskDefFormatDriverHistogram(&statisticsChildBuf, "flush",
+ disk->histogram_boundaries_flush);
+
+ virXMLFormatElement(&childBuf, "statistics", NULL, &statisticsChildBuf);
virXMLFormatElement(buf, "driver", &attrBuf, &childBuf);
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8f53ed96c0..b120d4a68e 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -596,6 +596,13 @@ struct _virDomainDiskDef {
GSList *iothreads; /* List of virDomainIothreadMappingDef */
unsigned int *statistics; /* Optional, zero terminated list of intervals to
collect statistics for */
+ /* optional zero terminated lists of bin boundaries for latency histograms */
+ unsigned int *histogram_boundaries;
+ unsigned int *histogram_boundaries_read;
+ unsigned int *histogram_boundaries_write;
+ unsigned int *histogram_boundaries_zone;
+ unsigned int *histogram_boundaries_flush;
+
virDomainDiskDetectZeroes detect_zeroes;
virTristateSwitch discard_no_unref;
char *domain_name; /* backend domain name */
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 1f9ac102a0..441328a08e 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -2728,13 +2728,36 @@
</optional>
<optional>
<element name="statistics">
- <zeroOrMore>
- <element name="statistic">
- <attribute name="interval">
- <ref name="unsignedInt"/>
- </attribute>
- </element>
- </zeroOrMore>
+ <interleave>
+ <zeroOrMore>
+ <element name="statistic">
+ <attribute name="interval">
+ <ref name="unsignedInt"/>
+ </attribute>
+ </element>
+ </zeroOrMore>
+ <zeroOrMore>
+ <element name="latency-histogram">
+ <optional>
+ <attribute name='type'>
+ <choice>
+ <value>read</value>
+ <value>write</value>
+ <value>zone</value>
+ <value>flush</value>
+ </choice>
+ </attribute>
+ </optional>
+ <oneOrMore>
+ <element name='bin'>
+ <attribute name='start'>
+ <ref name="unsignedInt"/>
+ </attribute>
+ </element>
+ </oneOrMore>
+ </element>
+ </zeroOrMore>
+ </interleave>
</element>
</optional>
</interleave>
diff --git a/tests/qemuxmlconfdata/disk-statistics-intervals.x86_64-latest.xml b/tests/qemuxmlconfdata/disk-statistics-intervals.x86_64-latest.xml
index 4c55c50ef5..d02f954073 100644
--- a/tests/qemuxmlconfdata/disk-statistics-intervals.x86_64-latest.xml
+++ b/tests/qemuxmlconfdata/disk-statistics-intervals.x86_64-latest.xml
@@ -22,6 +22,11 @@
<statistics>
<statistic interval='3'/>
<statistic interval='10'/>
+ <latency-histogram>
+ <bin start='0'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
</statistics>
</driver>
<source file='/var/lib/libvirt/images/iothrtest1.img'/>
@@ -33,6 +38,30 @@
<statistics>
<statistic interval='5'/>
<statistic interval='15'/>
+ <latency-histogram type='read'>
+ <bin start='0'/>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='write'>
+ <bin start='0'/>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='zone'>
+ <bin start='0'/>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='flush'>
+ <bin start='0'/>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
</statistics>
</driver>
<source file='/var/lib/libvirt/images/iothrtest2.img'/>
diff --git a/tests/qemuxmlconfdata/disk-statistics-intervals.xml b/tests/qemuxmlconfdata/disk-statistics-intervals.xml
index f5e801f5a8..5f9e9470d7 100644
--- a/tests/qemuxmlconfdata/disk-statistics-intervals.xml
+++ b/tests/qemuxmlconfdata/disk-statistics-intervals.xml
@@ -19,6 +19,11 @@
<statistics>
<statistic interval='3'/>
<statistic interval='10'/>
+ <latency-histogram>
+ <bin start='0'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
</statistics>
</driver>
<source file='/var/lib/libvirt/images/iothrtest1.img'/>
@@ -29,6 +34,26 @@
<statistics>
<statistic interval='5'/>
<statistic interval='15'/>
+ <latency-histogram type='read'>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='write'>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='zone'>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
+ <latency-histogram type='flush'>
+ <bin start='10'/>
+ <bin start='20'/>
+ <bin start='30'/>
+ </latency-histogram>
</statistics>
</driver>
<source file='/var/lib/libvirt/images/iothrtest2.img'/>
--
2.53.0

View File

@ -0,0 +1,125 @@
From c2eb6d70891d9be5ce13f07946841239a81c3ed9 Mon Sep 17 00:00:00 2001
Message-ID: <c2eb6d70891d9be5ce13f07946841239a81c3ed9.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Mon, 16 Feb 2026 15:08:54 +0100
Subject: [PATCH] RHEL-ONLY: backport test data for 'migrate-pr' capability of
'scsi-block'
In upstream qemu the capability is present starting with qemu-11.0. We
don't have the test data downstream and backporting them would be too
invasive. Backport the relevant capability detection as a
downstream-only fix.
https://issues.redhat.com/browse/RHEL-140614 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-135115 [rhel-10.2]
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
---
.../caps_10.2.0_x86_64.replies | 79 ++++++++++++++++++-
.../caps_10.2.0_x86_64.xml | 1 +
2 files changed, 76 insertions(+), 4 deletions(-)
diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.replies b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.replies
index cb4abb4533..10db9baca1 100644
--- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.replies
+++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.replies
@@ -33081,10 +33081,81 @@
}
{
- "error": {
- "class": "DeviceNotFound",
- "desc": "The libvirt device dump was not collected for this version+device tuple"
- },
+ "return": [
+ {
+ "default-value": 4294967295,
+ "name": "scsi-id",
+ "type": "uint32"
+ },
+ {
+ "default-value": 4294967295,
+ "name": "lun",
+ "type": "uint32"
+ },
+ {
+ "default-value": 0,
+ "name": "channel",
+ "type": "uint32"
+ },
+ {
+ "default-value": "auto",
+ "name": "rerror",
+ "description": "Error handling policy (report/ignore/enospc/stop/auto)",
+ "type": "BlockdevOnError"
+ },
+ {
+ "default-value": 2147483647,
+ "name": "max_io_size",
+ "type": "uint64"
+ },
+ {
+ "default-value": false,
+ "name": "share-rw",
+ "description": "on/off",
+ "type": "bool"
+ },
+ {
+ "default-value": true,
+ "name": "migrate-pr",
+ "description": "on/off",
+ "type": "bool"
+ },
+ {
+ "default-value": "auto",
+ "name": "werror",
+ "description": "Error handling policy (report/ignore/enospc/stop/auto)",
+ "type": "BlockdevOnError"
+ },
+ {
+ "default-value": 1073741824,
+ "name": "max_unmap_size",
+ "type": "uint64"
+ },
+ {
+ "default-value": -1,
+ "name": "scsi_version",
+ "type": "int32"
+ },
+ {
+ "default-value": 0,
+ "name": "rotation_rate",
+ "type": "uint16"
+ },
+ {
+ "name": "drive",
+ "description": "Node name or ID of a block device to use as a backend",
+ "type": "str"
+ },
+ {
+ "default-value": 30,
+ "name": "io_timeout",
+ "type": "uint32"
+ },
+ {
+ "name": "bootindex",
+ "type": "int32"
+ }
+ ],
"id": "libvirt-37"
}
diff --git a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
index 7cff2c2291..7d5a75ce88 100644
--- a/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_10.2.0_x86_64.xml
@@ -215,6 +215,7 @@
<flag name='acpi-generic-initiator'/>
<flag name='disk-timed-stats'/>
<flag name='query-accelerators'/>
+ <flag name='scsi-block.migrate-pr'/>
<version>10001091</version>
<microcodeVersion>43100287</microcodeVersion>
<package>v10.2.0-rc1-38-gfb241d0a1f</package>
--
2.53.0

View File

@ -0,0 +1,62 @@
From f6268acd96651ce72014e2ea7ed649caff0b9133 Mon Sep 17 00:00:00 2001
Message-ID: <f6268acd96651ce72014e2ea7ed649caff0b9133.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 30 Jan 2026 17:47:46 +0100
Subject: [PATCH] docs: formatdomain: Fix indentation of docs for
<disk><driver><statistics> element
All other paragraphs in this section use 2 spaces after hyphen, fix the
recently added section.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 7da1a83914ca10cc811583d7310bf60e04b70488)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
docs/formatdomain.rst | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 9836837441..45f262113b 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -3605,22 +3605,22 @@ paravirtualized driver is specified via the ``disk`` element.
</iothreads>
</driver>
- - The optional ``statistics`` sub-element allows configuring statistics
- collection in configurable intervals for the given disk. Intervals are
- configured by ``<statistic>`` sub-elements with ``interval`` attribute
- configuring the collection window duration in seconds. The statistics
- are available via the bulk statistics API.
+ - The optional ``statistics`` sub-element allows configuring statistics
+ collection in configurable intervals for the given disk. Intervals are
+ configured by ``<statistic>`` sub-elements with ``interval`` attribute
+ configuring the collection window duration in seconds. The statistics
+ are available via the bulk statistics API.
- Example::
+ Example::
- <driver name='qemu'>
- <statistics>
- <statistic interval='1'/>
- <statistic interval='10'/>
- </statistics>
- </driver>
+ <driver name='qemu'>
+ <statistics>
+ <statistic interval='1'/>
+ <statistic interval='10'/>
+ </statistics>
+ </driver>
- :since:`Since 11.9.0 (QEMU 10.2, virtio, ide, scsi disks only)`.
+ :since:`Since 11.9.0 (QEMU 10.2, virtio, ide, scsi disks only)`.
- The optional ``queues`` attribute specifies the number of virt queues for
virtio-blk ( :since:`Since 3.9.0` ) or vhost-user-blk
--
2.53.0

View File

@ -0,0 +1,51 @@
From ea6f8a96929577416a5cc4f4452f920312aef081 Mon Sep 17 00:00:00 2001
Message-ID: <ea6f8a96929577416a5cc4f4452f920312aef081.1771336682.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 30 Jan 2026 17:37:48 +0100
Subject: [PATCH] docs: formatdomain: Reword section about the '<statistics>'
element under disk driver
Separate the timed statistics group and link to the fields which are
returned by it.
Prepare the wording for more statistics configs in the future.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit ad65b00c1393f7f13e15744e2e1be4fb531e2a17)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
docs/formatdomain.rst | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 45f262113b..70882c6820 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -3605,11 +3605,17 @@ paravirtualized driver is specified via the ``disk`` element.
</iothreads>
</driver>
- - The optional ``statistics`` sub-element allows configuring statistics
- collection in configurable intervals for the given disk. Intervals are
- configured by ``<statistic>`` sub-elements with ``interval`` attribute
- configuring the collection window duration in seconds. The statistics
- are available via the bulk statistics API.
+ - The optional ``statistics`` sub-element allows configuring various optional
+ statistics collection.
+
+ Statistic values returned under
+ `VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX <html/libvirt-libvirt-domain.html#VIR_DOMAIN_STATS_BLOCK_SUFFIX_TIMED_GROUP_PREFIX>`__
+ typed parameter prefix returned by the
+ `virConnectGetAllDomainStats <html/libvirt-libvirt-domain.html#virConnectGetAllDomainStats>`__
+ API are collected based on one or more configurable intervals. An interval
+ of collection is configured by ``<statistic>`` sub-elements with
+ ``interval`` attribute configuring the collection window duration in
+ seconds.
Example::
--
2.53.0

View File

@ -0,0 +1,144 @@
From 92a7fef67b736e20c8e94f3407df7a984ee59102 Mon Sep 17 00:00:00 2001
Message-ID: <92a7fef67b736e20c8e94f3407df7a984ee59102.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 29 Jan 2026 11:15:04 +0100
Subject: [PATCH] qemu: Extract disk setup done via QMP into a separate helper
Introduce 'qemuProcessSetupDiskPropsRuntime' helper function which will
collect all code used for runtime setup of a disk.
This is currently old-style throttling.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 1789a0f8a3623e8f0f6e50730feb58e3d8c48376)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
Conflicts:
- Commit b9b9092c9c1f8b42e311c524d9fc4a8e73ae28a6 which dropped disk
property refresh was not backported, thus the context around the call
to qemuProcessSetupDiskPropsRuntime was different
---
src/qemu/qemu_hotplug.c | 23 +++++------------------
src/qemu/qemu_process.c | 37 +++++++++++++++++++++++++++----------
src/qemu/qemu_process.h | 3 +++
3 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index fb426deb1a..f2dc4469a3 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -569,13 +569,8 @@ qemuDomainChangeMediaBlockdev(virDomainObj *vm,
}
/* set throttling for the new image */
- if (rc == 0 &&
- !virStorageSourceIsEmpty(newsrc) &&
- qemuDiskConfigBlkdeviotuneEnabled(disk)) {
- rc = qemuMonitorSetBlockIoThrottle(priv->mon,
- diskPriv->qomName,
- &disk->blkdeviotune);
- }
+ if (rc == 0)
+ rc = qemuProcessSetupDiskPropsRuntime(priv->mon, disk);
if (rc == 0)
rc = qemuMonitorBlockdevTrayClose(priv->mon, diskPriv->qomName);
@@ -795,21 +790,13 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm,
if (rc == 0)
rc = qemuMonitorAddDeviceProps(priv->mon, &devprops);
- /* Setup throttling of disk via block_set_io_throttle QMP command. This
- * is a hack until the 'throttle' blockdev driver will support modification
- * of the trhottle group. See also qemuProcessSetupDiskThrottlingBlockdev.
- * As there isn't anything sane to do if this fails, let's just return
- * success.
- */
if (rc == 0) {
qemuDomainDiskPrivate *diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk);
g_autoptr(GHashTable) blockinfo = NULL;
- if (qemuDiskConfigBlkdeviotuneEnabled(disk)) {
- if (qemuMonitorSetBlockIoThrottle(priv->mon, diskPriv->qomName,
- &disk->blkdeviotune) < 0)
- VIR_WARN("failed to set blkdeviotune for '%s' of '%s'", disk->dst, vm->def->name);
- }
+ /* There isn't anything sane to do if this fails (rollback would
+ * require hot-unplug), let's just return success. */
+ ignore_value(qemuProcessSetupDiskPropsRuntime(priv->mon, disk));
if ((blockinfo = qemuMonitorGetBlockInfo(priv->mon))) {
struct qemuDomainDiskInfo *diskinfo;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index d8f0c78fd1..c99bb36c93 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7937,6 +7937,32 @@ qemuProcessGenID(virDomainObj *vm,
}
+/**
+ * qemuProcessSetupDiskPropsRuntime:
+ * @mon: qemu monitor object
+ * @disk: disk definition
+ *
+ * This function expects that caller already entered 'monitor' context.
+ *
+ * Sets up disk properties which are only possible to be set in runtime.
+ */
+int
+qemuProcessSetupDiskPropsRuntime(qemuMonitor *mon,
+ virDomainDiskDef *disk)
+{
+ if (virStorageSourceIsEmpty(disk->src))
+ return 0;
+
+ if (qemuDiskConfigBlkdeviotuneEnabled(disk) &&
+ qemuMonitorSetBlockIoThrottle(mon,
+ QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName,
+ &disk->blkdeviotune) < 0)
+ return -1;
+
+ return 0;
+}
+
+
/**
* qemuProcessSetupDiskThrottling:
*
@@ -7960,16 +7986,7 @@ qemuProcessSetupDiskThrottling(virDomainObj *vm,
for (i = 0; i < vm->def->ndisks; i++) {
virDomainDiskDef *disk = vm->def->disks[i];
- /* Setting throttling for empty drives fails */
- if (virStorageSourceIsEmpty(disk->src))
- continue;
-
- if (!qemuDiskConfigBlkdeviotuneEnabled(disk))
- continue;
-
- if (qemuMonitorSetBlockIoThrottle(qemuDomainGetMonitor(vm),
- QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName,
- &disk->blkdeviotune) < 0)
+ if (qemuProcessSetupDiskPropsRuntime(qemuDomainGetMonitor(vm), disk) < 0)
goto cleanup;
}
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index 426e11d79e..df78b00abb 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -146,6 +146,9 @@ int qemuProcessPrepareHostStorageSourceChain(virDomainObj *vm,
int qemuProcessPrepareHostStorageDisk(virDomainObj *vm,
virDomainDiskDef *disk);
+int qemuProcessSetupDiskPropsRuntime(qemuMonitor *mon,
+ virDomainDiskDef *disk);
+
int qemuProcessDeleteThreadContext(virDomainObj *vm);
int qemuProcessLaunch(virConnectPtr conn,
--
2.53.0

View File

@ -0,0 +1,220 @@
From 3f03b1cbc20d0af7900cc43cc576a356a95a292b Mon Sep 17 00:00:00 2001
Message-ID: <3f03b1cbc20d0af7900cc43cc576a356a95a292b.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 11 Dec 2025 19:47:16 +0100
Subject: [PATCH] qemu: Implement support for persistent reservation migration
control
The 'migration' attribute for the '<reservations>' element allows to
control the persistent reservation migration feature independently of
the machine type default.
Add the XML plumbing and qemu support.
We consider it ABI for now since it influences qemu migration protocol.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 0d3ef7cb71979172de2c531d865e4525a314f902)
https://issues.redhat.com/browse/RHEL-140614 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-135115 [rhel-10.2]
---
docs/formatdomain.rst | 3 +++
src/conf/domain_conf.c | 21 +++++++++++++++++++
src/conf/schemas/storagecommon.rng | 5 +++++
src/conf/storage_source_conf.c | 10 +++++++++
src/conf/storage_source_conf.h | 2 ++
src/qemu/qemu_command.c | 4 ++++
src/qemu/qemu_validate.c | 16 ++++++++++++++
...irtio-scsi-reservations.x86_64-latest.args | 2 +-
.../disk-virtio-scsi-reservations.xml | 2 +-
9 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 167912348e..9836837441 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -3169,6 +3169,9 @@ paravirtualized driver is specified via the ``disk`` element.
the socket, and finally ``mode`` which accepts one value ``client``
specifying the role of hypervisor. It's recommended to allow libvirt
manage the persistent reservations.
+ :since:`Since 12.1.0` the ``migration`` (values ``yes``, ``no``) controls
+ whether the hypervisor should attempt to migrate persistent reservations
+ during migration.
``initiator``
:since:`Since 4.7.0`, the ``initiator`` element is supported for
a disk ``type`` "network" that is using a ``source`` element with the
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 902c1188ef..f5c4d135a9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -20951,6 +20951,27 @@ virDomainDiskDefCheckABIStability(virDomainDiskDef *src,
return false;
}
+ /* While not guest visible it influences the qemu migration stream so
+ * we need to keep it identical */
+ if (src->src->pr || dst->src->pr) {
+ virTristateBool srcmig = VIR_TRISTATE_BOOL_ABSENT;
+ virTristateBool dstmig = VIR_TRISTATE_BOOL_ABSENT;
+
+ if (src->src->pr)
+ srcmig = src->src->pr->migration;
+
+ if (dst->src->pr)
+ dstmig = dst->src->pr->migration;
+
+ if (srcmig != dstmig) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Target disk reservations 'migration' property %1$s does not match source %2$s"),
+ virTristateBoolTypeToString(dstmig),
+ virTristateBoolTypeToString(srcmig));
+ return false;
+ }
+ }
+
if (!virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
return false;
diff --git a/src/conf/schemas/storagecommon.rng b/src/conf/schemas/storagecommon.rng
index 14704c737e..450d53131f 100644
--- a/src/conf/schemas/storagecommon.rng
+++ b/src/conf/schemas/storagecommon.rng
@@ -104,6 +104,11 @@
<ref name="virYesNo"/>
</attribute>
</optional>
+ <optional>
+ <attribute name="migration">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
<optional>
<ref name="unixSocketSource"/>
</optional>
diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c
index 087de1eaf2..24d4b0de6a 100644
--- a/src/conf/storage_source_conf.c
+++ b/src/conf/storage_source_conf.c
@@ -330,6 +330,11 @@ virStoragePRDefParseXML(xmlXPathContextPtr ctxt)
&prd->managed) < 0)
goto cleanup;
+ if (virXMLPropTristateBool(ctxt->node, "migration",
+ VIR_XML_PROP_NONZERO,
+ &prd->migration) < 0)
+ goto cleanup;
+
type = virXPathString("string(./source[1]/@type)", ctxt);
path = virXPathString("string(./source[1]/@path)", ctxt);
mode = virXPathString("string(./source[1]/@mode)", ctxt);
@@ -384,6 +389,11 @@ virStoragePRDefFormat(virBuffer *buf,
{
virBufferAsprintf(buf, "<reservations managed='%s'",
virTristateBoolTypeToString(prd->managed));
+
+ if (prd->migration != VIR_TRISTATE_BOOL_ABSENT)
+ virBufferAsprintf(buf, " migration='%s'",
+ virTristateBoolTypeToString(prd->migration));
+
if (prd->path &&
(prd->managed == VIR_TRISTATE_BOOL_NO || !migratable)) {
virBufferAddLit(buf, ">\n");
diff --git a/src/conf/storage_source_conf.h b/src/conf/storage_source_conf.h
index fc868b31af..5a4b088eeb 100644
--- a/src/conf/storage_source_conf.h
+++ b/src/conf/storage_source_conf.h
@@ -235,6 +235,8 @@ struct _virStoragePRDef {
virTristateBool managed;
char *path;
+ virTristateBool migration;
+
/* manager object alias */
char *mgralias;
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index f355352018..c8626e6d49 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1691,6 +1691,7 @@ qemuBuildDiskDeviceProps(const virDomainDef *def,
g_autofree char *usbdiskalias = NULL;
const virDomainDeviceInfo *deviceinfo = &disk->info;
g_autoptr(virJSONValue) statistics = NULL;
+ virTristateBool migrate_pr = VIR_TRISTATE_BOOL_ABSENT;
virDomainDeviceInfo usbSCSIinfo = {
.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE,
.addr.drive = { .diskbus = VIR_DOMAIN_DISK_BUS_USB },
@@ -1716,6 +1717,8 @@ qemuBuildDiskDeviceProps(const virDomainDef *def,
case VIR_DOMAIN_DISK_BUS_SCSI:
if (disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
driver = "scsi-block";
+ if (disk->src->pr)
+ migrate_pr = disk->src->pr->migration;
} else {
if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) {
driver = "scsi-cd";
@@ -1937,6 +1940,7 @@ qemuBuildDiskDeviceProps(const virDomainDef *def,
"S:rerror", rpolicy,
"A:stats-intervals", &statistics,
"T:dpofua", disk->dpofua, /* SCSI-only, ensured by validation */
+ "T:migrate-pr", migrate_pr, /* 'scsi-block' only, ensured by validation */
NULL) < 0)
return NULL;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index da08fd17cd..a3dbd9a33b 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -3227,6 +3227,22 @@ qemuValidateDomainDeviceDefDiskFrontend(const virDomainDiskDef *disk,
}
}
+ if (disk->src->pr &&
+ disk->src->pr->migration != VIR_TRISTATE_BOOL_ABSENT) {
+ if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN ||
+ disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("persistent reservation migration supported only with 'lun' disks on 'scsi' bus"));
+ return -1;
+ }
+
+ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("persistent reservation migration not supported by this qemu"));
+ return -1;
+ }
+ }
+
if (disk->rotation_rate) {
if (disk->bus != VIR_DOMAIN_DISK_BUS_SCSI &&
disk->bus != VIR_DOMAIN_DISK_BUS_IDE &&
diff --git a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-latest.args b/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-latest.args
index cbc2a0f398..f1d7a450ee 100644
--- a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-latest.args
+++ b/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.x86_64-latest.args
@@ -33,7 +33,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
-device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"lun":0,"drive":"libvirt-2-storage","id":"scsi0-0-0-0","bootindex":1}' \
-object '{"qom-type":"pr-manager-helper","id":"pr-helper-libvirt-1-storage","path":"/path/to/qemu-pr-helper.sock"}' \
-blockdev '{"driver":"host_device","filename":"/dev/HostVG/QEMUGuest2","pr-manager":"pr-helper-libvirt-1-storage","node-name":"libvirt-1-storage","read-only":false}' \
--device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"lun":1,"drive":"libvirt-1-storage","id":"scsi0-0-0-1"}' \
+-device '{"driver":"scsi-block","bus":"scsi0.0","channel":0,"scsi-id":0,"lun":1,"drive":"libvirt-1-storage","id":"scsi0-0-0-1","migrate-pr":true}' \
-audiodev '{"id":"audio1","driver":"none"}' \
-device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x4"}' \
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
diff --git a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.xml b/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.xml
index 9c55d6ec3e..7f9160ff3a 100644
--- a/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.xml
+++ b/tests/qemuxmlconfdata/disk-virtio-scsi-reservations.xml
@@ -28,7 +28,7 @@
<disk type='block' device='lun'>
<driver name='qemu' type='raw'/>
<source dev='/dev/HostVG/QEMUGuest2'>
- <reservations managed='no'>
+ <reservations managed='no' migration='yes'>
<source type='unix' path='/path/to/qemu-pr-helper.sock' mode='client'/>
</reservations>
</source>
--
2.53.0

View File

@ -0,0 +1,132 @@
From f496b6095bf96eb8931b78054a272a5aaf70a2d9 Mon Sep 17 00:00:00 2001
Message-ID: <f496b6095bf96eb8931b78054a272a5aaf70a2d9.1771336682.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 23 Jan 2026 17:18:14 +0100
Subject: [PATCH] qemu: Setup disk latency histograms on startup/hotplug/update
Setup the histograms on startup and hotplug of devices via
'qemuProcessSetupDiskPropsRuntime' and facilitate update/reset/disable
of histogram collection via 'qemuDomainChangeDiskLive'.
The latter allows to use the update device API to either clear the bins
or select new bin configuration or disable the histogram altogether
without the need for a specific API.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 5787326541be4eafaa7ae3b4f866b3da793d44fe)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
src/qemu/qemu_domain.c | 17 +++++++++++++++++
src/qemu/qemu_domain.h | 3 +++
src/qemu/qemu_hotplug.c | 29 +++++++++++++++++++++++++++++
src/qemu/qemu_process.c | 10 ++++++++++
4 files changed, 59 insertions(+)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 8e1ebe7799..bdab117e96 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -10463,6 +10463,23 @@ qemuDomainInitializePflashStorageSource(virDomainObj *vm,
}
+/**
+ * qemuDomainDiskHasLatencyHistogram:
+ * @disk: disk definition
+ *
+ * Returns whether @disk has any latency histogram settings configured.
+ */
+bool
+qemuDomainDiskHasLatencyHistogram(virDomainDiskDef *disk)
+{
+ return disk->histogram_boundaries ||
+ disk->histogram_boundaries_read ||
+ disk->histogram_boundaries_write ||
+ disk->histogram_boundaries_zone ||
+ disk->histogram_boundaries_flush;
+}
+
+
/**
* qemuDomainDiskBlockJobIsSupported:
*
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 3361e97315..30ca67bf76 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -1078,6 +1078,9 @@ int
qemuDomainInitializePflashStorageSource(virDomainObj *vm,
virQEMUDriverConfig *cfg);
+bool
+qemuDomainDiskHasLatencyHistogram(virDomainDiskDef *disk);
+
bool
qemuDomainDiskBlockJobIsSupported(virDomainDiskDef *disk);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index f2dc4469a3..9445599d2c 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -7310,6 +7310,35 @@ qemuDomainChangeDiskLive(virDomainObj *vm,
dev->data.disk->src = NULL;
}
+ if (qemuDomainDiskHasLatencyHistogram(disk) ||
+ qemuDomainDiskHasLatencyHistogram(orig_disk)) {
+ int rc;
+
+ qemuDomainObjEnterMonitor(vm);
+ rc = qemuMonitorBlockLatencyHistogramSet(qemuDomainGetMonitor(vm),
+ QEMU_DOMAIN_DISK_PRIVATE(orig_disk)->qomName,
+ disk->histogram_boundaries,
+ disk->histogram_boundaries_read,
+ disk->histogram_boundaries_write,
+ disk->histogram_boundaries_zone,
+ disk->histogram_boundaries_flush);
+ qemuDomainObjExitMonitor(vm);
+
+ if (rc < 0)
+ return -1;
+
+ g_clear_pointer(&orig_disk->histogram_boundaries, g_free);
+ g_clear_pointer(&orig_disk->histogram_boundaries_read, g_free);
+ g_clear_pointer(&orig_disk->histogram_boundaries_write, g_free);
+ g_clear_pointer(&orig_disk->histogram_boundaries_zone, g_free);
+ g_clear_pointer(&orig_disk->histogram_boundaries_flush, g_free);
+ orig_disk->histogram_boundaries = g_steal_pointer(&disk->histogram_boundaries);
+ orig_disk->histogram_boundaries_read = g_steal_pointer(&disk->histogram_boundaries_read);
+ orig_disk->histogram_boundaries_write = g_steal_pointer(&disk->histogram_boundaries_write);
+ orig_disk->histogram_boundaries_zone = g_steal_pointer(&disk->histogram_boundaries_zone);
+ orig_disk->histogram_boundaries_flush = g_steal_pointer(&disk->histogram_boundaries_flush);
+ }
+
/* in case when we aren't updating disk source we update startup policy here */
orig_disk->startupPolicy = dev->data.disk->startupPolicy;
orig_disk->snapshot = dev->data.disk->snapshot;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index aadfaa92b0..37e688018c 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7959,6 +7959,16 @@ qemuProcessSetupDiskPropsRuntime(qemuMonitor *mon,
&disk->blkdeviotune) < 0)
return -1;
+ if (qemuDomainDiskHasLatencyHistogram(disk) &&
+ qemuMonitorBlockLatencyHistogramSet(mon,
+ QEMU_DOMAIN_DISK_PRIVATE(disk)->qomName,
+ disk->histogram_boundaries,
+ disk->histogram_boundaries_read,
+ disk->histogram_boundaries_write,
+ disk->histogram_boundaries_zone,
+ disk->histogram_boundaries_flush) < 0)
+ return -1;
+
return 0;
}
--
2.53.0

View File

@ -0,0 +1,58 @@
From 2674cc2e58f98439fe72e4d832e6e2e9b41a614f Mon Sep 17 00:00:00 2001
Message-ID: <2674cc2e58f98439fe72e4d832e6e2e9b41a614f.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 11 Dec 2025 19:26:40 +0100
Subject: [PATCH] qemu: capabilities: Introduce
QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR
Introduce capability for persisten migration control support.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit b0edb7eb9b819e0560bb7d65b4e0c89082b3b43b)
https://issues.redhat.com/browse/RHEL-140614 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-135115 [rhel-10.2]
Conflicts:
- Commit befdd44bf836c3ba46e46d57b587127e12736591 adding
QEMU_CAPS_VIRTIO_IOMMU_AW_BITS was not backported
---
src/qemu/qemu_capabilities.c | 2 ++
src/qemu/qemu_capabilities.h | 1 +
2 files changed, 3 insertions(+)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 1efb77d03b..2c8bd62c99 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -755,6 +755,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
"disk-timed-stats", /* QEMU_CAPS_DISK_TIMED_STATS */
"query-accelerators", /* QEMU_CAPS_QUERY_ACCELERATORS */
"mshv", /* QEMU_CAPS_MSHV */
+ "scsi-block.migrate-pr", /* QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR */
);
@@ -1536,6 +1537,7 @@ static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsSCSIDisk[] = {
};
static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsSCSIBlock[] = {
+ { "migrate-pr", QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR, NULL },
};
static struct virQEMUCapsDevicePropsFlags virQEMUCapsDevicePropsSCSIGeneric[] = {
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index f180844e66..0c76f2edda 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -730,6 +730,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
QEMU_CAPS_DISK_TIMED_STATS, /* timed stats support ('stats-intervals' property of disk frontends) */
QEMU_CAPS_QUERY_ACCELERATORS, /* query-accelerators command */
QEMU_CAPS_MSHV, /* -accel mshv */
+ QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR, /* persistent reservation migration support */
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
--
2.53.0

View File

@ -0,0 +1,182 @@
From 99b1b6fda9b4e098a7bbbbb44e02064c57bff558 Mon Sep 17 00:00:00 2001
Message-ID: <99b1b6fda9b4e098a7bbbbb44e02064c57bff558.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 11 Dec 2025 18:38:12 +0100
Subject: [PATCH] qemu: monitor: Add handlers for 'block-latency-histogram-set'
Add QMP monitor code for setting up latency histogram configuration.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit ad4830ce6844b75800685ea85b15a53b8dbc5ac6)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
src/qemu/qemu_monitor.c | 21 +++++++++++++
src/qemu/qemu_monitor.h | 9 ++++++
src/qemu/qemu_monitor_json.c | 60 ++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 9 ++++++
tests/qemumonitorjsontest.c | 9 ++++++
5 files changed, 108 insertions(+)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index cdd08004fb..3d7477c01c 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4612,3 +4612,24 @@ qemuMonitorBlockdevSetActive(qemuMonitor *mon,
return qemuMonitorJSONBlockdevSetActive(mon, nodename, active);
}
+
+
+int
+qemuMonitorBlockLatencyHistogramSet(qemuMonitor *mon,
+ const char *id,
+ unsigned int *boundaries,
+ unsigned int *boundaries_read,
+ unsigned int *boundaries_write,
+ unsigned int *boundaries_zone,
+ unsigned int *boundaries_flush)
+{
+ QEMU_CHECK_MONITOR(mon);
+ VIR_DEBUG("id='%s'", id);
+
+ return qemuMonitorJSONBlockLatencyHistogramSet(mon, id,
+ boundaries,
+ boundaries_read,
+ boundaries_write,
+ boundaries_zone,
+ boundaries_flush);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 238f7be875..bbe400003a 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1988,3 +1988,12 @@ int
qemuMonitorBlockdevSetActive(qemuMonitor *mon,
const char *nodename,
bool active);
+
+int
+qemuMonitorBlockLatencyHistogramSet(qemuMonitor *mon,
+ const char *id,
+ unsigned int *boundaries,
+ unsigned int *boundaries_read,
+ unsigned int *boundaries_write,
+ unsigned int *boundaries_zone,
+ unsigned int *boundaries_flush);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index edeea22ee0..45f690d9e2 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -9130,3 +9130,63 @@ qemuMonitorJSONBlockdevSetActive(qemuMonitor *mon,
return qemuMonitorJSONCheckError(cmd, reply);
}
+
+
+static virJSONValue *
+qemuMonitorJSONBlockLatencyHistogramBoundary(unsigned int *bound)
+{
+ g_autoptr(virJSONValue) ret = virJSONValueNewArray();
+
+ if (!bound)
+ return NULL;
+
+ for (; *bound > 0; bound++) {
+ g_autoptr(virJSONValue) val = virJSONValueNewNumberUint(*bound);
+
+ /* the only error is if the first argument is not an array */
+ ignore_value(virJSONValueArrayAppend(ret, &val));
+ }
+
+ return g_steal_pointer(&ret);
+}
+
+
+int
+qemuMonitorJSONBlockLatencyHistogramSet(qemuMonitor *mon,
+ const char *id,
+ unsigned int *boundaries,
+ unsigned int *boundaries_read,
+ unsigned int *boundaries_write,
+ unsigned int *boundaries_zone,
+ unsigned int *boundaries_flush)
+{
+ g_autoptr(virJSONValue) cmd = NULL;
+ g_autoptr(virJSONValue) reply = NULL;
+
+ g_autoptr(virJSONValue) bound = NULL;
+ g_autoptr(virJSONValue) bound_read = NULL;
+ g_autoptr(virJSONValue) bound_write = NULL;
+ g_autoptr(virJSONValue) bound_zone = NULL;
+ g_autoptr(virJSONValue) bound_flush = NULL;
+
+ bound = qemuMonitorJSONBlockLatencyHistogramBoundary(boundaries);
+ bound_read = qemuMonitorJSONBlockLatencyHistogramBoundary(boundaries_read);
+ bound_write = qemuMonitorJSONBlockLatencyHistogramBoundary(boundaries_write);
+ bound_zone = qemuMonitorJSONBlockLatencyHistogramBoundary(boundaries_zone);
+ bound_flush = qemuMonitorJSONBlockLatencyHistogramBoundary(boundaries_flush);
+
+ if (!(cmd = qemuMonitorJSONMakeCommand("block-latency-histogram-set",
+ "s:id", id,
+ "A:boundaries", &bound,
+ "A:boundaries-read", &bound_read,
+ "A:boundaries-write", &bound_write,
+ "A:boundaries-zap", &bound_zone,
+ "A:boundaries-flush", &bound_flush,
+ NULL)))
+ return -1;
+
+ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+ return -1;
+
+ return qemuMonitorJSONCheckError(cmd, reply);
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index db9160eb68..b418f70048 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -815,3 +815,12 @@ int
qemuMonitorJSONBlockdevSetActive(qemuMonitor *mon,
const char *nodename,
bool active);
+
+int
+qemuMonitorJSONBlockLatencyHistogramSet(qemuMonitor *mon,
+ const char *id,
+ unsigned int *boundaries,
+ unsigned int *boundaries_read,
+ unsigned int *boundaries_write,
+ unsigned int *boundaries_zone,
+ unsigned int *boundaries_flush);
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index bfe81739a7..1c1aaaa586 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -1130,6 +1130,14 @@ GEN_TEST_FUNC(qemuMonitorJSONSetAction,
GEN_TEST_FUNC(qemuMonitorJSONSetLaunchSecurityState, "sev_secret_header",
"sev_secret", 0, true)
+unsigned int testHistogramBoundaries[] = {10, 30, 50, 0};
+GEN_TEST_FUNC(qemuMonitorJSONBlockLatencyHistogramSet, "devid",
+ testHistogramBoundaries,
+ testHistogramBoundaries,
+ testHistogramBoundaries,
+ testHistogramBoundaries,
+ testHistogramBoundaries)
+
static int
testQemuMonitorJSONqemuMonitorJSONNBDServerStart(const void *opaque)
{
@@ -2958,6 +2966,7 @@ mymain(void)
DO_TEST_GEN(qemuMonitorJSONBlockJobCancel);
DO_TEST_GEN(qemuMonitorJSONSetAction);
DO_TEST_GEN(qemuMonitorJSONSetLaunchSecurityState);
+ DO_TEST_GEN(qemuMonitorJSONBlockLatencyHistogramSet);
DO_TEST(qemuMonitorJSONGetBalloonInfo);
DO_TEST(qemuMonitorJSONGetBlockInfo);
DO_TEST(qemuMonitorJSONGetAllBlockStatsInfo);
--
2.53.0

View File

@ -0,0 +1,168 @@
From e02f5e7ca63bdaaec62c2fffa681b9354bee0792 Mon Sep 17 00:00:00 2001
Message-ID: <e02f5e7ca63bdaaec62c2fffa681b9354bee0792.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 29 Jan 2026 14:08:18 +0100
Subject: [PATCH] qemu: monitor: Extract block latency histogram stats into
'qemuBlockStats'
Extract the 'rd_latency_histogram', 'wr_latency_histogram',
'zone_append_latency_histogram', and 'flush_latency_histogram' stats
objects into our internal data.
Rather than storing 'boundaries' between bins we store them as start
points.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 1c77d396ea9704eae09d7fea160cfd1a897beaf3)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
src/qemu/qemu_monitor.c | 20 +++++++++++++
src/qemu/qemu_monitor.h | 18 ++++++++++++
src/qemu/qemu_monitor_json.c | 55 ++++++++++++++++++++++++++++++++++++
3 files changed, 93 insertions(+)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 504500c864..cdd08004fb 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1986,6 +1986,26 @@ qemuBlockStatsFinalize(GObject *object)
g_free(stats->limits);
g_free(stats->timed_stats);
+ if (stats->histogram_read) {
+ g_free(stats->histogram_read->bins);
+ g_free(stats->histogram_read);
+ }
+
+ if (stats->histogram_write) {
+ g_free(stats->histogram_write->bins);
+ g_free(stats->histogram_write);
+ }
+
+ if (stats->histogram_zone) {
+ g_free(stats->histogram_zone->bins);
+ g_free(stats->histogram_zone);
+ }
+
+ if (stats->histogram_flush) {
+ g_free(stats->histogram_flush->bins);
+ g_free(stats->histogram_flush);
+ }
+
G_OBJECT_CLASS(qemu_block_stats_parent_class)->finalize(object);
}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 041aa7bc12..238f7be875 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -806,6 +806,18 @@ struct qemuBlockStatsLimits {
};
+struct qemuBlockStatsLatencyHistogramBin {
+ unsigned long long start;
+ unsigned long long value;
+};
+
+
+struct qemuBlockStatsLatencyHistogram {
+ struct qemuBlockStatsLatencyHistogramBin *bins;
+ size_t nbins;
+};
+
+
struct qemuBlockStatsTimed {
unsigned long long interval_length;
@@ -858,6 +870,12 @@ struct _qemuBlockStats {
/* block accounting/timed stats from qemu - one entry per interval configured */
size_t n_timed_stats;
struct qemuBlockStatsTimed *timed_stats;
+
+ /* latency histograms */
+ struct qemuBlockStatsLatencyHistogram *histogram_read;
+ struct qemuBlockStatsLatencyHistogram *histogram_write;
+ struct qemuBlockStatsLatencyHistogram *histogram_zone;
+ struct qemuBlockStatsLatencyHistogram *histogram_flush;
};
G_DECLARE_FINAL_TYPE(qemuBlockStats, qemu_block_stats, QEMU, BLOCK_STATS, GObject);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 401a28ff9a..edeea22ee0 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2425,6 +2425,52 @@ qemuMonitorJSONBlockStatsCollectDataTimed(virJSONValue *timed_stats,
}
+static void
+qemuMonitorJSONBlockStatsCollectDataLatencyHistogram(virJSONValue *stats,
+ const char *histogram_field,
+ struct qemuBlockStatsLatencyHistogram **histogram_data)
+{
+ virJSONValue *hist;
+ virJSONValue *hist_bins;
+ virJSONValue *hist_bounds;
+ g_autofree struct qemuBlockStatsLatencyHistogramBin *bins = NULL;
+ size_t nbins = 0;
+ size_t i;
+
+ if (!(hist = virJSONValueObjectGetObject(stats, histogram_field)))
+ return;
+
+ if (!(hist_bins = virJSONValueObjectGetArray(hist, "bins")) ||
+ !(hist_bounds = virJSONValueObjectGetArray(hist, "boundaries")) ||
+ virJSONValueArraySize(hist_bins) != (virJSONValueArraySize(hist_bounds) + 1)) {
+ VIR_DEBUG("malformed latency histogram container");
+ return;
+ }
+
+ nbins = virJSONValueArraySize(hist_bins);
+ bins = g_new0(struct qemuBlockStatsLatencyHistogramBin, nbins);
+
+ for (i = 0; i < nbins; i++) {
+ virJSONValue *bin = virJSONValueArrayGet(hist_bins, i);
+ virJSONValue *bound = NULL;
+
+ if (i > 0)
+ bound = virJSONValueArrayGet(hist_bounds, i - 1);
+
+ if (!bin ||
+ virJSONValueGetNumberUlong(bin, &(bins[i].value)) < 0 ||
+ (bound && virJSONValueGetNumberUlong(bound, &(bins[i].start)) < 0)) {
+ VIR_DEBUG("malformed latency histogram container");
+ return;
+ }
+ }
+
+ *histogram_data = g_new0(struct qemuBlockStatsLatencyHistogram, 1);
+ (*histogram_data)->bins = g_steal_pointer(&bins);
+ (*histogram_data)->nbins = nbins;
+}
+
+
static qemuBlockStats *
qemuMonitorJSONBlockStatsCollectData(virJSONValue *dev,
int *nstats)
@@ -2469,6 +2515,15 @@ qemuMonitorJSONBlockStatsCollectData(virJSONValue *dev,
bstats->wr_highest_offset_valid = true;
}
+ qemuMonitorJSONBlockStatsCollectDataLatencyHistogram(stats, "rd_latency_histogram",
+ &bstats->histogram_read);
+ qemuMonitorJSONBlockStatsCollectDataLatencyHistogram(stats, "wr_latency_histogram",
+ &bstats->histogram_write);
+ qemuMonitorJSONBlockStatsCollectDataLatencyHistogram(stats, "zone_append_latency_histogram",
+ &bstats->histogram_zone);
+ qemuMonitorJSONBlockStatsCollectDataLatencyHistogram(stats, "flush_latency_histogram",
+ &bstats->histogram_flush);
+
if ((timed_stats = virJSONValueObjectGetArray(stats, "timed_stats")) &&
virJSONValueArraySize(timed_stats) > 0)
qemuMonitorJSONBlockStatsCollectDataTimed(timed_stats, bstats);
--
2.53.0

View File

@ -0,0 +1,62 @@
From 0359b5fcf870f955bbdca998e5a02261e27c40b7 Mon Sep 17 00:00:00 2001
Message-ID: <0359b5fcf870f955bbdca998e5a02261e27c40b7.1771336681.git.jdenemar@redhat.com>
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 29 Jan 2026 11:21:38 +0100
Subject: [PATCH] qemu: process: Rename 'qemuProcessSetupDiskThrottling' to
'qemuProcessSetupDisks'
Rename the runtime disk option setup function to be universal.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit 42a39d703d98e4e48f0f9c8779884b6ac107de26)
https://issues.redhat.com/browse/RHEL-147866 [rhel-9.8]
https://issues.redhat.com/browse/RHEL-131335 [rhel-10.2]
---
src/qemu/qemu_process.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index c99bb36c93..aadfaa92b0 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -7964,21 +7964,19 @@ qemuProcessSetupDiskPropsRuntime(qemuMonitor *mon,
/**
- * qemuProcessSetupDiskThrottling:
+ * qemuProcessSetupDisks:
*
- * Sets up disk trottling for -blockdev via block_set_io_throttle monitor
- * command. This hack should be replaced by proper use of the 'throttle'
- * blockdev driver in qemu once it will support changing of the throttle group.
- * Same hack is done in qemuDomainAttachDiskGeneric.
+ * Sets up disk settings available only at runtime:
+ * - trottling for -blockdev via block_set_io_throttle QMP command
*/
static int
-qemuProcessSetupDiskThrottling(virDomainObj *vm,
- virDomainAsyncJob asyncJob)
+qemuProcessSetupDisks(virDomainObj *vm,
+ virDomainAsyncJob asyncJob)
{
size_t i;
int ret = -1;
- VIR_DEBUG("Setting up disk throttling for -blockdev via block_set_io_throttle");
+ VIR_DEBUG("Setting up disk config via runtime commands");
if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0)
return -1;
@@ -8575,7 +8573,7 @@ qemuProcessLaunch(virConnectPtr conn,
if (qemuProcessSetupBalloon(vm, asyncJob) < 0)
goto cleanup;
- if (qemuProcessSetupDiskThrottling(vm, asyncJob) < 0)
+ if (qemuProcessSetupDisks(vm, asyncJob) < 0)
goto cleanup;
/* Since CPUs were not started yet, the balloon could not return the memory
--
2.53.0

View File

@ -298,7 +298,7 @@
Summary: Library providing a simple virtualization API
Name: libvirt
Version: 11.10.0
Release: 8%{?dist}%{?extra_release}.alma.1
Release: 9%{?dist}%{?extra_release}.alma.1
License: GPL-2.0-or-later AND LGPL-2.1-only AND LGPL-2.1-or-later AND OFL-1.1
URL: https://libvirt.org/
@ -346,6 +346,19 @@ Patch37: libvirt-tests-qemuxmlconfdata-provide-iommufd-sample-XML-and-CLI-args.p
Patch38: libvirt-src-Use-device-alias-when-ifname-is-unset-in-virDomainInterfaceAddresses.patch
Patch39: libvirt-src-esx-esx_vi.c-Debug-path-element-comparisons.patch
Patch40: libvirt-qemu-Ignore-cmp_legacy-CPU-flag.patch
Patch41: libvirt-qemu-capabilities-Probe-properties-of-scsi-block-and-scsi-generic-devices.patch
Patch42: libvirt-qemu-capabilities-Introduce-QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR.patch
Patch43: libvirt-RHEL-ONLY-backport-test-data-for-migrate-pr-capability-of-scsi-block.patch
Patch44: libvirt-qemu-Implement-support-for-persistent-reservation-migration-control.patch
Patch45: libvirt-qemu-Extract-disk-setup-done-via-QMP-into-a-separate-helper.patch
Patch46: libvirt-qemu-process-Rename-qemuProcessSetupDiskThrottling-to-qemuProcessSetupDisks.patch
Patch47: libvirt-qemu-monitor-Extract-block-latency-histogram-stats-into-qemuBlockStats.patch
Patch48: libvirt-Expose-latency-histograms-via-virConnectGetAllDomainStats.patch
Patch49: libvirt-qemu-monitor-Add-handlers-for-block-latency-histogram-set.patch
Patch50: libvirt-docs-formatdomain-Fix-indentation-of-docs-for-disk-driver-statistics-element.patch
Patch51: libvirt-docs-formatdomain-Reword-section-about-the-statistics-element-under-disk-driver.patch
Patch52: libvirt-Introduce-support-for-disk-operation-latency-histogram-collection.patch
Patch53: libvirt-qemu-Setup-disk-latency-histograms-on-startup-hotplug-update.patch
Requires: libvirt-daemon = %{version}-%{release}
@ -2737,9 +2750,24 @@ exit 0
%endif
%changelog
* Thu Feb 12 2026 Eduard Abdullin <eabdullin@almalinux.org> - 11.10.0-8.alma.1
* Wed Feb 18 2026 Eduard Abdullin <eabdullin@almalinux.org> - 11.10.0-9.alma.1
- Enable building for ppc64le
* Tue Feb 17 2026 Jiri Denemark <jdenemar@redhat.com> - 11.10.0-9
- qemu: capabilities: Probe properties of 'scsi-block' and 'scsi-generic' devices (RHEL-135115)
- qemu: capabilities: Introduce QEMU_CAPS_DEVICE_SCSI_BLOCK_MIGRATE_PR (RHEL-135115)
- RHEL-ONLY: backport test data for 'migrate-pr' capability of 'scsi-block' (RHEL-135115)
- qemu: Implement support for persistent reservation migration control (RHEL-135115)
- qemu: Extract disk setup done via QMP into a separate helper (RHEL-131335)
- qemu: process: Rename 'qemuProcessSetupDiskThrottling' to 'qemuProcessSetupDisks' (RHEL-131335)
- qemu: monitor: Extract block latency histogram stats into 'qemuBlockStats' (RHEL-131335)
- Expose latency histograms via 'virConnectGetAllDomainStats' (RHEL-131335)
- qemu: monitor: Add handlers for 'block-latency-histogram-set' (RHEL-131335)
- docs: formatdomain: Fix indentation of docs for <disk><driver><statistics> element (RHEL-131335)
- docs: formatdomain: Reword section about the '<statistics>' element under disk driver (RHEL-131335)
- Introduce support for disk operation latency histogram collection (RHEL-131335)
- qemu: Setup disk latency histograms on startup/hotplug/update (RHEL-131335)
* Wed Feb 11 2026 Jiri Denemark <jdenemar@redhat.com> - 11.10.0-8
- src/esx/esx_vi.c: Debug path element comparisons (RHEL-145080)
- qemu: Ignore cmp_legacy CPU flag (RHEL-148494)