[libvirt] [tck PATCH] eliminate use of deprecated brctl in network tests
by Laine Stump
brctl is part of the bridge-utils package, which has been deprecated /
replaced by the "ip" and "bridge" commands in the iproute package in
all modern distros. This patch removes the few usages of brctl in
libvirt-tck's network tests, replacing it with a functional equivalent
that uses "ip link show type bridge" instead.
Signed-off-by: Laine Stump <laine(a)laine.org>
---
scripts/networks/networkxml2hostout/tck-testnet-1.dat | 4 ++--
scripts/networks/networkxml2hostout/tck-testnet-1.post.dat | 2 +-
scripts/networks/networkxml2hostout/tck-testnet-2.dat | 4 ++--
scripts/networks/networkxml2hostout/tck-testnet-2.post.dat | 2 +-
scripts/networks/networkxml2hostout/tck-testnet-3.dat | 4 ++--
scripts/networks/networkxml2hostout/tck-testnet-3.post.dat | 2 +-
6 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/scripts/networks/networkxml2hostout/tck-testnet-1.dat b/scripts/networks/networkxml2hostout/tck-testnet-1.dat
index 59cda2f..3e2ce12 100644
--- a/scripts/networks/networkxml2hostout/tck-testnet-1.dat
+++ b/scripts/networks/networkxml2hostout/tck-testnet-1.dat
@@ -15,8 +15,8 @@ ACCEPT all -- 10.1.2.0/24 0.0.0.0/0
bind-dynamic
#grep dhcp-range `ps aux | sed -n '0,/dnsmasq .*tck-testnet/ s|.*--conf-file=\(.*tck-testnet.conf\).*|\1|p'`
dhcp-range=10.1.2.2,10.1.2.254
-#brctl show | grep tck-testbr | gawk '{print $1" "$3}'
-tck-testbr yes
+#ip link show type bridge | grep tck-testbr | gawk '{print $2}'
+tck-testbr:
#ip -o addr show dev tck-testbr | gawk '{print $4" "$6}'
10.1.2.1/24 10.1.2.255
#virsh net-list | grep tck-testnet
diff --git a/scripts/networks/networkxml2hostout/tck-testnet-1.post.dat b/scripts/networks/networkxml2hostout/tck-testnet-1.post.dat
index 48e1d5a..30f981a 100644
--- a/scripts/networks/networkxml2hostout/tck-testnet-1.post.dat
+++ b/scripts/networks/networkxml2hostout/tck-testnet-1.post.dat
@@ -4,6 +4,6 @@
#ps aux | sed -n '/dnsmasq .*tck-testnet/ s|.*\(dhcp-range 10\.1\.2\.2\,10\.1\.2\.254*\).*|\1|p'
#route -n | grep '10\.1\.2\.'
#route -n | grep '10\.1\.2\.'
-#brctl show | grep tck-testbr | gawk '{print $1" "$3}'
+#ip link show type bridge | grep tck-testbr | gawk '{print $2}'
#ifconfig tck-testbr 2>/dev/null| grep ':10\.1\.2\.'
#virsh net-list | grep tck-testnet
diff --git a/scripts/networks/networkxml2hostout/tck-testnet-2.dat b/scripts/networks/networkxml2hostout/tck-testnet-2.dat
index 4f3d135..48b4b28 100644
--- a/scripts/networks/networkxml2hostout/tck-testnet-2.dat
+++ b/scripts/networks/networkxml2hostout/tck-testnet-2.dat
@@ -10,8 +10,8 @@ ACCEPT all -- 10.1.2.0/24 0.0.0.0/0
bind-dynamic
#grep dhcp-range `ps aux | sed -n '0,/dnsmasq .*tck-testnet/ s|.*--conf-file=\(.*tck-testnet.conf\).*|\1|p'`
dhcp-range=10.1.2.2,10.1.2.254
-#brctl show | grep tck-testbr | gawk '{print $1" "$3}'
-tck-testbr yes
+#ip link show type bridge | grep tck-testbr | gawk '{print $2}'
+tck-testbr:
#ip -o addr show dev tck-testbr | gawk '{print $4" "$6}'
10.1.2.1/24 10.1.2.255
#virsh net-list | grep tck-testnet
diff --git a/scripts/networks/networkxml2hostout/tck-testnet-2.post.dat b/scripts/networks/networkxml2hostout/tck-testnet-2.post.dat
index a8e0f60..a80f663 100644
--- a/scripts/networks/networkxml2hostout/tck-testnet-2.post.dat
+++ b/scripts/networks/networkxml2hostout/tck-testnet-2.post.dat
@@ -3,6 +3,6 @@
#ps aux | sed -n '/dnsmasq .*tck-testnet/ s|.*\(listen-address 10\.1\.2\.1\).*|\1|p'
#ps aux | sed -n '/dnsmasq .*tck-testnet/ s|.*\(dhcp-range 10\.1\.2\.2,10\.1\.2\.254\).*|\1|p'
#route -n | grep '10\.1\.2\.'
-#brctl show | grep tck-testbr | gawk '{print $1" "$3}'
+#ip link show type bridge | grep tck-testbr | gawk '{print $2}'
#ifconfig tck-testbr 2>/dev/null | grep ':10\.1\.2\.'
#virsh net-list | grep tck-testnet
diff --git a/scripts/networks/networkxml2hostout/tck-testnet-3.dat b/scripts/networks/networkxml2hostout/tck-testnet-3.dat
index 5c61690..fca4f81 100644
--- a/scripts/networks/networkxml2hostout/tck-testnet-3.dat
+++ b/scripts/networks/networkxml2hostout/tck-testnet-3.dat
@@ -20,8 +20,8 @@ bind-dynamic
dhcp-range=10.1.2.2,10.1.2.254
dhcp-range=2001:db8:ac10:fe01::1,ra-only
dhcp-range=2001:db8:ac10:fd01::1,ra-only
-#brctl show | grep tck-testbr | gawk '{print $1" "$3}'
-tck-testbr yes
+#ip link show type bridge | grep tck-testbr | gawk '{print $2}'
+tck-testbr:
#ip -o addr show dev tck-testbr | gawk '{print $4" "$6}' | grep -v link
10.1.2.1/24 10.1.2.255
192.168.97.1/24 192.168.97.255
diff --git a/scripts/networks/networkxml2hostout/tck-testnet-3.post.dat b/scripts/networks/networkxml2hostout/tck-testnet-3.post.dat
index e525e72..2bebd61 100644
--- a/scripts/networks/networkxml2hostout/tck-testnet-3.post.dat
+++ b/scripts/networks/networkxml2hostout/tck-testnet-3.post.dat
@@ -11,7 +11,7 @@
#route -n | grep '10\.1\.2\.'
#route -n | grep '192\.168\.97\.'
#route -n | grep '172\.28\.255\.240'
-#brctl show | grep tck-testbr
+#ip link show type bridge | grep tck-testbr | gawk '{print $2}'
#ifconfig tck-testbr 2>/dev/null | grep ':10\.1\.2\.'
#ifconfig tck-testbr 2>/dev/null | grep 'inet6 addr: 2001'
#ip addr show tck-testbr 2>/dev/null | grep "inet "
--
2.18.0
6 years, 3 months
[libvirt] [PATCH] api,qemu: add block latency histogram
by Nikolay Shirokovskiy
This patch adds option to configure/read latency histogram of
block device IO operations. The corresponding functionality
in qemu still has x- prefix AFAIK. So this patch should
help qemu functionality to become non experimental.
In short histogram is configured thru new API virDomainSetBlockLatencyHistogram and
histogram itself is available as new fields of virConnectGetAllDomainStats
output.
---
include/libvirt/libvirt-domain.h | 27 ++++++
src/access/viraccessperm.c | 3 +-
src/access/viraccessperm.h | 6 ++
src/conf/domain_conf.c | 6 ++
src/conf/domain_conf.h | 1 +
src/driver-hypervisor.h | 9 ++
src/libvirt-domain.c | 58 +++++++++++++
src/libvirt_private.syms | 2 +
src/libvirt_public.syms | 5 ++
src/qemu/qemu_driver.c | 136 ++++++++++++++++++++++++++++++
src/qemu/qemu_monitor.c | 37 +++++++-
src/qemu/qemu_monitor.h | 19 +++++
src/qemu/qemu_monitor_json.c | 163 ++++++++++++++++++++++++++++++++----
src/qemu/qemu_monitor_json.h | 8 ++
src/remote/remote_daemon_dispatch.c | 39 +++++++++
src/remote/remote_driver.c | 49 ++++++++++-
src/remote/remote_protocol.x | 23 ++++-
src/remote_protocol-structs | 11 +++
tools/virsh-domain.c | 118 ++++++++++++++++++++++++++
tools/virsh.pod | 18 ++++
20 files changed, 716 insertions(+), 22 deletions(-)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index fdd2d6b..4fafa3d 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4793,4 +4793,31 @@ int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
int *nparams,
unsigned int flags);
+/*
+ * virDomainBlockLatencyHistogram:
+ *
+ * Selects a IO operation for which latency histogram is to be configured
+ */
+typedef enum {
+ VIR_DOMAIN_BLOCK_LATENCY_ALL = 0,
+ VIR_DOMAIN_BLOCK_LATENCY_READ = 1,
+ VIR_DOMAIN_BLOCK_LATENCY_WRITE = 2,
+ VIR_DOMAIN_BLOCK_LATENCY_FLUSH = 3,
+
+# ifdef VIR_ENUM_SENTINELS
+ VIR_DOMAIN_BLOCK_LATENCY_LAST
+ /*
+ * NB: this enum value will increase over time. It reflects the last state
+ * supported by this version of the libvirt API.
+ */
+# endif
+} virDomainBlockLatencyHistogram;
+
+int virDomainSetBlockLatencyHistogram(virDomainPtr dom,
+ const char *dev,
+ unsigned int op,
+ unsigned long long *boundaries,
+ int nboundaries,
+ unsigned int flags);
+
#endif /* __VIR_LIBVIRT_DOMAIN_H__ */
diff --git a/src/access/viraccessperm.c b/src/access/viraccessperm.c
index d7cbb70..e08853a 100644
--- a/src/access/viraccessperm.c
+++ b/src/access/viraccessperm.c
@@ -43,7 +43,8 @@ VIR_ENUM_IMPL(virAccessPermDomain,
"fs_trim", "fs_freeze",
"block_read", "block_write", "mem_read",
"open_graphics", "open_device", "screenshot",
- "open_namespace", "set_time", "set_password");
+ "open_namespace", "set_time", "set_password",
+ "block_stats_conf");
VIR_ENUM_IMPL(virAccessPermInterface,
VIR_ACCESS_PERM_INTERFACE_LAST,
diff --git a/src/access/viraccessperm.h b/src/access/viraccessperm.h
index 5ac5ff3..a3097c5 100644
--- a/src/access/viraccessperm.h
+++ b/src/access/viraccessperm.h
@@ -312,6 +312,12 @@ typedef enum {
*/
VIR_ACCESS_PERM_DOMAIN_SET_PASSWORD,
+ /**
+ * @desc: Configure block stats gathering
+ * @message: Configuring block stats gathering requires authorization
+ */
+ VIR_ACCESS_PERM_DOMAIN_BLOCK_STATS_CONF,
+
VIR_ACCESS_PERM_DOMAIN_LAST,
} virAccessPermDomain;
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 38cac07..6095636 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -802,6 +802,12 @@ VIR_ENUM_IMPL(virDomainCrashedReason, VIR_DOMAIN_CRASHED_LAST,
VIR_ENUM_IMPL(virDomainPMSuspendedReason, VIR_DOMAIN_PMSUSPENDED_LAST,
"unknown")
+VIR_ENUM_IMPL(virDomainBlockLatencyHistogram, VIR_DOMAIN_BLOCK_LATENCY_LAST,
+ "all",
+ "read",
+ "write",
+ "flush")
+
VIR_ENUM_IMPL(virDomainSeclabel, VIR_DOMAIN_SECLABEL_LAST,
"default",
"none",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8a36733..e2674c8 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3466,6 +3466,7 @@ VIR_ENUM_DECL(virDomainShutdownReason)
VIR_ENUM_DECL(virDomainShutoffReason)
VIR_ENUM_DECL(virDomainCrashedReason)
VIR_ENUM_DECL(virDomainPMSuspendedReason)
+VIR_ENUM_DECL(virDomainBlockLatencyHistogram)
const char *virDomainStateReasonToString(virDomainState state, int reason);
int virDomainStateReasonFromString(virDomainState state, const char *reason);
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index eef31eb..968334f 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1322,6 +1322,14 @@ typedef int
unsigned int flags);
+typedef int
+(*virDrvDomainSetBlockLatencyHistogram)(virDomainPtr dom,
+ const char *dev,
+ unsigned int op,
+ unsigned long long *boundaries,
+ int nboundaries,
+ unsigned int flags);
+
typedef struct _virHypervisorDriver virHypervisorDriver;
typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1572,6 +1580,7 @@ struct _virHypervisorDriver {
virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
virDrvNodeGetSEVInfo nodeGetSEVInfo;
virDrvDomainGetLaunchSecurityInfo domainGetLaunchSecurityInfo;
+ virDrvDomainSetBlockLatencyHistogram domainSetBlockLatencyHistogram;
};
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index ef46027..bfc1947 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12223,3 +12223,61 @@ int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
virDispatchError(domain->conn);
return -1;
}
+
+
+/*
+ * virDomainSetBlockLatencyHistogram:
+ * @domain: pointer to domain object
+ * @dev: string specifying the block device
+ * @op: selects io operation to set histogram for
+ * @boundaries: borders of histogram bins in nanoseconds, 0 ns and +inf ns
+ * borders are implicit and should not be specified
+ * @nboundaries: number of boundaries
+ * @flags: currently unused, callers should pass 0
+ *
+ * Configures latency histogram parameters for IO operation @op for disk @dev
+ * of the @domain. If @op is VIR_DOMAIN_BLOCK_LATENCY_ALL then histograms
+ * for all IO operations will be configured.
+ *
+ * @boundaries is list of histogram iterval boundaries in nanoseconds in acsending
+ * order. Boundaries 0 and +inf are implicit and should not be specified.
+ * For example 10, 50, 100 will configure histogram with intervals
+ * [0, 10), [10, 50), [50, 100) and [100, +inf). If @boundaries is NULL
+ * and @op is VIR_DOMAIN_BLOCK_LATENCY_ALL then all the histograms will be removed
+ * that is they will not be collected and will not be in the domain stats output.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int virDomainSetBlockLatencyHistogram(virDomainPtr domain,
+ const char *dev,
+ unsigned int op,
+ unsigned long long *boundaries,
+ int nboundaries,
+ unsigned int flags)
+{
+ VIR_DOMAIN_DEBUG(domain, "dev='%s' op=%d boundaries=%p "
+ "nboundaries=%d flags=0x%x",
+ NULLSTR(dev), op, boundaries, nboundaries, flags);
+
+ virResetLastError();
+
+ virCheckDomainReturn(domain, -1);
+ virCheckReadOnlyGoto(domain->conn->flags, error);
+
+ virCheckNonNullArgGoto(dev, error);
+
+ if (domain->conn->driver->domainSetBlockLatencyHistogram) {
+ int ret;
+ ret = domain->conn->driver->domainSetBlockLatencyHistogram(
+ domain, dev, op, boundaries, nboundaries, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(domain->conn);
+ return -1;
+}
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 954ab4b..3eb36f1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -189,6 +189,8 @@ virDiskNameToIndex;
virDomainActualNetDefFree;
virDomainBlockedReasonTypeFromString;
virDomainBlockedReasonTypeToString;
+virDomainBlockLatencyHistogramTypeFromString;
+virDomainBlockLatencyHistogramTypeToString;
virDomainBootTypeFromString;
virDomainBootTypeToString;
virDomainCapabilitiesPolicyTypeToString;
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index d4cdbd8..4f20993 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -809,4 +809,9 @@ LIBVIRT_4.5.0 {
virNWFilterBindingGetFilterName;
} LIBVIRT_4.4.0;
+LIBVIRT_4.8.0 {
+ global:
+ virDomainSetBlockLatencyHistogram;
+} LIBVIRT_4.5.0;
+
# .... define new API here using predicted next version number ....
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a0f7c71..d473ddc 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20099,6 +20099,48 @@ qemuDomainGetStatsOneBlockRefreshNamed(virStorageSourcePtr src,
static int
+qemuDomainGetBlockLatency(virDomainStatsRecordPtr record,
+ int *maxparams,
+ size_t block_idx,
+ const char *op,
+ qemuBlockLatencyStatsPtr latency)
+{
+ char param_name[VIR_TYPED_PARAM_FIELD_LENGTH];
+ size_t i;
+ int ret = -1;
+
+ if (!latency->nbins)
+ return 0;
+
+ snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
+ "block.%zu.latency.%s.bincount", block_idx, op);
+ if (virTypedParamsAddUInt(&record->params, &record->nparams, maxparams,
+ param_name, latency->nbins) < 0)
+ goto cleanup;
+
+ for (i = 0; i < latency->nbins; i++) {
+ snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
+ "block.%zu.latency.%s.bin.%zu", block_idx, op, i);
+ if (virTypedParamsAddULLong(&record->params, &record->nparams, maxparams,
+ param_name, latency->bins[i]) < 0)
+ goto cleanup;
+ }
+
+ for (i = 0; i < latency->nbins - 1; i++) {
+ snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH,
+ "block.%zu.latency.%s.boundary.%zu", block_idx, op, i);
+ if (virTypedParamsAddULLong(&record->params, &record->nparams, maxparams,
+ param_name, latency->boundaries[i]) < 0)
+ goto cleanup;
+ }
+
+ ret = 0;
+ cleanup:
+ return ret;
+}
+
+
+static int
qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver,
virQEMUDriverConfigPtr cfg,
virDomainObjPtr dom,
@@ -20128,6 +20170,14 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver,
goto cleanup;
}
+ if (qemuDomainGetBlockLatency(record, maxparams, block_idx, "rd",
+ &entry->rd_latency) < 0 ||
+ qemuDomainGetBlockLatency(record, maxparams, block_idx, "wr",
+ &entry->wr_latency) < 0 ||
+ qemuDomainGetBlockLatency(record, maxparams, block_idx, "fl",
+ &entry->flush_latency) < 0)
+ goto cleanup;
+
QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
"allocation", entry->wr_highest_offset);
@@ -21752,6 +21802,91 @@ qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
return ret;
}
+
+static
+int qemuDomainSetBlockLatencyHistogram(virDomainPtr dom,
+ const char *dev,
+ unsigned int op,
+ unsigned long long *boundaries,
+ int nboundaries,
+ unsigned int flags)
+{
+ virQEMUDriverPtr driver = dom->conn->privateData;
+ qemuDomainObjPrivatePtr priv;
+ virDomainObjPtr vm;
+ virDomainDiskDefPtr disk;
+ char *device = NULL;
+ bool job = false;
+ int ret = -1;
+ int rc;
+
+ virCheckFlags(0, -1);
+
+ if (op >= VIR_DOMAIN_BLOCK_LATENCY_LAST) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("unknown latency histogram: %d"), op);
+ return -1;
+ }
+
+ if (!boundaries && op) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("per operation histogram deletion is not supported"));
+ return -1;
+ }
+
+ if (boundaries && nboundaries > 1) {
+ size_t i;
+
+ for (i = 0; i < nboundaries - 1; i++) {
+ if (boundaries[i] > boundaries[i + 1]) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("boundaries should be in ascending order"));
+ return -1;
+ }
+ }
+ }
+
+ if (!(vm = qemuDomObjFromDomain(dom)))
+ return -1;
+
+ if (virDomainSetBlockLatencyHistogramEnsureACL(dom->conn, vm->def) < 0)
+ goto cleanup;
+
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+ goto cleanup;
+ job = true;
+
+ if (!virDomainObjIsActive(vm)) {
+ virReportError(VIR_ERR_OPERATION_INVALID,
+ "%s", _("domain is not running"));
+ goto cleanup;
+ }
+
+ priv = vm->privateData;
+
+ if (!(disk = qemuDomainDiskByName(vm->def, dev)))
+ goto cleanup;
+
+ if (!(device = qemuAliasDiskDriveFromDisk(disk)))
+ goto cleanup;
+
+ qemuDomainObjEnterMonitor(driver, vm);
+ rc = qemuMonitorBlockLatencyHistogramSet(priv->mon, device, op,
+ boundaries, nboundaries);
+ if (qemuDomainObjExitMonitor(driver, vm) < 0 || rc < 0)
+ goto cleanup;
+
+ ret = 0;
+ cleanup:
+ if (job)
+ qemuDomainObjEndJob(driver, vm);
+ virDomainObjEndAPI(&vm);
+ VIR_FREE(device);
+
+ return ret;
+}
+
+
static virHypervisorDriver qemuHypervisorDriver = {
.name = QEMU_DRIVER_NAME,
.connectURIProbe = qemuConnectURIProbe,
@@ -21977,6 +22112,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
.connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 */
.nodeGetSEVInfo = qemuNodeGetSEVInfo, /* 4.5.0 */
.domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.5.0 */
+ .domainSetBlockLatencyHistogram = qemuDomainSetBlockLatencyHistogram, /* 4.8.0 */
};
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 4c0002d..064da62 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2257,6 +2257,25 @@ qemuMonitorQueryBlockstats(qemuMonitorPtr mon)
}
+void
+qemuBlockStatsFree(void *value, const void *name ATTRIBUTE_UNUSED)
+{
+ qemuBlockStatsPtr stats = value;
+
+ if (!stats)
+ return;
+
+ VIR_FREE(stats->rd_latency.bins);
+ VIR_FREE(stats->rd_latency.boundaries);
+ VIR_FREE(stats->wr_latency.bins);
+ VIR_FREE(stats->wr_latency.boundaries);
+ VIR_FREE(stats->flush_latency.bins);
+ VIR_FREE(stats->flush_latency.boundaries);
+
+ VIR_FREE(stats);
+}
+
+
/**
* qemuMonitorGetAllBlockStatsInfo:
* @mon: monitor object
@@ -2279,7 +2298,7 @@ qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
QEMU_CHECK_MONITOR(mon);
- if (!(*ret_stats = virHashCreate(10, virHashValueFree)))
+ if (!(*ret_stats = virHashCreate(10, qemuBlockStatsFree)))
goto error;
ret = qemuMonitorJSONGetAllBlockStatsInfo(mon, *ret_stats,
@@ -4429,3 +4448,19 @@ qemuMonitorGetPRManagerInfo(qemuMonitorPtr mon,
virHashFree(info);
return ret;
}
+
+int
+qemuMonitorBlockLatencyHistogramSet(qemuMonitorPtr mon,
+ const char *device,
+ unsigned int op,
+ unsigned long long *boundaries,
+ int nboundaries)
+{
+ VIR_DEBUG("mon=%p, device=%s op=%d boundaries=%p nboundaries=%d",
+ mon, device, op, boundaries, nboundaries);
+
+ QEMU_CHECK_MONITOR(mon);
+
+ return qemuMonitorJSONBlockLatencyHistogramSet(mon, device, op,
+ boundaries, nboundaries);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 48b142a..9295ecb 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -569,6 +569,14 @@ virHashTablePtr qemuMonitorGetBlockInfo(qemuMonitorPtr mon);
virJSONValuePtr qemuMonitorQueryBlockstats(qemuMonitorPtr mon);
+typedef struct _qemuBlockLatencyStats qemuBlockLatencyStats;
+typedef qemuBlockLatencyStats *qemuBlockLatencyStatsPtr;
+struct _qemuBlockLatencyStats {
+ unsigned long long *boundaries;
+ unsigned long long *bins;
+ unsigned int nbins;
+};
+
typedef struct _qemuBlockStats qemuBlockStats;
typedef qemuBlockStats *qemuBlockStatsPtr;
struct _qemuBlockStats {
@@ -580,6 +588,9 @@ struct _qemuBlockStats {
long long wr_total_times;
long long flush_req;
long long flush_total_times;
+ qemuBlockLatencyStats rd_latency;
+ qemuBlockLatencyStats wr_latency;
+ qemuBlockLatencyStats flush_latency;
unsigned long long capacity;
unsigned long long physical;
@@ -592,6 +603,8 @@ struct _qemuBlockStats {
unsigned long long write_threshold;
};
+void qemuBlockStatsFree(void *value, const void *name);
+
int qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
virHashTablePtr *ret_stats,
bool backingChain)
@@ -1188,4 +1201,10 @@ struct _qemuMonitorPRManagerInfo {
int qemuMonitorGetPRManagerInfo(qemuMonitorPtr mon,
virHashTablePtr *retinfo);
+int qemuMonitorBlockLatencyHistogramSet(qemuMonitorPtr mon,
+ const char *device,
+ unsigned int op,
+ unsigned long long *boundaries,
+ int nboundaries);
+
#endif /* QEMU_MONITOR_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 3181805..7622626 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2319,6 +2319,64 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
}
+static int
+qemuMonitorJSONGetBlockLatencyStats(virJSONValuePtr stats,
+ const char *name,
+ qemuBlockLatencyStatsPtr latency)
+{
+ virJSONValuePtr latencyJSON;
+ virJSONValuePtr bins;
+ virJSONValuePtr boundaries;
+ size_t i;
+
+ if (!(latencyJSON = virJSONValueObjectGetObject(stats, name)))
+ return 0;
+
+ if (!(bins = virJSONValueObjectGetArray(latencyJSON, "bins"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read bins in latency %s"), name);
+ return -1;
+ }
+
+ if (!(boundaries = virJSONValueObjectGetArray(latencyJSON, "boundaries"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read boundaries in latency %s"), name);
+ return -1;
+ }
+
+ if (virJSONValueArraySize(bins) != virJSONValueArraySize(boundaries) + 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("bins and boundaries size mismatch in latency %s"), name);
+ return -1;
+ }
+ latency->nbins = virJSONValueArraySize(bins);
+
+ if (VIR_ALLOC_N(latency->boundaries, latency->nbins - 1) < 0 ||
+ VIR_ALLOC_N(latency->bins, latency->nbins) < 0)
+ return -1;
+
+ for (i = 0; i < latency->nbins; i++) {
+ if (virJSONValueGetNumberUlong(virJSONValueArrayGet(bins, i),
+ &latency->bins[i]) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid bins in latency %s"), name);
+ return -1;
+ }
+ }
+
+ for (i = 0; i < latency->nbins - 1; i++) {
+ if (virJSONValueGetNumberUlong(virJSONValueArrayGet(boundaries, i),
+ &latency->boundaries[i]) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid boundaries in latency %s"), name);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
static qemuBlockStatsPtr
qemuMonitorJSONBlockStatsCollectData(virJSONValuePtr dev,
int *nstats)
@@ -2358,6 +2416,17 @@ qemuMonitorJSONBlockStatsCollectData(virJSONValuePtr dev,
QEMU_MONITOR_BLOCK_STAT_GET("flush_total_time_ns", bstats->flush_total_times, false);
#undef QEMU_MONITOR_BLOCK_STAT_GET
+#define QEMU_MONITOR_BLOCK_LATENCY_GET(NAME) \
+ if (qemuMonitorJSONGetBlockLatencyStats(stats, \
+ #NAME "_latency_histogram", \
+ &bstats->NAME ## _latency) < 0) \
+ goto cleanup;
+
+ QEMU_MONITOR_BLOCK_LATENCY_GET(rd);
+ QEMU_MONITOR_BLOCK_LATENCY_GET(wr);
+ QEMU_MONITOR_BLOCK_LATENCY_GET(flush);
+#undef QEMU_MONITOR_BLOCK_LATENCY_GET
+
if ((parent = virJSONValueObjectGetObject(dev, "parent")) &&
(parentstats = virJSONValueObjectGetObject(parent, "stats"))) {
if (virJSONValueObjectGetNumberUlong(parentstats, "wr_highest_offset",
@@ -2368,30 +2437,28 @@ qemuMonitorJSONBlockStatsCollectData(virJSONValuePtr dev,
VIR_STEAL_PTR(ret, bstats);
cleanup:
- VIR_FREE(bstats);
+ qemuBlockStatsFree(bstats, NULL);
return ret;
}
static int
-qemuMonitorJSONAddOneBlockStatsInfo(qemuBlockStatsPtr bstats,
+qemuMonitorJSONAddOneBlockStatsInfo(virJSONValuePtr dev,
const char *name,
virHashTablePtr stats)
{
- qemuBlockStatsPtr copy = NULL;
+ qemuBlockStatsPtr bstats;
+ int nstats;
- if (VIR_ALLOC(copy) < 0)
+ if (!(bstats = qemuMonitorJSONBlockStatsCollectData(dev, &nstats)))
return -1;
- if (bstats)
- *copy = *bstats;
-
- if (virHashAddEntry(stats, name, copy) < 0) {
- VIR_FREE(copy);
+ if (virHashAddEntry(stats, name, bstats) < 0) {
+ qemuBlockStatsFree(bstats, NULL);
return -1;
}
- return 0;
+ return nstats;
}
@@ -2402,7 +2469,6 @@ qemuMonitorJSONGetOneBlockStatsInfo(virJSONValuePtr dev,
virHashTablePtr hash,
bool backingChain)
{
- qemuBlockStatsPtr bstats = NULL;
int ret = -1;
int nstats = 0;
const char *qdevname = NULL;
@@ -2423,19 +2489,16 @@ qemuMonitorJSONGetOneBlockStatsInfo(virJSONValuePtr dev,
goto cleanup;
}
- if (!(bstats = qemuMonitorJSONBlockStatsCollectData(dev, &nstats)))
- goto cleanup;
-
if (devicename &&
- qemuMonitorJSONAddOneBlockStatsInfo(bstats, devicename, hash) < 0)
+ (nstats = qemuMonitorJSONAddOneBlockStatsInfo(dev, devicename, hash)) < 0)
goto cleanup;
if (qdevname && STRNEQ_NULLABLE(qdevname, devicename) &&
- qemuMonitorJSONAddOneBlockStatsInfo(bstats, qdevname, hash) < 0)
+ qemuMonitorJSONAddOneBlockStatsInfo(dev, qdevname, hash) < 0)
goto cleanup;
if (nodename &&
- qemuMonitorJSONAddOneBlockStatsInfo(bstats, nodename, hash) < 0)
+ qemuMonitorJSONAddOneBlockStatsInfo(dev, nodename, hash) < 0)
goto cleanup;
if (backingChain &&
@@ -2446,7 +2509,6 @@ qemuMonitorJSONGetOneBlockStatsInfo(virJSONValuePtr dev,
ret = nstats;
cleanup:
- VIR_FREE(bstats);
VIR_FREE(devicename);
return ret;
}
@@ -8396,3 +8458,68 @@ qemuMonitorJSONGetPRManagerInfo(qemuMonitorPtr mon,
return ret;
}
+
+
+int
+qemuMonitorJSONBlockLatencyHistogramSet(qemuMonitorPtr mon,
+ const char *device,
+ unsigned int op,
+ unsigned long long *boundaries,
+ int nboundaries)
+{
+ int ret = -1;
+ char *specOp = NULL;
+ virJSONValuePtr cmd = NULL;
+ virJSONValuePtr reply = NULL;
+ const char *specAll = "A:boundaries";
+ const char *spec;
+ virJSONValuePtr boundariesJSON = NULL;
+
+ if (op != VIR_DOMAIN_BLOCK_LATENCY_ALL) {
+ if (virAsprintf(&specOp, "A:boundaries-%s",
+ virDomainBlockLatencyHistogramTypeToString(op)) < 0)
+ return -1;
+ spec = specOp;
+ } else {
+ spec = specAll;
+ }
+
+ if (boundaries) {
+ size_t i;
+
+ if (!(boundariesJSON = virJSONValueNewArray()))
+ goto cleanup;
+
+ for (i = 0; i < nboundaries; i++) {
+ virJSONValuePtr val;
+
+ if (!(val = virJSONValueNewNumberUlong(boundaries[i])) ||
+ virJSONValueArrayAppend(boundariesJSON, val) < 0) {
+ virJSONValueFree(val);
+ goto cleanup;
+ }
+ }
+ }
+
+ if (!(cmd = qemuMonitorJSONMakeCommand("block-latency-histogram-set",
+ "s:device", device,
+ spec, &boundariesJSON,
+ NULL)))
+ return -1;
+
+ if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+ goto cleanup;
+
+ if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ virJSONValueFree(boundariesJSON);
+ VIR_FREE(specOp);
+
+ return ret;
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index da267b1..f1636a4 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -577,4 +577,12 @@ int qemuMonitorJSONGetPRManagerInfo(qemuMonitorPtr mon,
virHashTablePtr info)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+int
+qemuMonitorJSONBlockLatencyHistogramSet(qemuMonitorPtr mon,
+ const char *device,
+ unsigned int op,
+ unsigned long long *boundaries,
+ int nboundaries)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
#endif /* QEMU_MONITOR_JSON_H */
diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c
index e62ebfb..50d2dc4 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -7030,6 +7030,45 @@ remoteDispatchStorageVolGetInfoFlags(virNetServerPtr server ATTRIBUTE_UNUSED,
}
+static int
+remoteDispatchDomainSetBlockLatencyHistogram(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr,
+ remote_domain_set_block_latency_histogram_args *args,
+ remote_domain_set_block_latency_histogram_ret *ret)
+{
+ int rv = -1;
+ virDomainPtr dom = NULL;
+ int result;
+ struct daemonClientPrivate *priv = virNetServerClientGetPrivateData(client);
+
+ if (!priv->conn) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+ goto cleanup;
+ }
+
+ if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+ goto cleanup;
+
+ if ((result = virDomainSetBlockLatencyHistogram(dom, args->dev,
+ args->op,
+ (unsigned long long *)args->boundaries.boundaries_val,
+ args->boundaries.boundaries_len,
+ args->flags)) < 0)
+ goto cleanup;
+
+ ret->result = result;
+ rv = 0;
+
+ cleanup:
+ if (rv < 0)
+ virNetMessageSaveError(rerr);
+ virObjectUnref(dom);
+ return rv;
+}
+
+
/*----- Helpers. -----*/
/* get_nonnull_domain and get_nonnull_network turn an on-wire
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 3b43e21..c5f9295 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8153,6 +8153,52 @@ remoteStorageVolGetInfoFlags(virStorageVolPtr vol,
}
+static int
+remoteDomainSetBlockLatencyHistogram(virDomainPtr dom,
+ const char *dev,
+ unsigned int op,
+ unsigned long long *boundaries,
+ int nboundaries,
+ unsigned int flags)
+{
+ int rv = -1;
+ struct private_data *priv = dom->conn->privateData;
+ remote_domain_set_block_latency_histogram_args args;
+ remote_domain_set_block_latency_histogram_ret ret;
+
+ remoteDriverLock(priv);
+
+ if (nboundaries > REMOTE_DOMAIN_SET_BLOCK_LATENCY_HISTOGRAM_BOUNDARIES_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("boundaries length greater than maximum: %d > %d"),
+ nboundaries,
+ REMOTE_DOMAIN_SET_BLOCK_LATENCY_HISTOGRAM_BOUNDARIES_MAX);
+ goto done;
+ }
+
+ make_nonnull_domain(&args.dom, dom);
+ args.dev = (char *)dev;
+ args.op = op;
+ args.boundaries.boundaries_val = (uint64_t *) boundaries;
+ args.boundaries.boundaries_len = nboundaries;
+ args.flags = flags;
+
+ memset(&ret, 0, sizeof(ret));
+
+ if (call(dom->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_BLOCK_LATENCY_HISTOGRAM,
+ (xdrproc_t)xdr_remote_domain_set_block_latency_histogram_args, (char *)&args,
+ (xdrproc_t)xdr_remote_domain_set_block_latency_histogram_ret, (char *)&ret) == -1) {
+ goto done;
+ }
+
+ rv = ret.result;
+
+ done:
+ remoteDriverUnlock(priv);
+ return rv;
+}
+
+
/* get_nonnull_domain and get_nonnull_network turn an on-wire
* (name, uuid) pair into virDomainPtr or virNetworkPtr object.
* These can return NULL if underlying memory allocations fail,
@@ -8536,7 +8582,8 @@ static virHypervisorDriver hypervisor_driver = {
.connectCompareHypervisorCPU = remoteConnectCompareHypervisorCPU, /* 4.4.0 */
.connectBaselineHypervisorCPU = remoteConnectBaselineHypervisorCPU, /* 4.4.0 */
.nodeGetSEVInfo = remoteNodeGetSEVInfo, /* 4.5.0 */
- .domainGetLaunchSecurityInfo = remoteDomainGetLaunchSecurityInfo /* 4.5.0 */
+ .domainGetLaunchSecurityInfo = remoteDomainGetLaunchSecurityInfo, /* 4.5.0 */
+ .domainSetBlockLatencyHistogram = remoteDomainSetBlockLatencyHistogram, /* 4.8.0 */
};
static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 28c8feb..c4ede63 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -262,6 +262,9 @@ const REMOTE_NODE_SEV_INFO_MAX = 64;
/* Upper limit on number of launch security information entries */
const REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX = 64;
+/* Upper limit on block latency histogram boundaries. */
+const REMOTE_DOMAIN_SET_BLOCK_LATENCY_HISTOGRAM_BOUNDARIES_MAX = 1024;
+
/* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */
typedef opaque remote_uuid[VIR_UUID_BUFLEN];
@@ -3557,6 +3560,18 @@ struct remote_connect_list_all_nwfilter_bindings_ret { /* insert@1 */
unsigned int ret;
};
+struct remote_domain_set_block_latency_histogram_args {
+ remote_nonnull_domain dom;
+ remote_nonnull_string dev;
+ unsigned int op;
+ unsigned hyper boundaries<REMOTE_DOMAIN_SET_BLOCK_LATENCY_HISTOGRAM_BOUNDARIES_MAX>;
+ unsigned int flags;
+};
+
+struct remote_domain_set_block_latency_histogram_ret {
+ int result;
+};
+
/*----- Protocol. -----*/
/* Define the program number, protocol version and procedure numbers here. */
@@ -6312,5 +6327,11 @@ enum remote_procedure {
* @acl: connect:search_nwfilter_bindings
* @aclfilter: nwfilter_binding:getattr
*/
- REMOTE_PROC_CONNECT_LIST_ALL_NWFILTER_BINDINGS = 401
+ REMOTE_PROC_CONNECT_LIST_ALL_NWFILTER_BINDINGS = 401,
+
+ /**
+ * @generate: none
+ * @acl: domain:block_stats_conf
+ */
+ REMOTE_PROC_DOMAIN_SET_BLOCK_LATENCY_HISTOGRAM = 402
};
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 6343e14..aa85253 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -2966,6 +2966,16 @@ struct remote_connect_list_all_nwfilter_bindings_ret {
} bindings;
u_int ret;
};
+struct remote_domain_set_block_latency_histogram_args {
+ remote_nonnull_domain dom;
+ remote_nonnull_string dev;
+ u_int op;
+ struct {
+ u_int boundaries_len;
+ uint64_t boundaries_val;
+ } boundaries;
+ u_int flags;
+};
enum remote_procedure {
REMOTE_PROC_CONNECT_OPEN = 1,
REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -3368,4 +3378,5 @@ enum remote_procedure {
REMOTE_PROC_NWFILTER_BINDING_CREATE_XML = 399,
REMOTE_PROC_NWFILTER_BINDING_DELETE = 400,
REMOTE_PROC_CONNECT_LIST_ALL_NWFILTER_BINDINGS = 401,
+ REMOTE_PROC_DOMAIN_SET_BLOCK_LATENCY_HISTOGRAM = 402,
};
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index c1cff9f..e4cf49b 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -13816,6 +13816,118 @@ cmdDomFSInfo(vshControl *ctl, const vshCmd *cmd)
return ret >= 0;
}
+/*
+ * "block-set-latency-histogram" command
+ */
+static const vshCmdInfo info_block_set_latency_histogram[] = {
+ {.name = "help",
+ .data = N_("configures latency histogram for given device for given operation")
+ },
+ {.name = "desc",
+ .data = N_("configures latency histogram for given device for given operation")
+ },
+ {.name = NULL}
+};
+
+static const vshCmdOptDef opts_block_set_latency_histogram[] = {
+ VIRSH_COMMON_OPT_DOMAIN_FULL(VIR_CONNECT_LIST_DOMAINS_ACTIVE),
+ {.name = "dev",
+ .type = VSH_OT_DATA,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_("device to set latency histogram for")
+ },
+ {.name = "boundaries",
+ .type = VSH_OT_STRING,
+ .help = N_("comma separated histogram boundaries in nanoseconds")
+ },
+ {.name = "op",
+ .type = VSH_OT_STRING,
+ .help = N_("operation to set latency histogram for, all if omitted")
+ },
+ {.name = NULL}
+};
+
+static bool
+cmdBlockSetLatencyHistogram(vshControl *ctl, const vshCmd *cmd)
+{
+ const char *dev = NULL;
+ const char *opstr = NULL;
+ const char *boundariesstr = NULL;
+ char **boundarieslist = NULL;
+ char **tmp = NULL;
+ unsigned long long *boundaries = NULL;
+ size_t nboundaries = 0;
+ unsigned char op;
+ virDomainPtr dom;
+ bool ret = false;
+
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+ return false;
+
+ if (vshCommandOptStringReq(ctl, cmd, "dev", &dev) < 0)
+ goto cleanup;
+
+ if (vshCommandOptStringReq(ctl, cmd, "op", &opstr) < 0)
+ goto cleanup;
+
+ if (opstr) {
+ if (STREQ(opstr, "read")) {
+ op = VIR_DOMAIN_BLOCK_LATENCY_READ;
+ } else if (STREQ(opstr, "write")) {
+ op = VIR_DOMAIN_BLOCK_LATENCY_WRITE;
+ } else if (STREQ(opstr, "flush")) {
+ op = VIR_DOMAIN_BLOCK_LATENCY_FLUSH;
+ } else {
+ vshError(ctl, _("Unknown operation %s value, expecting "
+ "'read', 'write', 'flush'."), opstr);
+ goto cleanup;
+ }
+ } else {
+ op = VIR_DOMAIN_BLOCK_LATENCY_ALL;
+ }
+
+ if (vshCommandOptStringReq(ctl, cmd, "boundaries", &boundariesstr) < 0)
+ goto cleanup;
+
+ if (!boundariesstr && op) {
+ vshError(ctl, _("per operation histogram deletion is not supported"));
+ goto cleanup;
+ }
+
+ if (boundariesstr &&
+ !(boundarieslist = virStringSplit(boundariesstr, ",", 0))) {
+ vshError(ctl, "%s", _("Cannot parse boundaries string"));
+ goto cleanup;
+ }
+
+ tmp = boundarieslist;
+ while (boundarieslist && *tmp) {
+ unsigned long long val;
+
+ if (virStrToLong_ull(*tmp, NULL, 10, &val) < 0) {
+ vshError(ctl, _("Cannot parse boundaries value: %s"), *tmp);
+ goto cleanup;
+ }
+
+ if (VIR_APPEND_ELEMENT(boundaries, nboundaries, val) < 0)
+ goto cleanup;
+
+ tmp++;
+ }
+
+ if (virDomainSetBlockLatencyHistogram(dom, dev, op,
+ boundaries, nboundaries, 0) < 0)
+ goto cleanup;
+
+ ret = true;
+
+ cleanup:
+ virshDomainFree(dom);
+ virStringListFree(boundarieslist);
+ VIR_FREE(boundaries);
+ return ret;
+}
+
const vshCmdDef domManagementCmds[] = {
{.name = "attach-device",
.handler = cmdAttachDevice,
@@ -14425,5 +14537,11 @@ const vshCmdDef domManagementCmds[] = {
.info = info_domblkthreshold,
.flags = 0
},
+ {.name = "block-set-latency-histogram",
+ .handler = cmdBlockSetLatencyHistogram,
+ .opts = opts_block_set_latency_histogram,
+ .info = info_block_set_latency_histogram,
+ .flags = 0
+ },
{.name = NULL}
};
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 86c041d..faed047 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2988,6 +2988,24 @@ See B<vcpupin> for information on I<cpulist>.
Output the IP address and port number for the VNC display. If the information
is not available the processes will provide an exit code of 1.
+=item B<block-set-latency-histogram> I<domain> I<disk> [I<boundaries>]
+[I<--op> I<operation>]
+
+Configures latency histogram parameters for IO operation I<operation> for disk
+I<disk> and resets all histogram's bins to zero. I<operation> is one of
+C<read>, C<write> or C<flush>. If I<operation> is omitted then histograms for
+all operations will be configured. Histogram itself is available via
+B<domstats>.
+
+I<boundaries> is a comma separated list of histogram iterval boundaries in
+nanoseconds in acsending order. Boundaries 0 and +inf are implicit and should
+not be specified. For example "10, 50, 100" will configure histogram with
+intervals [0, 10), [10, 50), [50, 100) and [100, +inf).
+
+If both I<boundaries> and I<operation> are omitted then the histograms for all
+operations will be removed that is they will not be collected and will not be
+in the B<domstats> output.
+
=back
=head1 DEVICE COMMANDS
--
1.8.3.1
6 years, 3 months
[libvirt] [PATCH v7] qemu: Introduce state_lock_timeout to qemu.conf
by Yi Wang
When doing some job holding state lock for a long time,
we may come across error:
"Timed out during operation: cannot acquire state change lock"
Well, sometimes it's not a problem and users want to continue
to wait, and this patch allow users decide how long time they
can wait the state lock.
Signed-off-by: Yi Wang <wang.yi59(a)zte.com.cn>
Reviewed-by: Xi Xu <xu.xi8(a)zte.com.cn>
---
changes in v7:
- fix multiplication issue in BeginJobInternal
changes in v6:
- modify the description in qemu.conf
- move the multiplication to BeginJobInternal
changes in v5:
- adjust position of state lock in aug file
- fix state lock time got from conf file from milliseconds to
seconds
changes in v4:
- fix syntax-check error
changes in v3:
- add user-friendly description and nb of state lock
- check validity of stateLockTimeout
changes in v2:
- change default value to 30 in qemu.conf
- set the default value in virQEMUDriverConfigNew()
---
src/qemu/libvirtd_qemu.aug | 1 +
src/qemu/qemu.conf | 7 +++++++
src/qemu/qemu_conf.c | 14 ++++++++++++++
src/qemu/qemu_conf.h | 2 ++
src/qemu/qemu_domain.c | 5 +----
src/qemu/test_libvirtd_qemu.aug.in | 1 +
6 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug
index ddc4bbf..a5601e1 100644
--- a/src/qemu/libvirtd_qemu.aug
+++ b/src/qemu/libvirtd_qemu.aug
@@ -100,6 +100,7 @@ module Libvirtd_qemu =
| str_entry "lock_manager"
let rpc_entry = int_entry "max_queued"
+ | int_entry "state_lock_timeout"
| int_entry "keepalive_interval"
| int_entry "keepalive_count"
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index cd57b3c..f5e34f1 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -667,6 +667,13 @@
#
#max_queued = 0
+
+# It is strongly recommended to not touch this setting
+#
+# Default is 30
+#
+#state_lock_timeout = 60
+
###################################################################
# Keepalive protocol:
# This allows qemu driver to detect broken connections to remote
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index a4f545e..5be37dc 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -129,6 +129,9 @@ void qemuDomainCmdlineDefFree(qemuDomainCmdlineDefPtr def)
#endif
+/* Give up waiting for mutex after 30 seconds */
+#define QEMU_JOB_WAIT_TIME (30)
+
virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged)
{
virQEMUDriverConfigPtr cfg;
@@ -346,6 +349,8 @@ virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged)
cfg->glusterDebugLevel = 4;
cfg->stdioLogD = true;
+ cfg->stateLockTimeout = QEMU_JOB_WAIT_TIME;
+
if (!(cfg->namespaces = virBitmapNew(QEMU_DOMAIN_NS_LAST)))
goto error;
@@ -863,6 +868,9 @@ int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
if (virConfGetValueUInt(conf, "keepalive_count", &cfg->keepAliveCount) < 0)
goto cleanup;
+ if (virConfGetValueInt(conf, "state_lock_timeout", &cfg->stateLockTimeout) < 0)
+ goto cleanup;
+
if (virConfGetValueInt(conf, "seccomp_sandbox", &cfg->seccompSandbox) < 0)
goto cleanup;
@@ -1055,6 +1063,12 @@ virQEMUDriverConfigValidate(virQEMUDriverConfigPtr cfg)
return -1;
}
+ if (cfg->stateLockTimeout <= 0) {
+ virReportError(VIR_ERR_CONF_SYNTAX, "%s",
+ _("state_lock_timeout must be larger than zero"));
+ return -1;
+ }
+
return 0;
}
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index a8d84ef..97cf2e1 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -190,6 +190,8 @@ struct _virQEMUDriverConfig {
int keepAliveInterval;
unsigned int keepAliveCount;
+ int stateLockTimeout;
+
int seccompSandbox;
char *migrateHost;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 886e3fb..4dea85f 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -6652,9 +6652,6 @@ qemuDomainObjCanSetJob(qemuDomainObjPrivatePtr priv,
priv->job.agentActive == QEMU_AGENT_JOB_NONE));
}
-/* Give up waiting for mutex after 30 seconds */
-#define QEMU_JOB_WAIT_TIME (1000ull * 30)
-
/**
* qemuDomainObjBeginJobInternal:
* @driver: qemu driver
@@ -6714,7 +6711,7 @@ qemuDomainObjBeginJobInternal(virQEMUDriverPtr driver,
}
priv->jobs_queued++;
- then = now + QEMU_JOB_WAIT_TIME;
+ then = now + cfg->stateLockTimeout * 1000;
retry:
if ((!async && job != QEMU_JOB_DESTROY) &&
diff --git a/src/qemu/test_libvirtd_qemu.aug.in b/src/qemu/test_libvirtd_qemu.aug.in
index f1e8806..8e072d0 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -82,6 +82,7 @@ module Test_libvirtd_qemu =
{ "relaxed_acs_check" = "1" }
{ "lock_manager" = "lockd" }
{ "max_queued" = "0" }
+{ "state_lock_timeout" = "60" }
{ "keepalive_interval" = "5" }
{ "keepalive_count" = "5" }
{ "seccomp_sandbox" = "1" }
--
1.8.3.1
6 years, 3 months
[libvirt] [PATCH] tests: Follow up on qemucaps2xmldata rename
by Andrea Bolognani
The directory has been renamed in 562990849a9d, but a
reference to it was not updated at the same time, causing
'make dist' to fail ever since. Fix it.
Signed-off-by: Andrea Bolognani <abologna(a)redhat.com>
---
Pushed under the Pink Bunny Ears of Shame™ rule.
tests/Makefile.am | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 136fe16f71..51be1509e1 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -122,7 +122,7 @@ EXTRA_DIST = \
qemuargv2xmldata \
qemublocktestdata \
qemucapabilitiesdata \
- qemucaps2xmldata \
+ qemucaps2xmloutdata \
qemuhotplugtestcpus \
qemuhotplugtestdevices \
qemuhotplugtestdomains \
--
2.17.1
6 years, 3 months
[libvirt] [PATCH 0/5] qemu: Detect KVM usability correctly
by Andrea Bolognani
There are a few cases in which we're not reporting the correct
information through 'virsh capabilities', leading to applications
such as libguestfs attempting to launch KVM guests on a host that
doesn't actually support them.
Our code is also more complicated than it needs to be due to
backwards compatibilty reasons that we no longer care about these
days, so we can perform some cleanup there; there are further
cleanup opportunities in the same area, but some of them are a
bit tricky so I'll leave them for a follow-up series.
We also get some extra test coverage pretty much for free. Yay!
Andrea Bolognani (5):
tests: Reuse qemucapabilities data for qemucaps2xml
tests: Add more tests to qemucaps2xml
qemu: Drop QEMU_CAPS_ENABLE_KVM
qemu: Clarify QEMU_CAPS_KVM
qemu: Don't check for /dev/kvm presence
src/qemu/qemu_capabilities.c | 27 +---
src/qemu/qemu_capabilities.h | 4 +-
tests/qemucapabilitiestest.c | 1 +
tests/qemucaps2xmldata/all_1.6.0-1.caps | 129 ------------------
.../nodisksnapshot_1.6.0-1.caps | 128 -----------------
.../caps_1.5.3.x86_64.xml} | 12 +-
.../caps_1.6.0.x86_64.xml} | 14 +-
.../caps_1.7.0.x86_64.xml} | 12 +-
.../caps_2.1.1.x86_64.xml} | 12 +-
.../caps_2.10.0.aarch64.xml} | 13 +-
.../caps_2.10.0.ppc64.xml} | 14 +-
.../caps_2.10.0.s390x.xml} | 14 +-
.../caps_2.10.0.x86_64.xml} | 12 +-
.../caps_2.11.0.s390x.xml} | 14 +-
.../caps_2.11.0.x86_64.xml} | 12 +-
.../caps_2.12.0.aarch64.xml} | 13 +-
.../caps_2.12.0.ppc64.xml} | 14 +-
.../caps_2.12.0.s390x.xml} | 14 +-
.../caps_2.12.0.x86_64.xml} | 12 +-
.../caps_2.4.0.x86_64.xml} | 12 +-
.../caps_2.5.0.x86_64.xml} | 12 +-
.../caps_2.6.0.aarch64.xml} | 13 +-
.../caps_2.6.0.ppc64.xml} | 14 +-
.../caps_2.6.0.x86_64.xml} | 12 +-
.../caps_2.7.0.s390x.xml} | 14 +-
.../caps_2.7.0.x86_64.xml} | 12 +-
.../caps_2.8.0.s390x.xml} | 14 +-
.../caps_2.8.0.x86_64.xml} | 12 +-
.../caps_2.9.0.ppc64.xml} | 14 +-
.../caps_2.9.0.s390x.xml} | 14 +-
.../caps_2.9.0.x86_64.xml} | 12 +-
.../caps_3.0.0.ppc64.xml} | 14 +-
.../caps_3.0.0.riscv32.xml} | 13 +-
.../caps_3.0.0.riscv64.xml | 25 ++++
.../caps_3.0.0.x86_64.xml} | 12 +-
tests/qemucaps2xmltest.c | 63 +++++++--
tests/qemuxml2argvtest.c | 11 +-
37 files changed, 229 insertions(+), 535 deletions(-)
delete mode 100644 tests/qemucaps2xmldata/all_1.6.0-1.caps
delete mode 100644 tests/qemucaps2xmldata/nodisksnapshot_1.6.0-1.caps
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_1.5.3.x86_64.xml} (67%)
rename tests/{qemucaps2xmldata/nodisksnapshot_1.6.0-1.xml => qemucaps2xmloutdata/caps_1.6.0.x86_64.xml} (60%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_1.7.0.x86_64.xml} (67%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.1.1.x86_64.xml} (67%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.10.0.aarch64.xml} (62%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.10.0.ppc64.xml} (56%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.10.0.s390x.xml} (56%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.10.0.x86_64.xml} (67%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.11.0.s390x.xml} (56%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.11.0.x86_64.xml} (67%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.12.0.aarch64.xml} (62%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.12.0.ppc64.xml} (56%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.12.0.s390x.xml} (56%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.12.0.x86_64.xml} (67%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.4.0.x86_64.xml} (67%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.5.0.x86_64.xml} (67%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.6.0.aarch64.xml} (62%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.6.0.ppc64.xml} (56%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.6.0.x86_64.xml} (67%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.7.0.s390x.xml} (56%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.7.0.x86_64.xml} (67%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.8.0.s390x.xml} (56%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.8.0.x86_64.xml} (67%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.9.0.ppc64.xml} (56%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.9.0.s390x.xml} (56%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_2.9.0.x86_64.xml} (67%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_3.0.0.ppc64.xml} (56%)
copy tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_3.0.0.riscv32.xml} (54%)
create mode 100644 tests/qemucaps2xmloutdata/caps_3.0.0.riscv64.xml
rename tests/{qemucaps2xmldata/all_1.6.0-1.xml => qemucaps2xmloutdata/caps_3.0.0.x86_64.xml} (67%)
--
2.17.1
6 years, 3 months
[libvirt] [PATCHv2 0/6] Introduce syntax-check rule for incorrect indentation and blank first line in function body
by Shi Lei
v1 here:
https://www.redhat.com/archives/libvir-list/2018-September/msg00497.html
Diff from v1: (according to the comments from Jano)
- Change build-aux/check-spacing.pl rather than cfg.mk
- Don't exempt '/' (which matches comments in function) in the rule
- Split these two type of error messages and only output the relevant one
- Patch 2/4 of v1 divide into two patches by the type of error messages
Shi Lei (6):
build-aux:check-spacing.pl: Introduce syntax-check rule for incorrect
indentation and blank first line in function body
src: fix incorrect indentation in function body by checking first line
tests: fix incorrect indentation in function body by checking first
line
src: remove blank first line in function body
tests: remove blank first line in function body
tools: remove blank first line in function body
build-aux/check-spacing.pl | 22 +++++
src/bhyve/bhyve_command.c | 3 -
src/bhyve/bhyve_conf.c | 6 +-
src/bhyve/bhyve_driver.c | 33 ++++---
src/bhyve/bhyve_monitor.c | 1 -
src/bhyve/bhyve_process.c | 1 -
src/conf/cpu_conf.c | 1 -
src/conf/domain_capabilities.c | 1 -
src/conf/domain_conf.c | 12 +--
src/conf/network_conf.c | 2 -
src/cpu/cpu_s390.c | 84 ++++++++--------
src/cpu/cpu_x86.c | 1 -
src/esx/esx_vi_types.c | 2 +-
src/locking/lock_driver_nop.c | 1 -
src/network/bridge_driver.c | 1 -
src/network/bridge_driver_linux.c | 1 -
src/nwfilter/nwfilter_learnipaddr.c | 1 -
src/phyp/phyp_driver.c | 1 -
src/qemu/qemu_alias.c | 1 -
src/qemu/qemu_domain_address.c | 86 ++++++++---------
src/qemu/qemu_driver.c | 1 -
src/qemu/qemu_monitor.c | 1 -
src/qemu/qemu_monitor_json.c | 1 -
src/qemu/qemu_process.c | 1 -
src/storage/storage_backend_sheepdog.c | 3 -
src/storage/storage_driver.c | 1 -
src/storage/storage_util.c | 1 -
src/test/test_driver.c | 2 -
src/util/vircommand.c | 6 +-
src/util/virdnsmasq.c | 1 -
src/util/virfile.c | 1 -
src/util/virnetdev.c | 49 +++++-----
src/util/virnetdevmacvlan.c | 11 +--
src/util/virnetdevvportprofile.c | 2 +-
src/util/virstoragefile.c | 1 -
src/util/virutil.c | 3 +-
src/vbox/vbox_storage.c | 1 -
src/vbox/vbox_tmpl.c | 8 +-
src/vz/vz_driver.c | 1 -
src/vz/vz_sdk.c | 1 -
src/xenapi/xenapi_driver.c | 2 -
src/xenconfig/xen_common.c | 11 +--
tests/qemuxml2argvmock.c | 2 +-
tests/sexpr2xmltest.c | 44 ++++-----
tests/virnetdevmock.c | 1 -
tests/virnettlshelpers.c | 18 ++--
tests/virshtest.c | 128 ++++++++++++-------------
tests/vshtabletest.c | 3 -
tests/xml2sexprtest.c | 36 +++----
tools/virsh-volume.c | 1 -
tools/virt-admin.c | 1 -
51 files changed, 284 insertions(+), 320 deletions(-)
--
2.17.1
6 years, 3 months
[libvirt] [PATCH 0/5] Use memfd if possible
by marcandre.lureau@redhat.com
From: Marc-André Lureau <marcandre.lureau(a)redhat.com>
Hi,
This is an alternative to "[RFC v2 02/16] qemu: add memfd memory
backing", which added a new source type. Instead, Daniel suggested to
automatically use memfd for anonymous memory when available.
Marc-André Lureau (5):
qemu: add memory-backend-memfd capability check
qemu: check memory-backend-memfd.hugetlb capability
qemu: prefer memfd for anonymous memory
conf: drop hugepage non-anoymous memory requirement
tests: add qemuxml2argv memfd-memory-numa test
src/conf/domain_conf.c | 7 --
src/qemu/qemu_capabilities.c | 10 ++
src/qemu/qemu_capabilities.h | 2 +
src/qemu/qemu_command.c | 61 +++++++---
.../caps_2.12.0.aarch64.replies | 94 ++++++++++++---
.../caps_2.12.0.aarch64.xml | 4 +-
.../caps_2.12.0.ppc64.replies | 90 +++++++++++---
.../caps_2.12.0.ppc64.xml | 4 +-
.../caps_2.12.0.s390x.replies | 98 ++++++++++++----
.../caps_2.12.0.s390x.xml | 4 +-
.../caps_2.12.0.x86_64.replies | 110 +++++++++++++-----
.../caps_2.12.0.x86_64.xml | 4 +-
.../caps_3.0.0.ppc64.replies | 90 +++++++++++---
.../qemucapabilitiesdata/caps_3.0.0.ppc64.xml | 4 +-
.../caps_3.0.0.riscv32.replies | 86 +++++++++++---
.../caps_3.0.0.riscv32.xml | 2 +
.../caps_3.0.0.riscv64.replies | 86 +++++++++++---
.../caps_3.0.0.riscv64.xml | 2 +
.../caps_3.0.0.x86_64.replies | 110 +++++++++++++-----
.../caps_3.0.0.x86_64.xml | 4 +-
tests/qemuxml2argvdata/memfd-memory-numa.args | 28 +++++
tests/qemuxml2argvdata/memfd-memory-numa.xml | 36 ++++++
tests/qemuxml2argvtest.c | 5 +
23 files changed, 760 insertions(+), 181 deletions(-)
create mode 100644 tests/qemuxml2argvdata/memfd-memory-numa.args
create mode 100644 tests/qemuxml2argvdata/memfd-memory-numa.xml
--
2.19.0.rc1
6 years, 3 months
[libvirt] [PATCH v2 0/2] Fix issues in qemuARPGetInterfaces and virArpTableGet
by Lin Ma
v1 -> v2:
* Follow Chen Hanxiao's suggestion, Ignore 3 types of virtual interface backends
* Adjusted the commit messages of patch 1/2 to reflect the code changes.
Lin Ma (2):
qemu: Remove network type limitation for qemuARPGetInterfaces
virarptable: Return a virArpTablePtr when the nlmsghdr for loop is
over
src/qemu/qemu_driver.c | 4 +++-
src/util/virarptable.c | 2 ++
2 files changed, 5 insertions(+), 1 deletion(-)
--
2.15.1
6 years, 3 months
[libvirt] [PATCH] conf: Move more PCI functions out of device_conf
by Andrea Bolognani
Functions that deal with virPCIDeviceAddress exclusively
belong to util/virpci.
Signed-off-by: Andrea Bolognani <abologna(a)redhat.com>
---
src/conf/device_conf.c | 66 ----------------------------------------
src/conf/device_conf.h | 7 -----
src/libvirt_private.syms | 6 ++--
src/util/virpci.c | 65 +++++++++++++++++++++++++++++++++++++++
src/util/virpci.h | 7 +++++
5 files changed, 75 insertions(+), 76 deletions(-)
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index cbdfbf6ef4..98a419f40f 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -160,59 +160,6 @@ virDomainDeviceInfoAddressIsEqual(const virDomainDeviceInfo *a,
return true;
}
-bool
-virPCIDeviceAddressIsValid(virPCIDeviceAddressPtr addr,
- bool report)
-{
- if (addr->domain > 0xFFFF) {
- if (report)
- virReportError(VIR_ERR_XML_ERROR,
- _("Invalid PCI address domain='0x%x', "
- "must be <= 0xFFFF"),
- addr->domain);
- return false;
- }
- if (addr->bus > 0xFF) {
- if (report)
- virReportError(VIR_ERR_XML_ERROR,
- _("Invalid PCI address bus='0x%x', "
- "must be <= 0xFF"),
- addr->bus);
- return false;
- }
- if (addr->slot > 0x1F) {
- if (report)
- virReportError(VIR_ERR_XML_ERROR,
- _("Invalid PCI address slot='0x%x', "
- "must be <= 0x1F"),
- addr->slot);
- return false;
- }
- if (addr->function > 7) {
- if (report)
- virReportError(VIR_ERR_XML_ERROR,
- _("Invalid PCI address function=0x%x, "
- "must be <= 7"),
- addr->function);
- return false;
- }
- if (virPCIDeviceAddressIsEmpty(addr)) {
- if (report)
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("Invalid PCI address 0000:00:00, at least "
- "one of domain, bus, or slot must be > 0"));
- return false;
- }
- return true;
-}
-
-
-bool
-virPCIDeviceAddressIsEmpty(const virPCIDeviceAddress *addr)
-{
- return !(addr->domain || addr->bus || addr->slot);
-}
-
bool
virDeviceInfoPCIAddressIsWanted(const virDomainDeviceInfo *info)
{
@@ -309,19 +256,6 @@ virPCIDeviceAddressFormat(virBufferPtr buf,
return 0;
}
-bool
-virPCIDeviceAddressEqual(virPCIDeviceAddress *addr1,
- virPCIDeviceAddress *addr2)
-{
- if (addr1->domain == addr2->domain &&
- addr1->bus == addr2->bus &&
- addr1->slot == addr2->slot &&
- addr1->function == addr2->function) {
- return true;
- }
- return false;
-}
-
bool
virDomainDeviceCCWAddressIsValid(virDomainDeviceCCWAddressPtr addr)
{
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index 9f51118e29..407956bd02 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -191,10 +191,6 @@ bool virDomainDeviceInfoAddressIsEqual(const virDomainDeviceInfo *a,
bool virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
int type);
-bool virPCIDeviceAddressIsValid(virPCIDeviceAddressPtr addr,
- bool report);
-bool virPCIDeviceAddressIsEmpty(const virPCIDeviceAddress *addr);
-
bool virDeviceInfoPCIAddressIsWanted(const virDomainDeviceInfo *info);
bool virDeviceInfoPCIAddressIsPresent(const virDomainDeviceInfo *info);
@@ -205,9 +201,6 @@ int virPCIDeviceAddressFormat(virBufferPtr buf,
virPCIDeviceAddress addr,
bool includeTypeInAddr);
-bool virPCIDeviceAddressEqual(virPCIDeviceAddress *addr1,
- virPCIDeviceAddress *addr2);
-
bool virDomainDeviceCCWAddressIsValid(virDomainDeviceCCWAddressPtr addr);
int virDomainDeviceCCWAddressParseXML(xmlNodePtr node,
virDomainDeviceCCWAddressPtr addr);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index a0d229a79f..d6662d691d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -108,10 +108,7 @@ virDomainDeviceUSBAddressParseXML;
virDomainDeviceVirtioSerialAddressParseXML;
virInterfaceLinkFormat;
virInterfaceLinkParseXML;
-virPCIDeviceAddressEqual;
virPCIDeviceAddressFormat;
-virPCIDeviceAddressIsEmpty;
-virPCIDeviceAddressIsValid;
virPCIDeviceAddressParseXML;
@@ -2498,10 +2495,13 @@ virObjectUnref;
# util/virpci.h
virPCIDeviceAddressAsString;
+virPCIDeviceAddressEqual;
virPCIDeviceAddressGetIOMMUGroupAddresses;
virPCIDeviceAddressGetIOMMUGroupNum;
virPCIDeviceAddressGetSysfsFile;
virPCIDeviceAddressIOMMUGroupIterate;
+virPCIDeviceAddressIsEmpty;
+virPCIDeviceAddressIsValid;
virPCIDeviceAddressParse;
virPCIDeviceCopy;
virPCIDeviceDetach;
diff --git a/src/util/virpci.c b/src/util/virpci.c
index 1730d888f7..fb3f04fac3 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -1668,6 +1668,71 @@ virPCIDeviceReadID(virPCIDevicePtr dev, const char *id_name)
return id_str;
}
+bool
+virPCIDeviceAddressIsValid(virPCIDeviceAddressPtr addr,
+ bool report)
+{
+ if (addr->domain > 0xFFFF) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address domain='0x%x', "
+ "must be <= 0xFFFF"),
+ addr->domain);
+ return false;
+ }
+ if (addr->bus > 0xFF) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address bus='0x%x', "
+ "must be <= 0xFF"),
+ addr->bus);
+ return false;
+ }
+ if (addr->slot > 0x1F) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address slot='0x%x', "
+ "must be <= 0x1F"),
+ addr->slot);
+ return false;
+ }
+ if (addr->function > 7) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid PCI address function=0x%x, "
+ "must be <= 7"),
+ addr->function);
+ return false;
+ }
+ if (virPCIDeviceAddressIsEmpty(addr)) {
+ if (report)
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("Invalid PCI address 0000:00:00, at least "
+ "one of domain, bus, or slot must be > 0"));
+ return false;
+ }
+ return true;
+}
+
+bool
+virPCIDeviceAddressIsEmpty(const virPCIDeviceAddress *addr)
+{
+ return !(addr->domain || addr->bus || addr->slot);
+}
+
+bool
+virPCIDeviceAddressEqual(virPCIDeviceAddress *addr1,
+ virPCIDeviceAddress *addr2)
+{
+ if (addr1->domain == addr2->domain &&
+ addr1->bus == addr2->bus &&
+ addr1->slot == addr2->slot &&
+ addr1->function == addr2->function) {
+ return true;
+ }
+ return false;
+}
+
char *
virPCIDeviceAddressAsString(virPCIDeviceAddressPtr addr)
{
diff --git a/src/util/virpci.h b/src/util/virpci.h
index b4f72f8f06..16c2eded5e 100644
--- a/src/util/virpci.h
+++ b/src/util/virpci.h
@@ -218,6 +218,13 @@ int virPCIGetSysfsFile(char *virPCIDeviceName,
char **pci_sysfs_device_link)
ATTRIBUTE_RETURN_CHECK;
+bool virPCIDeviceAddressIsValid(virPCIDeviceAddressPtr addr,
+ bool report);
+bool virPCIDeviceAddressIsEmpty(const virPCIDeviceAddress *addr);
+
+bool virPCIDeviceAddressEqual(virPCIDeviceAddress *addr1,
+ virPCIDeviceAddress *addr2);
+
char *virPCIDeviceAddressAsString(virPCIDeviceAddressPtr addr)
ATTRIBUTE_NONNULL(1);
--
2.17.1
6 years, 3 months
[libvirt] [PATCH] libxl: remove configure check for libxl_domain_config_from_json
by Jim Fehlig
The libxl_domain_config_from_json API appeared in Xen 4.5, hence
there is no need to check for its existence after changing the
minimum supported Xen version to 4.6. Remove the check and its
use in the tests.
Signed-off-by: Jim Fehlig <jfehlig(a)suse.com>
---
m4/virt-driver-libxl.m4 | 7 -------
tests/libxlxml2domconfigtest.c | 4 ++--
2 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/m4/virt-driver-libxl.m4 b/m4/virt-driver-libxl.m4
index 902da11472..70c5c59e6a 100644
--- a/m4/virt-driver-libxl.m4
+++ b/m4/virt-driver-libxl.m4
@@ -56,13 +56,6 @@ AC_DEFUN([LIBVIRT_DRIVER_CHECK_LIBXL], [
],[
LIBXL_LIBS="$LIBXL_LIBS -lxenstore -lxenctrl"
])
-
- dnl Check if libxl_domain_config_from_json is available for domXML to
- dnl libxl_domain_config tests
- LIBS="$LIBS -lxenlight -lxenctrl"
- AC_CHECK_FUNCS([libxl_domain_config_from_json])
- CFLAGS="$old_CFLAGS"
- LIBS="$old_LIBS"
fi
AC_SUBST([LIBXL_CFLAGS])
diff --git a/tests/libxlxml2domconfigtest.c b/tests/libxlxml2domconfigtest.c
index b814461acc..eacf8f5615 100644
--- a/tests/libxlxml2domconfigtest.c
+++ b/tests/libxlxml2domconfigtest.c
@@ -33,7 +33,7 @@
#include "testutils.h"
-#if defined(WITH_LIBXL) && defined(WITH_YAJL) && defined(HAVE_LIBXL_DOMAIN_CONFIG_FROM_JSON)
+#if defined(WITH_LIBXL) && defined(WITH_YAJL)
# include "internal.h"
# include "viralloc.h"
@@ -228,4 +228,4 @@ int main(void)
return EXIT_AM_SKIP;
}
-#endif /* WITH_LIBXL && WITH_YAJL && HAVE_LIBXL_DOMAIN_CONFIG_FROM_JSON */
+#endif /* WITH_LIBXL && WITH_YAJL */
--
2.18.0
6 years, 3 months