Discussion:
[libvirt] [REPOST PATCH v2 02/12] qemu: Split qemuDomainGetIOThreadsLive
John Ferlan
2018-11-05 12:58:06 UTC
Permalink
Separate out the fetch of the IOThread monitor call into a separate
helper so that a subsequent domain statistics change can fetch the raw
IOThread data and parse it as it sees fit.

Signed-off-by: John Ferlan <***@redhat.com>
---
src/qemu/qemu_driver.c | 48 ++++++++++++++++++++++++++----------------
1 file changed, 30 insertions(+), 18 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a52e2495d5..e13633c1e0 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5486,39 +5486,52 @@ qemuDomainGetMaxVcpus(virDomainPtr dom)
VIR_DOMAIN_VCPU_MAXIMUM));
}

+
static int
-qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- virDomainIOThreadInfoPtr **info)
+qemuDomainGetIOThreadsMon(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuMonitorIOThreadInfoPtr **iothreads)
{
qemuDomainObjPrivatePtr priv;
- qemuMonitorIOThreadInfoPtr *iothreads = NULL;
- virDomainIOThreadInfoPtr *info_ret = NULL;
int niothreads = 0;
- size_t i;
- int ret = -1;
-
- if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
- goto cleanup;

if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("cannot list IOThreads for an inactive domain"));
- goto endjob;
+ return -1;
}

priv = vm->privateData;
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("IOThreads not supported with this binary"));
- goto endjob;
+ return -1;
}

qemuDomainObjEnterMonitor(driver, vm);
- niothreads = qemuMonitorGetIOThreads(priv->mon, &iothreads);
- if (qemuDomainObjExitMonitor(driver, vm) < 0)
- goto endjob;
- if (niothreads < 0)
+ niothreads = qemuMonitorGetIOThreads(priv->mon, iothreads);
+ if (qemuDomainObjExitMonitor(driver, vm) < 0 || niothreads < 0)
+ return -1;
+
+ return niothreads;
+}
+
+
+static int
+qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainIOThreadInfoPtr **info)
+{
+ qemuMonitorIOThreadInfoPtr *iothreads = NULL;
+ virDomainIOThreadInfoPtr *info_ret = NULL;
+ int niothreads = 0;
+ size_t i;
+ int ret = -1;
+
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+ goto cleanup;
+
+ if ((niothreads = qemuDomainGetIOThreadsMon(driver, vm, &iothreads)) < 0)
goto endjob;

/* Nothing to do */
@@ -5548,8 +5561,7 @@ qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
virBitmapFree(map);
}

- *info = info_ret;
- info_ret = NULL;
+ VIR_STEAL_PTR(*info, info_ret);
ret = niothreads;

endjob:
--
2.17.2
John Ferlan
2018-11-05 12:58:07 UTC
Permalink
Process the IOThreads polling stats if available. Generate the
output params record to be returned to the caller with the three
values - poll-max-ns, poll-grow, and poll-shrink.

Signed-off-by: John Ferlan <***@redhat.com>
---
include/libvirt/libvirt-domain.h | 1 +
src/libvirt-domain.c | 38 +++++++++++++++
src/qemu/qemu_driver.c | 81 ++++++++++++++++++++++++++++++++
3 files changed, 120 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index fdd2d6b8ea..58fd4bc10c 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -2048,6 +2048,7 @@ typedef enum {
VIR_DOMAIN_STATS_INTERFACE = (1 << 4), /* return domain interfaces info */
VIR_DOMAIN_STATS_BLOCK = (1 << 5), /* return domain block info */
VIR_DOMAIN_STATS_PERF = (1 << 6), /* return domain perf event info */
+ VIR_DOMAIN_STATS_IOTHREAD = (1 << 7), /* return iothread poll info */
} virDomainStatsTypes;

typedef enum {
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 7690339521..9fda56d660 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -11499,6 +11499,44 @@ virConnectGetDomainCapabilities(virConnectPtr conn,
* long long. It is produced by the
* emulation_faults perf event
*
+ * VIR_DOMAIN_STATS_IOTHREAD:
+ * Return IOThread statistics if available. IOThread polling is a
+ * timing mechanism that allows the hypervisor to generate a longer
+ * period of time in which the guest will perform operations on the
+ * CPU being used by the IOThread. The higher the value for poll-max-ns
+ * the longer the guest will keep the CPU. This may affect other host
+ * threads using the CPU. The poll-grow and poll-shrink values allow
+ * the hypervisor to generate a mechanism to add or remove polling time
+ * within the confines of 0 and poll-max-ns. For QEMU, the poll-grow is
+ * multiplied by the polling interval, while poll-shrink is used as a
+ * divisor. When not provided, QEMU may double the polling time until
+ * poll-max-ns is reached. When poll-shrink is 0 (zero) QEMU may reset
+ * the polling interval to 0 until it finds its "sweet spot". Setting
+ * poll-grow too large may cause frequent fluctution of the time; however,
+ * this can be tempered by a high poll-shrink to reduce the polling
+ * interval. For example, a poll-grow of 3 will triple the polling time
+ * which could quickly exceed poll-max-ns; however, a poll-shrink of
+ * 10 would cut that polling time more gradually.
+ *
+ * The typed parameter keys are in this format:
+ *
+ * "iothread.cnt" - maximum number of IOThreads in the subsequent list
+ * as unsigned int. Each IOThread in the list will
+ * will use it's iothread_id value as the <id>. There
+ * may be fewer <id> entries than the iothread.cnt
+ * value if the polling values are not supported.
+ * "iothread.<id>.poll-max-ns" - maximum polling time in ns as an unsigned
+ * long long. A 0 (zero) means polling is
+ * disabled.
+ * "iothread.<id>.poll-grow" - polling time factor as an unsigned int.
+ * A 0 (zero) indicates to allow the underlying
+ * hypervisor to choose how to grow the
+ * polling time.
+ * "iothread.<id>.poll-shrink" - polling time divisor as an unsigned int.
+ * A 0 (zero) indicates to allow the underlying
+ * hypervisor to choose how to shrink the
+ * polling time.
+ *
* Note that entire stats groups or individual stat fields may be missing from
* the output in case they are not supported by the given hypervisor, are not
* applicable for the current state of the guest domain, or their retrieval
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index e13633c1e0..b50d805bf1 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20437,6 +20437,86 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,

#undef QEMU_ADD_NAME_PARAM

+#define QEMU_ADD_IOTHREAD_PARAM_UI(record, maxparams, id, name, value) \
+ do { \
+ char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
+ snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
+ "iothread.%u.%s", id, name); \
+ if (virTypedParamsAddUInt(&(record)->params, \
+ &(record)->nparams, \
+ maxparams, \
+ param_name, \
+ value) < 0) \
+ goto cleanup; \
+ } while (0)
+
+#define QEMU_ADD_IOTHREAD_PARAM_ULL(record, maxparams, id, name, value) \
+do { \
+ char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
+ snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
+ "iothread.%u.%s", id, name); \
+ if (virTypedParamsAddULLong(&(record)->params, \
+ &(record)->nparams, \
+ maxparams, \
+ param_name, \
+ value) < 0) \
+ goto cleanup; \
+} while (0)
+
+static int
+qemuDomainGetStatsIOThread(virQEMUDriverPtr driver,
+ virDomainObjPtr dom,
+ virDomainStatsRecordPtr record,
+ int *maxparams,
+ unsigned int privflags ATTRIBUTE_UNUSED)
+{
+ size_t i;
+ qemuMonitorIOThreadInfoPtr *iothreads = NULL;
+ int niothreads;
+ int ret = -1;
+
+ if (!virDomainObjIsActive(dom))
+ return 0;
+
+ if ((niothreads = qemuDomainGetIOThreadsMon(driver, dom, &iothreads)) < 0)
+ return -1;
+
+ if (niothreads == 0)
+ return 0;
+
+ QEMU_ADD_COUNT_PARAM(record, maxparams, "iothread", niothreads);
+
+ for (i = 0; i < niothreads; i++) {
+ if (iothreads[i]->poll_valid) {
+ QEMU_ADD_IOTHREAD_PARAM_ULL(record, maxparams,
+ iothreads[i]->iothread_id,
+ "poll-max-ns",
+ iothreads[i]->poll_max_ns);
+ QEMU_ADD_IOTHREAD_PARAM_UI(record, maxparams,
+ iothreads[i]->iothread_id,
+ "poll-grow",
+ iothreads[i]->poll_grow);
+ QEMU_ADD_IOTHREAD_PARAM_UI(record, maxparams,
+ iothreads[i]->iothread_id,
+ "poll-shrink",
+ iothreads[i]->poll_shrink);
+ }
+ }
+
+ ret = 0;
+
+ cleanup:
+ for (i = 0; i < niothreads; i++)
+ VIR_FREE(iothreads[i]);
+ VIR_FREE(iothreads);
+
+ return ret;
+}
+
+#undef QEMU_ADD_IOTHREAD_PARAM_UI
+
+#undef QEMU_ADD_IOTHREAD_PARAM_ULL
+
#undef QEMU_ADD_COUNT_PARAM

static int
@@ -20511,6 +20591,7 @@ static struct qemuDomainGetStatsWorker qemuDomainGetStatsWorkers[] = {
{ qemuDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE, false },
{ qemuDomainGetStatsBlock, VIR_DOMAIN_STATS_BLOCK, true },
{ qemuDomainGetStatsPerf, VIR_DOMAIN_STATS_PERF, false },
+ { qemuDomainGetStatsIOThread, VIR_DOMAIN_STATS_IOTHREAD, true },
{ NULL, 0, false }
};
--
2.17.2
John Ferlan
2018-11-05 12:58:09 UTC
Permalink
Create a new API that will allow an adjustment of IOThread
polling parameters for the specified IOThread. These parameters
will not be saved in the guest XML. Currently the only parameters
supported will allow the hypervisor to adjust the parameters used
to limit and alter the scope of the polling interval. The polling
interval allows the IOThread to spend more or less time processing
in the guest.

Based on code originally posted by Pavel Hrdina <***@redhat.com>
to add virDomainAddIOThreadParams and virDomainModIOThreadParams.
Modification of those changes to use virDomainSetIOThreadParams
instead and remove concepts related to saving the data in guest
XML as well as the way to specifically enable the polling parameters.

Signed-off-by: John Ferlan <***@redhat.com>
ACKed-by: Michal Privoznik <***@redhat.com>
---
include/libvirt/libvirt-domain.h | 44 ++++++++++++++++++++
src/driver-hypervisor.h | 8 ++++
src/libvirt-domain.c | 70 ++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 5 +++
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 21 +++++++++-
src/remote_protocol-structs | 10 +++++
7 files changed, 158 insertions(+), 1 deletion(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 58fd4bc10c..bf89d0149f 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1911,6 +1911,50 @@ int virDomainDelIOThread(virDomainPtr domain,
unsigned int iothread_id,
unsigned int flags);

+/* IOThread set parameters */
+
+/**
+ * VIR_DOMAIN_IOTHREAD_POLL_MAX_NS:
+ *
+ * The maximum polling time that can be used by polling algorithm in ns.
+ * The polling time starts at 0 (zero) and is the time spent by the guest
+ * to process IOThread data before returning the CPU to the host. The
+ * polling time will be dynamically modified over time based on the
+ * poll_grow and poll_shrink parameters provided. A value set too large
+ * will cause more CPU time to be allocated the guest. A value set too
+ * small will not provide enough cycles for the guest to process data.
+ * The polling interval is not available for statistical purposes.
+ */
+# define VIR_DOMAIN_IOTHREAD_POLL_MAX_NS "poll_max_ns"
+
+/**
+ * VIR_DOMAIN_IOTHREAD_POLL_GROW:
+ *
+ * This provides a value for the dynamic polling adjustment algorithm to
+ * use to grow its polling interval up to the poll_max_ns value. A value
+ * of 0 (zero) allows the hypervisor to choose its own value. The algorithm
+ * to use for adjustment is hypervisor specific.
+ */
+# define VIR_DOMAIN_IOTHREAD_POLL_GROW "poll_grow"
+
+/**
+ * VIR_DOMAIN_IOTHREAD_POLL_SHRINK:
+ *
+ * This provides a value for the dynamic polling adjustment algorithm to
+ * use to shrink its polling interval when the polling interval exceeds
+ * the poll_max_ns value. A value of 0 (zero) allows the hypervisor to
+ * choose its own value. The algorithm to use for adjustment is hypervisor
+ * specific.
+ */
+# define VIR_DOMAIN_IOTHREAD_POLL_SHRINK "poll_shrink"
+
+int virDomainSetIOThreadParams(virDomainPtr domain,
+ unsigned int iothread_id,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags);
+
+
/**
* VIR_USE_CPU:
* @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN/OUT)
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index eef31eb1f0..6be3e175ce 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -406,6 +406,13 @@ typedef int
unsigned int iothread_id,
unsigned int flags);

+typedef int
+(*virDrvDomainSetIOThreadParams)(virDomainPtr domain,
+ unsigned int iothread_id,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags);
+
typedef int
(*virDrvDomainGetSecurityLabel)(virDomainPtr domain,
virSecurityLabelPtr seclabel);
@@ -1407,6 +1414,7 @@ struct _virHypervisorDriver {
virDrvDomainPinIOThread domainPinIOThread;
virDrvDomainAddIOThread domainAddIOThread;
virDrvDomainDelIOThread domainDelIOThread;
+ virDrvDomainSetIOThreadParams domainSetIOThreadParams;
virDrvDomainGetSecurityLabel domainGetSecurityLabel;
virDrvDomainGetSecurityLabelList domainGetSecurityLabelList;
virDrvNodeGetSecurityModel nodeGetSecurityModel;
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 9fda56d660..5b76458f11 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -7812,6 +7812,76 @@ virDomainDelIOThread(virDomainPtr domain,
}


+/**
+ * virDomainSetIOThreadParams:
+ * @domain: a domain object
+ * @iothread_id: the specific IOThread ID value to add
+ * @params: pointer to IOThread parameter objects
+ * @nparams: number of IOThread parameters
+ * @flags: bitwise-OR of virDomainModificationImpact and virTypedParameterFlags
+ *
+ * Dynamically set IOThread parameters to the domain. It is left up to
+ * the underlying virtual hypervisor to determine the valid range for an
+ * @iothread_id, determining whether the @iothread_id already exists, and
+ * determining the validity of the provided param values.
+ *
+ * See VIR_DOMAIN_IOTHREAD_* for detailed description of accepted IOThread
+ * parameters.
+ *
+ * Since the purpose of this API is to dynamically modify the IOThread
+ * @flags should only include the VIR_DOMAIN_AFFECT_CURRENT and/or
+ * VIR_DOMAIN_AFFECT_LIVE virDomainMemoryModFlags. Setting other flags
+ * may cause errors from the hypervisor.
+ *
+ * Note that this call can fail if the underlying virtualization hypervisor
+ * does not support it or does not support setting the provided values.
+ *
+ * This function requires privileged access to the hypervisor.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+int
+virDomainSetIOThreadParams(virDomainPtr domain,
+ unsigned int iothread_id,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags)
+{
+ virConnectPtr conn;
+
+ VIR_DOMAIN_DEBUG(domain, "iothread_id=%u, params=%p, nparams=%d, flags=0x%x",
+ iothread_id, params, nparams, flags);
+ VIR_TYPED_PARAMS_DEBUG(params, nparams);
+
+ virResetLastError();
+
+ virCheckDomainReturn(domain, -1);
+ conn = domain->conn;
+
+ virCheckReadOnlyGoto(conn->flags, error);
+ virCheckNonNullArgGoto(params, error);
+ virCheckPositiveArgGoto(nparams, error);
+
+ if (virTypedParameterValidateSet(conn, params, nparams) < 0)
+ goto error;
+
+ if (conn->driver->domainSetIOThreadParams) {
+ int ret;
+ ret = conn->driver->domainSetIOThreadParams(domain, iothread_id,
+ params, nparams, flags);
+ if (ret < 0)
+ goto error;
+ return ret;
+ }
+
+ virReportUnsupportedError();
+
+ error:
+ virDispatchError(domain->conn);
+ return -1;
+}
+
+
/**
* virDomainGetSecurityLabel:
* @domain: a domain object
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index d4cdbd8b32..042b4df043 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.10.0 {
+ global:
+ virDomainSetIOThreadParams;
+} LIBVIRT_4.5.0;
+
# .... define new API here using predicted next version number ....
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 3b43e219e5..dc61391553 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -8371,6 +8371,7 @@ static virHypervisorDriver hypervisor_driver = {
.domainPinIOThread = remoteDomainPinIOThread, /* 1.2.14 */
.domainAddIOThread = remoteDomainAddIOThread, /* 1.2.15 */
.domainDelIOThread = remoteDomainDelIOThread, /* 1.2.15 */
+ .domainSetIOThreadParams = remoteDomainSetIOThreadParams, /* 4.10.0 */
.domainGetSecurityLabel = remoteDomainGetSecurityLabel, /* 0.6.1 */
.domainGetSecurityLabelList = remoteDomainGetSecurityLabelList, /* 0.10.0 */
.nodeGetSecurityModel = remoteNodeGetSecurityModel, /* 0.6.1 */
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 28c8febabd..7630b2ed15 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -256,6 +256,9 @@ const REMOTE_DOMAIN_IP_ADDR_MAX = 2048;
/* Upper limit on number of guest vcpu information entries */
const REMOTE_DOMAIN_GUEST_VCPU_PARAMS_MAX = 64;

+/* Upper limit on number of IOThread parameter set entries */
+const REMOTE_DOMAIN_IOTHREAD_PARAMS_MAX = 64;
+
/* Upper limit on number of SEV parameters */
const REMOTE_NODE_SEV_INFO_MAX = 64;

@@ -1249,6 +1252,13 @@ struct remote_domain_del_iothread_args {
unsigned int flags;
};

+struct remote_domain_set_iothread_params_args {
+ remote_nonnull_domain dom;
+ unsigned int iothread_id;
+ remote_typed_param params<REMOTE_DOMAIN_IOTHREAD_PARAMS_MAX>;
+ unsigned int flags;
+};
+
struct remote_domain_get_security_label_args {
remote_nonnull_domain dom;
};
@@ -6312,5 +6322,14 @@ 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: both
+ * @acl: domain:write
+ * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE
+ * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG
+ */
+ REMOTE_PROC_DOMAIN_SET_IOTHREAD_PARAMS = 402
+
};
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 6343e14638..7c27c63542 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -866,6 +866,15 @@ struct remote_domain_del_iothread_args {
u_int iothread_id;
u_int flags;
};
+struct remote_domain_set_iothread_params_args {
+ remote_nonnull_domain dom;
+ u_int iothread_id;
+ struct {
+ u_int params_len;
+ remote_typed_param * params_val;
+ } params;
+ u_int flags;
+};
struct remote_domain_get_security_label_args {
remote_nonnull_domain dom;
};
@@ -3368,4 +3377,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_IOTHREAD_PARAMS = 402,
};
--
2.17.2
Michal Privoznik
2018-11-15 09:55:20 UTC
Permalink
Post by John Ferlan
Create a new API that will allow an adjustment of IOThread
polling parameters for the specified IOThread. These parameters
will not be saved in the guest XML. Currently the only parameters
supported will allow the hypervisor to adjust the parameters used
to limit and alter the scope of the polling interval. The polling
interval allows the IOThread to spend more or less time processing
in the guest.
to add virDomainAddIOThreadParams and virDomainModIOThreadParams.
Modification of those changes to use virDomainSetIOThreadParams
instead and remove concepts related to saving the data in guest
XML as well as the way to specifically enable the polling parameters.
---
include/libvirt/libvirt-domain.h | 44 ++++++++++++++++++++
src/driver-hypervisor.h | 8 ++++
src/libvirt-domain.c | 70 ++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 5 +++
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 21 +++++++++-
src/remote_protocol-structs | 10 +++++
7 files changed, 158 insertions(+), 1 deletion(-)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 58fd4bc10c..bf89d0149f 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1911,6 +1911,50 @@ int virDomainDelIOThread(virDomainPtr domain,
unsigned int iothread_id,
unsigned int flags);
+/* IOThread set parameters */
+
+/**
+ *
+ * The maximum polling time that can be used by polling algorithm in ns.
+ * The polling time starts at 0 (zero) and is the time spent by the guest
+ * to process IOThread data before returning the CPU to the host. The
+ * polling time will be dynamically modified over time based on the
+ * poll_grow and poll_shrink parameters provided. A value set too large
+ * will cause more CPU time to be allocated the guest. A value set too
+ * small will not provide enough cycles for the guest to process data.
+ * The polling interval is not available for statistical purposes.
+ */
+# define VIR_DOMAIN_IOTHREAD_POLL_MAX_NS "poll_max_ns"
+
+/**
+ *
+ * This provides a value for the dynamic polling adjustment algorithm to
+ * use to grow its polling interval up to the poll_max_ns value. A value
+ * of 0 (zero) allows the hypervisor to choose its own value. The algorithm
+ * to use for adjustment is hypervisor specific.
+ */
+# define VIR_DOMAIN_IOTHREAD_POLL_GROW "poll_grow"
+
+/**
+ *
+ * This provides a value for the dynamic polling adjustment algorithm to
+ * use to shrink its polling interval when the polling interval exceeds
+ * the poll_max_ns value. A value of 0 (zero) allows the hypervisor to
+ * choose its own value. The algorithm to use for adjustment is hypervisor
+ * specific.
+ */
+# define VIR_DOMAIN_IOTHREAD_POLL_SHRINK "poll_shrink"
+
+int virDomainSetIOThreadParams(virDomainPtr domain,
On a completely unrelated note, this is stupid. I mean the amount of
spaces after 'int'. I wonder if a patch that reformats all the header
files would be accepted.

The ACK still holds.
Post by John Ferlan
+ unsigned int iothread_id,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags);
Michal
John Ferlan
2018-11-15 20:19:35 UTC
Permalink
Post by Michal Privoznik
Post by John Ferlan
Create a new API that will allow an adjustment of IOThread
polling parameters for the specified IOThread. These parameters
will not be saved in the guest XML. Currently the only parameters
supported will allow the hypervisor to adjust the parameters used
to limit and alter the scope of the polling interval. The polling
interval allows the IOThread to spend more or less time processing
in the guest.
to add virDomainAddIOThreadParams and virDomainModIOThreadParams.
Modification of those changes to use virDomainSetIOThreadParams
instead and remove concepts related to saving the data in guest
XML as well as the way to specifically enable the polling parameters.
---
include/libvirt/libvirt-domain.h | 44 ++++++++++++++++++++
src/driver-hypervisor.h | 8 ++++
src/libvirt-domain.c | 70 ++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 5 +++
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 21 +++++++++-
src/remote_protocol-structs | 10 +++++
7 files changed, 158 insertions(+), 1 deletion(-)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 58fd4bc10c..bf89d0149f 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -1911,6 +1911,50 @@ int virDomainDelIOThread(virDomainPtr domain,
unsigned int iothread_id,
unsigned int flags);
+/* IOThread set parameters */
+
+/**
+ *
+ * The maximum polling time that can be used by polling algorithm in ns.
+ * The polling time starts at 0 (zero) and is the time spent by the guest
+ * to process IOThread data before returning the CPU to the host. The
+ * polling time will be dynamically modified over time based on the
+ * poll_grow and poll_shrink parameters provided. A value set too large
+ * will cause more CPU time to be allocated the guest. A value set too
+ * small will not provide enough cycles for the guest to process data.
+ * The polling interval is not available for statistical purposes.
+ */
+# define VIR_DOMAIN_IOTHREAD_POLL_MAX_NS "poll_max_ns"
+
+/**
+ *
+ * This provides a value for the dynamic polling adjustment algorithm to
+ * use to grow its polling interval up to the poll_max_ns value. A value
+ * of 0 (zero) allows the hypervisor to choose its own value. The algorithm
+ * to use for adjustment is hypervisor specific.
+ */
+# define VIR_DOMAIN_IOTHREAD_POLL_GROW "poll_grow"
+
+/**
+ *
+ * This provides a value for the dynamic polling adjustment algorithm to
+ * use to shrink its polling interval when the polling interval exceeds
+ * the poll_max_ns value. A value of 0 (zero) allows the hypervisor to
+ * choose its own value. The algorithm to use for adjustment is hypervisor
+ * specific.
+ */
+# define VIR_DOMAIN_IOTHREAD_POLL_SHRINK "poll_shrink"
+
+int virDomainSetIOThreadParams(virDomainPtr domain,
On a completely unrelated note, this is stupid. I mean the amount of
spaces after 'int'. I wonder if a patch that reformats all the header
files would be accepted.
I agree with the spacing... I assumed it had something to do with the
docs pages generation; however, a quick test shows that by removing the
extraneous spaces doesn't change the format that I can see in the docs.
Furthermore there are other API's which don't do any spacing.

So perhaps a nice task for a first time contributor to remove the spaces
*and* make sure that it doesn't affect the webpage.

Tks -

John

Since it'll conflict - I'll wait for you to push the 'memfd' stuff first
w/ capabilities changes before pushing this... but don't wait too long ;-)
Post by Michal Privoznik
The ACK still holds.
Post by John Ferlan
+ unsigned int iothread_id,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags);
Michal
John Ferlan
2018-11-05 12:58:15 UTC
Permalink
Add a command to allow for setting various dynamic IOThread polling
interval scope (poll-max-ns, poll-grow, and poll-shrink). Describe
the values in the virsh.pod in as generic terms as possible. The
more specific QEMU algorithm has been divulged in the previous patch.

Based heavily on code originally posted by Pavel Hrdina
<***@redhat.com>, but altered to only provide one command
and to not managed a poll disabled state.

Signed-off-by: John Ferlan <***@redhat.com>
---
tools/virsh-domain.c | 110 +++++++++++++++++++++++++++++++++++++++++++
tools/virsh.pod | 21 +++++++++
2 files changed, 131 insertions(+)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 372bdb95d3..4ee6ddf956 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -7734,6 +7734,110 @@ cmdIOThreadAdd(vshControl *ctl, const vshCmd *cmd)
return ret;
}

+
+ /*
+ * "iothreadset" command
+ */
+static const vshCmdInfo info_iothreadset[] = {
+ {.name = "help",
+ .data = N_("modifies an existing IOThread of the guest domain")
+ },
+ {.name = "desc",
+ .data = N_("Modifies an existing IOThread of the guest domain.")
+ },
+ {.name = NULL}
+};
+
+static const vshCmdOptDef opts_iothreadset[] = {
+ VIRSH_COMMON_OPT_DOMAIN_FULL(0),
+ {.name = "id",
+ .type = VSH_OT_INT,
+ .flags = VSH_OFLAG_REQ,
+ .help = N_("iothread id of existing IOThread")
+ },
+ {.name = "poll-max-ns",
+ .type = VSH_OT_INT,
+ .help = N_("set the maximum IOThread polling time in ns")
+ },
+ {.name = "poll-grow",
+ .type = VSH_OT_INT,
+ .help = N_("set the value to increase the IOThread polling time")
+ },
+ {.name = "poll-shrink",
+ .type = VSH_OT_INT,
+ .help = N_("set the value for reduction of the IOThread polling time ")
+ },
+ VIRSH_COMMON_OPT_DOMAIN_LIVE,
+ VIRSH_COMMON_OPT_DOMAIN_CURRENT,
+ {.name = NULL}
+};
+
+static bool
+cmdIOThreadSet(vshControl *ctl, const vshCmd *cmd)
+{
+ virDomainPtr dom;
+ int id = 0;
+ bool ret = false;
+ bool live = vshCommandOptBool(cmd, "live");
+ unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+ virTypedParameterPtr params = NULL;
+ int nparams = 0;
+ int maxparams = 0;
+ unsigned long long poll_max;
+ unsigned int poll_val;
+ int rc;
+
+ if (live)
+ flags |= VIR_DOMAIN_AFFECT_LIVE;
+
+ if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+ return false;
+
+ if (vshCommandOptInt(ctl, cmd, "id", &id) < 0)
+ goto cleanup;
+ if (id <= 0) {
+ vshError(ctl, _("Invalid IOThread id value: '%d'"), id);
+ goto cleanup;
+ }
+
+ poll_val = 0;
+ if ((rc = vshCommandOptULongLong(ctl, cmd, "poll-max-ns", &poll_max)) < 0)
+ goto cleanup;
+ if (rc > 0 && virTypedParamsAddULLong(&params, &nparams, &maxparams,
+ VIR_DOMAIN_IOTHREAD_POLL_MAX_NS,
+ poll_max) < 0)
+ goto save_error;
+
+#define VSH_IOTHREAD_SET_UINT_PARAMS(opt, param) \
+ poll_val = 0; \
+ if ((rc = vshCommandOptUInt(ctl, cmd, opt, &poll_val)) < 0) \
+ goto cleanup; \
+ if (rc > 0 && \
+ virTypedParamsAddUInt(&params, &nparams, &maxparams, \
+ param, poll_val) < 0) \
+ goto save_error;
+
+ VSH_IOTHREAD_SET_UINT_PARAMS("poll-grow", VIR_DOMAIN_IOTHREAD_POLL_GROW)
+ VSH_IOTHREAD_SET_UINT_PARAMS("poll-shrink", VIR_DOMAIN_IOTHREAD_POLL_SHRINK)
+
+#undef VSH_IOTHREAD_SET_UINT_PARAMS
+
+ if (virDomainSetIOThreadParams(dom, id, params, nparams, flags) < 0)
+ goto cleanup;
+
+ ret = true;
+
+ cleanup:
+ virTypedParamsFree(params, nparams);
+ virshDomainFree(dom);
+ return ret;
+
+ save_error:
+ vshSaveLibvirtError();
+ goto cleanup;
+}
+
+
/*
* "iothreaddel" command
*/
@@ -14149,6 +14253,12 @@ const vshCmdDef domManagementCmds[] = {
.info = info_iothreadadd,
.flags = 0
},
+ {.name = "iothreadset",
+ .handler = cmdIOThreadSet,
+ .opts = opts_iothreadset,
+ .info = info_iothreadset,
+ .flags = 0
+ },
{.name = "iothreaddel",
.handler = cmdIOThreadDel,
.opts = opts_iothreaddel,
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 90f3c1ef5c..48766567f8 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -1732,6 +1732,27 @@ If I<--config> is specified, affect the next boot of a persistent guest.
If I<--current> is specified or I<--live> and I<--config> are not specified,
affect the current guest state.

+=item B<iothreadset> I<domain> I<iothread_id>
+[[I<--poll-max-ns> B<ns>] [I<--poll-grow> B<factor>]
+[I<--poll-shrink> B<divisor>]]
+[[I<--config>] [I<--live>] | [I<--current>]]
+
+Modifies an existing iothread of the domain using the specified
+I<iothread_id>. The I<--poll-max-ns> provides the maximum polling
+interval to be allowed for an IOThread in ns. If a 0 (zero) is provided,
+then polling for the IOThread is disabled. The I<--poll-grow> is the
+factor by which the current polling time will be adjusted in order to
+reach the maximum polling time. If a 0 (zero) is provided, then the
+default factor will be used. The I<--poll-shrink> is the quotient
+by which the current polling time will be reduced in order to get
+below the maximum polling interval. If a 0 (zero) is provided, then
+the default quotient will be used.
+
+If I<--live> is specified, affect a running guest. If the guest is not
+running an error is returned.
+If I<--current> is specified or I<--live> is not specified, then handle
+as if I<--live> was specified.
+
=item B<iothreaddel> I<domain> I<iothread_id>
[[I<--config>] [I<--live>] | [I<--current>]]
--
2.17.2
John Ferlan
2018-11-05 12:58:16 UTC
Permalink
Signed-off-by: John Ferlan <***@redhat.com>
---
docs/news.xml | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/docs/news.xml b/docs/news.xml
index 9d98c34df2..c7c101fd47 100644
--- a/docs/news.xml
+++ b/docs/news.xml
@@ -35,6 +35,19 @@
<libvirt>
<release version="v4.10.0" date="unreleased">
<section title="New features">
+ <change>
+ <summary>
+ Support changing IOThread polling parameters for a live guest
+ </summary>
+ <description>
+ Introduced virDomainSetIOThreadParams which allows dynamically
+ setting the IOThread polling parameters used by QEMU to manage
+ the thread polling interval and the algorithm for growth or
+ shrink of the polling time. The values only affect a running
+ guest with IOThreads. The guest's IOThread polling values can
+ be viewed via the domain statistics.
+ </description>
+ </change>
</section>
<section title="Improvements">
</section>
--
2.17.2
John Ferlan
2018-11-05 12:58:05 UTC
Permalink
If there are IOThread polling values in the query-iothreads return
buffer, then fill them in and set a bool indicating their presence.
This will allow for displaying in a domain stats output eventually.

Note that the QEMU values are managed a bit differently (as int's
stored in int64_t's) than we will manage them (as unsigned long and
int values). This is intentional to allow for value validation
checking when it comes time to provide the values to QEMU.

Signed-off-by: John Ferlan <***@redhat.com>
ACKed-by: Michal Privoznik <***@redhat.com>
---
src/qemu/qemu_monitor.h | 4 ++++
src/qemu/qemu_monitor_json.c | 15 +++++++++++++++
2 files changed, 19 insertions(+)

diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 48b142a4f4..c2991e2b16 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1116,6 +1116,10 @@ typedef qemuMonitorIOThreadInfo *qemuMonitorIOThreadInfoPtr;
struct _qemuMonitorIOThreadInfo {
unsigned int iothread_id;
int thread_id;
+ bool poll_valid;
+ unsigned long long poll_max_ns;
+ unsigned int poll_grow;
+ unsigned int poll_shrink;
};
int qemuMonitorGetIOThreads(qemuMonitorPtr mon,
qemuMonitorIOThreadInfoPtr **iothreads);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 3de298c9e2..2e92984b44 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -7441,6 +7441,21 @@ qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon,
"'thread-id' data"));
goto cleanup;
}
+
+ /* Fetch poll values (since QEMU 2.9 ) if available. QEMU
+ * stores these values as int64_t's; however, the qapi type
+ * is an int. The qapi/misc.json also mis-describes the grow
+ * and shrink values as pure add/remove values. The source
+ * util/aio-posix.c function aio_poll uses them as a factor
+ * or divisor in it's calculation. We will fetch and store
+ * them as defined in our structures. */
+ if (virJSONValueObjectGetNumberUlong(child, "poll-max-ns",
+ &info->poll_max_ns) == 0 &&
+ virJSONValueObjectGetNumberUint(child, "poll-grow",
+ &info->poll_grow) == 0 &&
+ virJSONValueObjectGetNumberUint(child, "poll-shrink",
+ &info->poll_shrink) == 0)
+ info->poll_valid = true;
}

ret = n;
--
2.17.2
John Ferlan
2018-11-05 12:58:08 UTC
Permalink
Add an --iothread qualifier to domstats and an explanation in
the man page. Describe the values in as generic terms as possible
allowing each hypervisor to provide a specific algorithm to utilize
the values as it sees fit.

Signed-off-by: John Ferlan <***@redhat.com>
ACKed-by: Michal Privoznik <***@redhat.com>
---
tools/virsh-domain-monitor.c | 7 +++++++
tools/virsh.pod | 26 ++++++++++++++++++++++++--
2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c
index 3a2636377d..5187c1e248 100644
--- a/tools/virsh-domain-monitor.c
+++ b/tools/virsh-domain-monitor.c
@@ -2066,6 +2066,10 @@ static const vshCmdOptDef opts_domstats[] = {
.type = VSH_OT_BOOL,
.help = N_("report domain perf event statistics"),
},
+ {.name = "iothread",
+ .type = VSH_OT_BOOL,
+ .help = N_("report domain IOThread information"),
+ },
{.name = "list-active",
.type = VSH_OT_BOOL,
.help = N_("list only active domains"),
@@ -2179,6 +2183,9 @@ cmdDomstats(vshControl *ctl, const vshCmd *cmd)
if (vshCommandOptBool(cmd, "perf"))
stats |= VIR_DOMAIN_STATS_PERF;

+ if (vshCommandOptBool(cmd, "iothread"))
+ stats |= VIR_DOMAIN_STATS_IOTHREAD;
+
if (vshCommandOptBool(cmd, "list-active"))
flags |= VIR_CONNECT_GET_ALL_DOMAINS_STATS_ACTIVE;

diff --git a/tools/virsh.pod b/tools/virsh.pod
index 86c041d575..90f3c1ef5c 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -975,7 +975,8 @@ or unique source names printed by this command.

=item B<domstats> [I<--raw>] [I<--enforce>] [I<--backing>] [I<--nowait>]
[I<--state>] [I<--cpu-total>] [I<--balloon>] [I<--vcpu>] [I<--interface>]
-[I<--block>] [I<--perf>] [[I<--list-active>] [I<--list-inactive>]
+[I<--block>] [I<--perf>] [I<--iothread>]
+[[I<--list-active>] [I<--list-inactive>]
[I<--list-persistent>] [I<--list-transient>] [I<--list-running>]
[I<--list-paused>] [I<--list-shutoff>] [I<--list-other>]] | [I<domain> ...]

@@ -993,7 +994,7 @@ behavior use the I<--raw> flag.
The individual statistics groups are selectable via specific flags. By
default all supported statistics groups are returned. Supported
statistics groups flags are: I<--state>, I<--cpu-total>, I<--balloon>,
-I<--vcpu>, I<--interface>, I<--block>, I<--perf>.
+I<--vcpu>, I<--interface>, I<--block>, I<--perf>, I<--iothread>.

Note that - depending on the hypervisor type and version or the domain state
- not all of the following statistics may be returned.
@@ -1126,6 +1127,27 @@ Information listed includes:
VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD event
See domblkthreshold.

+I<--iothread> returns information about IOThreads on the running guest
+if supported by the hypervisor.
+
+The "poll-max-ns" for each thread is the maximum nanoseconds to allow
+each polling interval to occur. A polling interval is a period of time
+allowed for a thread to process data before being the guest gives up
+its CPU quantum back to the host. A value set too small will not allow
+the IOThread to run long enough on a CPU to process data. A value set
+too high will consume too much CPU time per IOThread failing to allow
+other threads running on the CPU to get time. The polling interval is
+not available for statistical purposes.
+
+ "iothread.<id>.poll-max-ns" - maximum polling time in nanoseconds used
+ by the <id> IOThread. A value of 0 (zero)
+ indicates polling is disabled.
+ "iothread.<id>.poll-grow" - polling time grow value. A value of 0 (zero)
+ indicates growth is managed by the hypervisor.
+ "iothread.<id>.poll-shrink" - polling time shrink value. A value of
+ 0 (zero) indicates shrink is managed by
+ the hypervisor.
+
Selecting a specific statistics groups doesn't guarantee that the
daemon supports the selected group of stats. Flag I<--enforce>
forces the command to fail if the daemon doesn't support the
--
2.17.2
John Ferlan
2018-11-05 12:58:13 UTC
Permalink
Add a capability check for IOThread polling (all were added at the
same time, so only one check is necessary).

Based on code originally posted by Pavel Hrdina <***@redhat.com>
with the only changes to include the more recent QEMU releases.

Signed-off-by: John Ferlan <***@redhat.com>
ACKed-by: Michal Privoznik <***@redhat.com>
---
src/qemu/qemu_capabilities.c | 2 ++
src/qemu/qemu_capabilities.h | 1 +
tests/qemucapabilitiesdata/caps_2.10.0.aarch64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml | 1 +
tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml | 1 +
tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.12.0.aarch64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.12.0.ppc64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml | 1 +
tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.9.0.ppc64.xml | 1 +
tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml | 1 +
tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 1 +
tests/qemucapabilitiesdata/caps_3.0.0.ppc64.xml | 1 +
tests/qemucapabilitiesdata/caps_3.0.0.riscv32.xml | 1 +
tests/qemucapabilitiesdata/caps_3.0.0.riscv64.xml | 1 +
tests/qemucapabilitiesdata/caps_3.0.0.s390x.xml | 1 +
tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml | 1 +
20 files changed, 21 insertions(+)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 2ca5af3297..4fdb0e66a5 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -509,6 +509,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"vfio-pci.display",
"blockdev",
"vfio-ap",
+ "iothread.poll-max-ns",
);


@@ -1239,6 +1240,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsQMPSchemaQueries[] = {
{ "nbd-server-start/arg-type/tls-creds", QEMU_CAPS_NBD_TLS },
{ "screendump/arg-type/device", QEMU_CAPS_SCREENDUMP_DEVICE },
{ "block-commit/arg-type/*top", QEMU_CAPS_ACTIVE_COMMIT },
+ { "query-iothreads/ret-type/poll-max-ns", QEMU_CAPS_IOTHREAD_POLLING },
};

typedef struct _virQEMUCapsObjectTypeProps virQEMUCapsObjectTypeProps;
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 6bb9a2c8f0..f53288bc81 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -493,6 +493,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
QEMU_CAPS_VFIO_PCI_DISPLAY, /* -device vfio-pci.display */
QEMU_CAPS_BLOCKDEV, /* -blockdev and blockdev-add are supported */
QEMU_CAPS_DEVICE_VFIO_AP, /* -device vfio-ap */
+ QEMU_CAPS_IOTHREAD_POLLING, /* -object iothread.poll-max-ns */

QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.10.0.aarch64.xml
index b9c4182a66..7061ba8f7e 100644
--- a/tests/qemucapabilitiesdata/caps_2.10.0.aarch64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.10.0.aarch64.xml
@@ -151,6 +151,7 @@
<flag name='blockdev-del'/>
<flag name='vhost-vsock'/>
<flag name='egl-headless'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2010000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>305067</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml
index 66b25601e7..2a48b63efe 100644
--- a/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml
@@ -150,6 +150,7 @@
<flag name='blockdev-del'/>
<flag name='vhost-vsock'/>
<flag name='egl-headless'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2010000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>384412</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml
index e000aac384..c35e014b32 100644
--- a/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml
@@ -113,6 +113,7 @@
<flag name='blockdev-del'/>
<flag name='vhost-vsock'/>
<flag name='egl-headless'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2010000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>306247</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
index ebc5e771d9..a8d787f99a 100644
--- a/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
@@ -192,6 +192,7 @@
<flag name='vhost-vsock'/>
<flag name='mch'/>
<flag name='egl-headless'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2010000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>364386</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml
index 4eb8a39d94..6ee53a1f21 100644
--- a/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml
@@ -120,6 +120,7 @@
<flag name='vhost-vsock'/>
<flag name='tpm-emulator'/>
<flag name='egl-headless'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2011000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>345099</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml
index 857a9a9f9a..4ba2a82b60 100644
--- a/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml
@@ -198,6 +198,7 @@
<flag name='mch'/>
<flag name='mch.extended-tseg-mbytes'/>
<flag name='egl-headless'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2011000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>368875</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.12.0.aarch64.xml
index 7bf1fab8cb..c7e62d3723 100644
--- a/tests/qemucapabilitiesdata/caps_2.12.0.aarch64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.12.0.aarch64.xml
@@ -162,6 +162,7 @@
<flag name='tpm-emulator'/>
<flag name='egl-headless'/>
<flag name='vfio-pci.display'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2011090</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>344910</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_2.12.0.ppc64.xml
index 8b8d8859c1..391c83eaaa 100644
--- a/tests/qemucapabilitiesdata/caps_2.12.0.ppc64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.12.0.ppc64.xml
@@ -160,6 +160,7 @@
<flag name='machine.pseries.cap-htm'/>
<flag name='egl-headless'/>
<flag name='vfio-pci.display'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2011090</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>425694</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml
index 79320d5229..1e09f24c31 100644
--- a/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml
@@ -128,6 +128,7 @@
<flag name='tpm-emulator'/>
<flag name='egl-headless'/>
<flag name='vfio-pci.display'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2012000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>374287</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
index fcf94ab720..407c6e63cc 100644
--- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
@@ -203,6 +203,7 @@
<flag name='sev-guest'/>
<flag name='egl-headless'/>
<flag name='vfio-pci.display'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2011090</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>413556</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.ppc64.xml
index f97ebdb9d4..d9ca8f3d2b 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.ppc64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.ppc64.xml
@@ -142,6 +142,7 @@
<flag name='hda-output'/>
<flag name='blockdev-del'/>
<flag name='vhost-vsock'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2009000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>349056</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
index 5a4371ab83..a789403ca6 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
@@ -107,6 +107,7 @@
<flag name='sdl-gl'/>
<flag name='blockdev-del'/>
<flag name='vhost-vsock'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2009000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>267973</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
index 7bf31d9fd5..3c26b381da 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
@@ -186,6 +186,7 @@
<flag name='vmgenid'/>
<flag name='vhost-vsock'/>
<flag name='mch'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2009000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>340375</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.ppc64.xml b/tests/qemucapabilitiesdata/caps_3.0.0.ppc64.xml
index a1e2ae6556..6aad2e0feb 100644
--- a/tests/qemucapabilitiesdata/caps_3.0.0.ppc64.xml
+++ b/tests/qemucapabilitiesdata/caps_3.0.0.ppc64.xml
@@ -160,6 +160,7 @@
<flag name='machine.pseries.cap-htm'/>
<flag name='egl-headless'/>
<flag name='vfio-pci.display'/>
+ <flag name='iothread.poll-max-ns'/>
<version>2012050</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>444131</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.riscv32.xml b/tests/qemucapabilitiesdata/caps_3.0.0.riscv32.xml
index 254a4cf3d8..231213ae3a 100644
--- a/tests/qemucapabilitiesdata/caps_3.0.0.riscv32.xml
+++ b/tests/qemucapabilitiesdata/caps_3.0.0.riscv32.xml
@@ -100,6 +100,7 @@
<flag name='chardev-fd-pass'/>
<flag name='tpm-emulator'/>
<flag name='egl-headless'/>
+ <flag name='iothread.poll-max-ns'/>
<version>3000000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>0</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.riscv64.xml b/tests/qemucapabilitiesdata/caps_3.0.0.riscv64.xml
index e7ab79e006..1722876dcc 100644
--- a/tests/qemucapabilitiesdata/caps_3.0.0.riscv64.xml
+++ b/tests/qemucapabilitiesdata/caps_3.0.0.riscv64.xml
@@ -100,6 +100,7 @@
<flag name='chardev-fd-pass'/>
<flag name='tpm-emulator'/>
<flag name='egl-headless'/>
+ <flag name='iothread.poll-max-ns'/>
<version>3000000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>0</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.s390x.xml b/tests/qemucapabilitiesdata/caps_3.0.0.s390x.xml
index 3b5f9818a5..b77e95510f 100644
--- a/tests/qemucapabilitiesdata/caps_3.0.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_3.0.0.s390x.xml
@@ -130,6 +130,7 @@
<flag name='tpm-emulator'/>
<flag name='egl-headless'/>
<flag name='vfio-pci.display'/>
+ <flag name='iothread.poll-max-ns'/>
<version>3000000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>387601</microcodeVersion>
diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
index 7ceea6b738..acfb1d45d2 100644
--- a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
@@ -205,6 +205,7 @@
<flag name='usb-storage.werror'/>
<flag name='egl-headless'/>
<flag name='vfio-pci.display'/>
+ <flag name='iothread.poll-max-ns'/>
<version>3000000</version>
<kvmVersion>0</kvmVersion>
<microcodeVersion>425157</microcodeVersion>
--
2.17.2
John Ferlan
2018-11-05 12:58:10 UTC
Permalink
Add functions to set the IOThreadInfo param data for the live guest.
Modify the _qemuMonitorIOThreadInfo to have a flag to indicate when
a value was set so that we don't set a value unless it was desired
to be set.

Based on code originally posted by Pavel Hrdina <***@redhat.com>,
but extracted into a separate patch. Note that qapi expects to receive
integer parameters rather than unsigned long long or unsigned int's.
QEMU does save the value in larger signed 64 bit values eventually.

Signed-off-by: John Ferlan <***@redhat.com>
---
src/qemu/qemu_monitor.c | 19 +++++++++++++++++++
src/qemu/qemu_monitor.h | 5 +++++
src/qemu/qemu_monitor_json.c | 35 +++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 4 ++++
4 files changed, 63 insertions(+)

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 7f7013e115..a65d638ab8 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4135,6 +4135,25 @@ qemuMonitorGetIOThreads(qemuMonitorPtr mon,
}


+/**
+ * qemuMonitorSetIOThread:
+ * @mon: Pointer to the monitor
+ * @iothreadInfo: filled IOThread info with data
+ *
+ * Alter the specified IOThread's IOThreadInfo values.
+ */
+int
+qemuMonitorSetIOThread(qemuMonitorPtr mon,
+ qemuMonitorIOThreadInfoPtr iothreadInfo)
+{
+ VIR_DEBUG("iothread=%p", iothreadInfo);
+
+ QEMU_CHECK_MONITOR(mon);
+
+ return qemuMonitorJSONSetIOThread(mon, iothreadInfo);
+}
+
+
/**
* qemuMonitorGetMemoryDeviceInfo:
* @mon: pointer to the monitor
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index c2991e2b16..66bfdb0e5c 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1120,9 +1120,14 @@ struct _qemuMonitorIOThreadInfo {
unsigned long long poll_max_ns;
unsigned int poll_grow;
unsigned int poll_shrink;
+ bool set_poll_max_ns;
+ bool set_poll_grow;
+ bool set_poll_shrink;
};
int qemuMonitorGetIOThreads(qemuMonitorPtr mon,
qemuMonitorIOThreadInfoPtr **iothreads);
+int qemuMonitorSetIOThread(qemuMonitorPtr mon,
+ qemuMonitorIOThreadInfoPtr iothreadInfo);

typedef struct _qemuMonitorMemoryDeviceInfo qemuMonitorMemoryDeviceInfo;
typedef qemuMonitorMemoryDeviceInfo *qemuMonitorMemoryDeviceInfoPtr;
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 2e92984b44..5a806f6c0e 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -7474,6 +7474,41 @@ qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon,
}


+int
+qemuMonitorJSONSetIOThread(qemuMonitorPtr mon,
+ qemuMonitorIOThreadInfoPtr iothreadInfo)
+{
+ int ret = -1;
+ char *path = NULL;
+ qemuMonitorJSONObjectProperty prop;
+
+ if (virAsprintf(&path, "/objects/iothread%u",
+ iothreadInfo->iothread_id) < 0)
+ goto cleanup;
+
+#define VIR_IOTHREAD_SET_PROP(propName, propVal) \
+ if (iothreadInfo->set_##propVal) { \
+ memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty)); \
+ prop.type = QEMU_MONITOR_OBJECT_PROPERTY_INT; \
+ prop.val.iv = iothreadInfo->propVal; \
+ if (qemuMonitorJSONSetObjectProperty(mon, path, propName, &prop) < 0) \
+ goto cleanup; \
+ }
+
+ VIR_IOTHREAD_SET_PROP("poll-max-ns", poll_max_ns);
+ VIR_IOTHREAD_SET_PROP("poll-grow", poll_grow);
+ VIR_IOTHREAD_SET_PROP("poll-shrink", poll_shrink);
+
+#undef VIR_IOTHREAD_SET_PROP
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(path);
+ return ret;
+}
+
+
int
qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
virHashTablePtr info)
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index da267b15b0..c3abd0ddf0 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -502,6 +502,10 @@ int qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon,
qemuMonitorIOThreadInfoPtr **iothreads)
ATTRIBUTE_NONNULL(2);

+int qemuMonitorJSONSetIOThread(qemuMonitorPtr mon,
+ qemuMonitorIOThreadInfoPtr iothreadInfo)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
int qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
virHashTablePtr info)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
--
2.17.2
John Ferlan
2018-11-05 12:58:11 UTC
Permalink
We're about to add a new state "modify" and thus the function
goes from just Add/Del. Use an enum to manage.

Extracted from code originally posted by Pavel Hrdina
<***@redhat.com>, but placed into a separate patch.

Signed-off-by: John Ferlan <***@redhat.com>
ACKed-by: Michal Privoznik <***@redhat.com>
---
src/qemu/qemu_driver.c | 32 +++++++++++++++++++++++++-------
1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b50d805bf1..6835d3e875 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6018,11 +6018,16 @@ qemuDomainDelIOThreadCheck(virDomainDefPtr def,
return 0;
}

+typedef enum {
+ VIR_DOMAIN_IOTHREAD_ACTION_ADD,
+ VIR_DOMAIN_IOTHREAD_ACTION_DEL,
+} virDomainIOThreadAction;
+
static int
qemuDomainChgIOThread(virQEMUDriverPtr driver,
virDomainObjPtr vm,
unsigned int iothread_id,
- bool add,
+ virDomainIOThreadAction action,
unsigned int flags)
{
virQEMUDriverConfigPtr cfg = NULL;
@@ -6048,18 +6053,24 @@ qemuDomainChgIOThread(virQEMUDriverPtr driver,
goto endjob;
}

- if (add) {
+ switch (action) {
+ case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
if (qemuDomainAddIOThreadCheck(def, iothread_id) < 0)
goto endjob;

if (qemuDomainHotplugAddIOThread(driver, vm, iothread_id) < 0)
goto endjob;
- } else {
+
+ break;
+
+ case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
if (qemuDomainDelIOThreadCheck(def, iothread_id) < 0)
goto endjob;

if (qemuDomainHotplugDelIOThread(driver, vm, iothread_id) < 0)
goto endjob;
+
+ break;
}

if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
@@ -6067,18 +6078,23 @@ qemuDomainChgIOThread(virQEMUDriverPtr driver,
}

if (persistentDef) {
- if (add) {
+ switch (action) {
+ case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
if (qemuDomainAddIOThreadCheck(persistentDef, iothread_id) < 0)
goto endjob;

if (!virDomainIOThreadIDAdd(persistentDef, iothread_id))
goto endjob;

- } else {
+ break;
+
+ case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
if (qemuDomainDelIOThreadCheck(persistentDef, iothread_id) < 0)
goto endjob;

virDomainIOThreadIDDel(persistentDef, iothread_id);
+
+ break;
}

if (virDomainSaveConfig(cfg->configDir, driver->caps,
@@ -6120,7 +6136,8 @@ qemuDomainAddIOThread(virDomainPtr dom,
if (virDomainAddIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;

- ret = qemuDomainChgIOThread(driver, vm, iothread_id, true, flags);
+ ret = qemuDomainChgIOThread(driver, vm, iothread_id,
+ VIR_DOMAIN_IOTHREAD_ACTION_ADD, flags);

cleanup:
virDomainObjEndAPI(&vm);
@@ -6152,7 +6169,8 @@ qemuDomainDelIOThread(virDomainPtr dom,
if (virDomainDelIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;

- ret = qemuDomainChgIOThread(driver, vm, iothread_id, false, flags);
+ ret = qemuDomainChgIOThread(driver, vm, iothread_id,
+ VIR_DOMAIN_IOTHREAD_ACTION_DEL, flags);

cleanup:
virDomainObjEndAPI(&vm);
--
2.17.2
John Ferlan
2018-11-05 12:58:12 UTC
Permalink
Rather than passing an iothread_id, let's pass a qemuMonitorIOThreadInfo
structure so that a subsequent change to modify the iothread info can
just generate and pass one.

Signed-off-by: John Ferlan <***@redhat.com>
ACKed-by: Michal Privoznik <***@redhat.com>
---
src/qemu/qemu_driver.c | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 6835d3e875..4ddca2f765 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -6026,7 +6026,7 @@ typedef enum {
static int
qemuDomainChgIOThread(virQEMUDriverPtr driver,
virDomainObjPtr vm,
- unsigned int iothread_id,
+ qemuMonitorIOThreadInfo iothread,
virDomainIOThreadAction action,
unsigned int flags)
{
@@ -6055,19 +6055,19 @@ qemuDomainChgIOThread(virQEMUDriverPtr driver,

switch (action) {
case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
- if (qemuDomainAddIOThreadCheck(def, iothread_id) < 0)
+ if (qemuDomainAddIOThreadCheck(def, iothread.iothread_id) < 0)
goto endjob;

- if (qemuDomainHotplugAddIOThread(driver, vm, iothread_id) < 0)
+ if (qemuDomainHotplugAddIOThread(driver, vm, iothread.iothread_id) < 0)
goto endjob;

break;

case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
- if (qemuDomainDelIOThreadCheck(def, iothread_id) < 0)
+ if (qemuDomainDelIOThreadCheck(def, iothread.iothread_id) < 0)
goto endjob;

- if (qemuDomainHotplugDelIOThread(driver, vm, iothread_id) < 0)
+ if (qemuDomainHotplugDelIOThread(driver, vm, iothread.iothread_id) < 0)
goto endjob;

break;
@@ -6080,19 +6080,19 @@ qemuDomainChgIOThread(virQEMUDriverPtr driver,
if (persistentDef) {
switch (action) {
case VIR_DOMAIN_IOTHREAD_ACTION_ADD:
- if (qemuDomainAddIOThreadCheck(persistentDef, iothread_id) < 0)
+ if (qemuDomainAddIOThreadCheck(persistentDef, iothread.iothread_id) < 0)
goto endjob;

- if (!virDomainIOThreadIDAdd(persistentDef, iothread_id))
+ if (!virDomainIOThreadIDAdd(persistentDef, iothread.iothread_id))
goto endjob;

break;

case VIR_DOMAIN_IOTHREAD_ACTION_DEL:
- if (qemuDomainDelIOThreadCheck(persistentDef, iothread_id) < 0)
+ if (qemuDomainDelIOThreadCheck(persistentDef, iothread.iothread_id) < 0)
goto endjob;

- virDomainIOThreadIDDel(persistentDef, iothread_id);
+ virDomainIOThreadIDDel(persistentDef, iothread.iothread_id);

break;
}
@@ -6119,6 +6119,7 @@ qemuDomainAddIOThread(virDomainPtr dom,
{
virQEMUDriverPtr driver = dom->conn->privateData;
virDomainObjPtr vm = NULL;
+ qemuMonitorIOThreadInfo iothread = {0};
int ret = -1;

virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
@@ -6136,7 +6137,8 @@ qemuDomainAddIOThread(virDomainPtr dom,
if (virDomainAddIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;

- ret = qemuDomainChgIOThread(driver, vm, iothread_id,
+ iothread.iothread_id = iothread_id;
+ ret = qemuDomainChgIOThread(driver, vm, iothread,
VIR_DOMAIN_IOTHREAD_ACTION_ADD, flags);

cleanup:
@@ -6152,6 +6154,7 @@ qemuDomainDelIOThread(virDomainPtr dom,
{
virQEMUDriverPtr driver = dom->conn->privateData;
virDomainObjPtr vm = NULL;
+ qemuMonitorIOThreadInfo iothread = {0};
int ret = -1;

virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
@@ -6169,7 +6172,8 @@ qemuDomainDelIOThread(virDomainPtr dom,
if (virDomainDelIOThreadEnsureACL(dom->conn, vm->def, flags) < 0)
goto cleanup;

- ret = qemuDomainChgIOThread(driver, vm, iothread_id,
+ iothread.iothread_id = iothread_id;
+ ret = qemuDomainChgIOThread(driver, vm, iothread,
VIR_DOMAIN_IOTHREAD_ACTION_DEL, flags);

cleanup:
--
2.17.2
John Ferlan
2018-11-05 12:58:14 UTC
Permalink
https://bugzilla.redhat.com/show_bug.cgi?id=1545732

Implement the QEMU driver mechanism in order to set the polling
parameters for an IOThread within the bounds specified by the
QEMU qapi parameter passing.

Based heavily on patches originally posted by Pavel Hrdina
<***@redhat.com>, but modified to only handle alterations
for a running guest. For the most part the API names changed,
the typed parameters removed the poll enabled value, and the
capabilities check was moved to just before the live attempt
to set. Since changes are only supported for a running guest,
no guest XML alterations were kept.

Signed-off-by: John Ferlan <***@redhat.com>
---
src/qemu/qemu_driver.c | 201 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 201 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 4ddca2f765..61b1ce717c 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5902,6 +5902,35 @@ qemuDomainHotplugAddIOThread(virQEMUDriverPtr driver,
goto cleanup;
}

+
+static int
+qemuDomainHotplugModIOThread(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuMonitorIOThreadInfo iothread)
+{
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ int rc;
+
+ if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_IOTHREAD_POLLING)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("IOThreads polling is not supported for this QEMU"));
+ return -1;
+ }
+
+ qemuDomainObjEnterMonitor(driver, vm);
+
+ rc = qemuMonitorSetIOThread(priv->mon, &iothread);
+
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ return -1;
+
+ if (rc < 0)
+ return -1;
+
+ return 0;
+}
+
+
static int
qemuDomainHotplugDelIOThread(virQEMUDriverPtr driver,
virDomainObjPtr vm,
@@ -6018,9 +6047,106 @@ qemuDomainDelIOThreadCheck(virDomainDefPtr def,
return 0;
}

+
+/**
+ * @params: Pointer to params list
+ * @nparams: Number of params to be parsed
+ * @iothread: Buffer to store the values
+ *
+ * The following is a description of each value parsed:
+ *
+ * - "poll-max-ns" for each IOThread is the maximum time in nanoseconds
+ * to allow each polling interval to occur. A polling interval is a
+ * period of time allowed for a thread to process data before it returns
+ * the CPU quantum back to the host. A value set too small will not allow
+ * the IOThread to run long enough on a CPU to process data. A value set
+ * too high will consume too much CPU time per IOThread failing to allow
+ * other threads running on the CPU to get time. A value of 0 (zero) will
+ * disable the polling.
+ *
+ * - "poll-grow" - factor to grow the current polling time when deemed
+ * necessary. If a 0 (zero) value is provided, QEMU currently doubles
+ * its polling interval unless the current value is greater than the
+ * poll-max-ns.
+ *
+ * - "poll-shrink" - divisor to reduced the current polling time when deemed
+ * necessary. If a 0 (zero) value is provided, QEMU resets the polling
+ * interval to 0 (zero) allowing the poll-grow to manipulate the time.
+ *
+ * QEMU keeps track of the polling time elapsed and may grow or shrink the
+ * its polling interval based upon its heuristic algorithm. It is possible
+ * that calculations determine that it has found a "sweet spot" and no
+ * ajustments are made. The polling time value is not available.
+ *
+ * Returns 0 on success, -1 on failure with error set.
+ */
+static int
+qemuDomainIOThreadParseParams(virTypedParameterPtr params,
+ int nparams,
+ qemuMonitorIOThreadInfoPtr iothread)
+{
+ int rc;
+
+ if (virTypedParamsValidate(params, nparams,
+ VIR_DOMAIN_IOTHREAD_POLL_MAX_NS,
+ VIR_TYPED_PARAM_ULLONG,
+ VIR_DOMAIN_IOTHREAD_POLL_GROW,
+ VIR_TYPED_PARAM_UINT,
+ VIR_DOMAIN_IOTHREAD_POLL_SHRINK,
+ VIR_TYPED_PARAM_UINT,
+ NULL) < 0)
+ return -1;
+
+ if ((rc = virTypedParamsGetULLong(params, nparams,
+ VIR_DOMAIN_IOTHREAD_POLL_MAX_NS,
+ &iothread->poll_max_ns)) < 0)
+ return -1;
+ if (rc == 1)
+ iothread->set_poll_max_ns = true;
+
+ if ((rc = virTypedParamsGetUInt(params, nparams,
+ VIR_DOMAIN_IOTHREAD_POLL_GROW,
+ &iothread->poll_grow)) < 0)
+ return -1;
+ if (rc == 1)
+ iothread->set_poll_grow = true;
+
+ if ((rc = virTypedParamsGetUInt(params, nparams,
+ VIR_DOMAIN_IOTHREAD_POLL_SHRINK,
+ &iothread->poll_shrink)) < 0)
+ return -1;
+ if (rc == 1)
+ iothread->set_poll_shrink = true;
+
+ if (iothread->set_poll_max_ns && iothread->poll_max_ns > INT_MAX) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("poll-max-ns (%llu) must be less than or equal to %d"),
+ iothread->poll_max_ns, INT_MAX);
+ return -1;
+ }
+
+ if (iothread->set_poll_grow && iothread->poll_grow > INT_MAX) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("poll-grow (%u) must be less than or equal to %d"),
+ iothread->poll_grow, INT_MAX);
+ return -1;
+ }
+
+ if (iothread->set_poll_shrink && iothread->poll_shrink > INT_MAX) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("poll-shrink (%u) must be less than or equal to %d"),
+ iothread->poll_shrink, INT_MAX);
+ return -1;
+ }
+
+ return 0;
+}
+
+
typedef enum {
VIR_DOMAIN_IOTHREAD_ACTION_ADD,
VIR_DOMAIN_IOTHREAD_ACTION_DEL,
+ VIR_DOMAIN_IOTHREAD_ACTION_MOD,
} virDomainIOThreadAction;

static int
@@ -6071,6 +6197,20 @@ qemuDomainChgIOThread(virQEMUDriverPtr driver,
goto endjob;

break;
+
+ case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
+ if (!(virDomainIOThreadIDFind(def, iothread.iothread_id))) {
+ virReportError(VIR_ERR_INVALID_ARG,
+ _("cannot find IOThread '%u' in iothreadids"),
+ iothread.iothread_id);
+ goto endjob;
+ }
+
+ if (qemuDomainHotplugModIOThread(driver, vm, iothread) < 0)
+ goto endjob;
+
+ break;
+
}

if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0)
@@ -6094,6 +6234,14 @@ qemuDomainChgIOThread(virQEMUDriverPtr driver,

virDomainIOThreadIDDel(persistentDef, iothread.iothread_id);

+ break;
+
+ case VIR_DOMAIN_IOTHREAD_ACTION_MOD:
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("configuring persistent polling values is "
+ "not supported"));
+ goto endjob;
+
break;
}

@@ -6181,6 +6329,58 @@ qemuDomainDelIOThread(virDomainPtr dom,
return ret;
}

+
+/**
+ * @dom: Domain to set IOThread params
+ * @iothread_id: IOThread 'id' that will be modified
+ * @params: List of parameters to change
+ * @nparams: Number of parameters in the list
+ * @flags: Flags for the set (only supports live alteration)
+ *
+ * Alter the specified @iothread_id with the values provided.
+ *
+ * Returs 0 on success, -1 on failure
+ */
+static int
+qemuDomainSetIOThreadParams(virDomainPtr dom,
+ unsigned int iothread_id,
+ virTypedParameterPtr params,
+ int nparams,
+ unsigned int flags)
+{
+ virQEMUDriverPtr driver = dom->conn->privateData;
+ virDomainObjPtr vm = NULL;
+ qemuMonitorIOThreadInfo iothread = {0};
+ int ret = -1;
+
+ virCheckFlags(VIR_DOMAIN_AFFECT_LIVE, -1);
+
+ if (iothread_id == 0) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("invalid value of 0 for iothread_id"));
+ goto cleanup;
+ }
+
+ iothread.iothread_id = iothread_id;
+
+ if (!(vm = qemuDomObjFromDomain(dom)))
+ goto cleanup;
+
+ if (virDomainSetIOThreadParamsEnsureACL(dom->conn, vm->def, flags) < 0)
+ goto cleanup;
+
+ if (qemuDomainIOThreadParseParams(params, nparams, &iothread) < 0)
+ goto cleanup;
+
+ ret = qemuDomainChgIOThread(driver, vm, iothread,
+ VIR_DOMAIN_IOTHREAD_ACTION_MOD, flags);
+
+ cleanup:
+ virDomainObjEndAPI(&vm);
+ return ret;
+}
+
+
static int qemuDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
{
virQEMUDriverPtr driver = dom->conn->privateData;
@@ -21964,6 +22164,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
.domainPinIOThread = qemuDomainPinIOThread, /* 1.2.14 */
.domainAddIOThread = qemuDomainAddIOThread, /* 1.2.15 */
.domainDelIOThread = qemuDomainDelIOThread, /* 1.2.15 */
+ .domainSetIOThreadParams = qemuDomainSetIOThreadParams, /* 4.10.0 */
.domainGetSecurityLabel = qemuDomainGetSecurityLabel, /* 0.6.1 */
.domainGetSecurityLabelList = qemuDomainGetSecurityLabelList, /* 0.10.0 */
.nodeGetSecurityModel = qemuNodeGetSecurityModel, /* 0.6.1 */
--
2.17.2
Christian Borntraeger
2018-11-05 13:18:47 UTC
Permalink
v2: https://www.redhat.com/archives/libvir-list/2018-October/msg01065.html
NB: Minor mods for this are change using 4.10.0 instead of 4.9.0, merge of
qemu_capabilities conflict, and updated news.xml
v1: https://www.redhat.com/archives/libvir-list/2018-October/msg00456.html
Changes since v1 (from code review)
Patch 2: Move the job back into qemuDomainGetIOThreadsLive
Patch 3: Add check for ActiveJob before allowing, use true for
*StatsWorker, and print 'iothread' in output not 'block'
Patch 5: Use virCheckPositiveArgGoto(nparams, error) instead of using
virCheckNonNegativeArgGoto(nparams, error). And then remove
the if (nparams) before the virCheckNonNullArgGoto(params, error);
Patch 6: Add ability to determine which parameter was set via bool
set_poll_{max_ns|grow|shrink} values. Then use those in
the macro that sets the value to determine whether or not
the value will be set based on whether it was changed.
Patch 10: Use bool's to set_ when the value is found in the incoming
params list. Remove the check that says poll_max_ns needs
to be set. Testing proves that if it's set to 0, then the
grow and shrink values can be changed (although they do
nothing)
Patch 12: (NEW) - News article
This series attempts to resurrect the concept of being able to modify
the IOThread polling parameters; however, in a slightly different
manner than the previous series posted by posted by Pavel Hrdina
https://www.redhat.com/archives/libvir-list/2017-February/msg01047.html
https://bugzilla.redhat.com/show_bug.cgi?id=1545732
to provide some way to modify the paremters without needing to supply
QEMU command line pass through values.
It's accepted that the values being changed are fairly or extremely
low level type knobs; however, it's also shown that by being able to
turn the knob it is possible for certain, specific appliances to be
able to gain a performance benefit for the thread at the expense of
other competing threads.
Unlike the previous series, this series does not attempt to save the
polling values in the guest XML. Rather, it only modifies the live
guest's IOThread with new values. It also doesn't provide the polling
values in a virsh iothread* command, rather it uses the domstats
in order to fetch and display the values. The theory being this
leaves the onus on the higher level appliance/application to provide
the "proper guidance" and "concerns" related to changing the values
to the consumer. Not saving the values means whatever values that
are chosen do not "live" in perpetuity. Once the guest is shut down
or the IOThread removed from guest, the hypervisor default values
take over again. Perhaps not a perfect situation in terms of what
the bz requests; however, storage of default values that could
cause performance issues is not an optimal situation. So this I
figured is a "comprimise" of sorts.
If it's still felt that no we don't want to do this, then fine,
but please in doing so own the bz, state your case, and close it.
I'm 50/50 on it, but figured at least I'd present this option and
see what the concensus was.
qemu: Check for and return IOThread polling values if available
qemu: Split qemuDomainGetIOThreadsLive
qemu: Implement the ability to return IOThread stats
virsh: Add ability to display IOThread stats
lib: Introduce virDomainSetIOThreadParams
qemu: Add monitor functions to set IOThread params
qemu: Alter qemuDomainChgIOThread to take enum instead of bool
qemu: Alter qemuDomainChgIOThread to take qemuMonitorIOThreadInfo
qemu: Detect whether iothread polling is supported
qemu: Introduce qemuDomainSetIOThreadParams
tools: Add virsh iothreadset command
docs: Add news article for IOThread polling
For the feature itself consider the patch series
Acked-by: Christian Borntraeger <***@de.ibm.com>

I always wanted this kind of control.
docs/news.xml | 13 +
include/libvirt/libvirt-domain.h | 45 ++
src/driver-hypervisor.h | 8 +
src/libvirt-domain.c | 108 +++++
src/libvirt_public.syms | 5 +
src/qemu/qemu_capabilities.c | 2 +
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_driver.c | 384 ++++++++++++++++--
src/qemu/qemu_monitor.c | 19 +
src/qemu/qemu_monitor.h | 9 +
src/qemu/qemu_monitor_json.c | 50 +++
src/qemu/qemu_monitor_json.h | 4 +
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 21 +-
src/remote_protocol-structs | 10 +
.../caps_2.10.0.aarch64.xml | 1 +
.../caps_2.10.0.ppc64.xml | 1 +
.../caps_2.10.0.s390x.xml | 1 +
.../caps_2.10.0.x86_64.xml | 1 +
.../caps_2.11.0.s390x.xml | 1 +
.../caps_2.11.0.x86_64.xml | 1 +
.../caps_2.12.0.aarch64.xml | 1 +
.../caps_2.12.0.ppc64.xml | 1 +
.../caps_2.12.0.s390x.xml | 1 +
.../caps_2.12.0.x86_64.xml | 1 +
.../qemucapabilitiesdata/caps_2.9.0.ppc64.xml | 1 +
.../qemucapabilitiesdata/caps_2.9.0.s390x.xml | 1 +
.../caps_2.9.0.x86_64.xml | 1 +
.../qemucapabilitiesdata/caps_3.0.0.ppc64.xml | 1 +
.../caps_3.0.0.riscv32.xml | 1 +
.../caps_3.0.0.riscv64.xml | 1 +
.../qemucapabilitiesdata/caps_3.0.0.s390x.xml | 1 +
.../caps_3.0.0.x86_64.xml | 1 +
tools/virsh-domain-monitor.c | 7 +
tools/virsh-domain.c | 110 +++++
tools/virsh.pod | 47 ++-
36 files changed, 825 insertions(+), 37 deletions(-)
John Ferlan
2018-11-12 14:36:01 UTC
Permalink
ping?

Tks,

John
v2: https://www.redhat.com/archives/libvir-list/2018-October/msg01065.html
NB: Minor mods for this are change using 4.10.0 instead of 4.9.0, merge of
qemu_capabilities conflict, and updated news.xml
v1: https://www.redhat.com/archives/libvir-list/2018-October/msg00456.html
Changes since v1 (from code review)
Patch 2: Move the job back into qemuDomainGetIOThreadsLive
Patch 3: Add check for ActiveJob before allowing, use true for
*StatsWorker, and print 'iothread' in output not 'block'
Patch 5: Use virCheckPositiveArgGoto(nparams, error) instead of using
virCheckNonNegativeArgGoto(nparams, error). And then remove
the if (nparams) before the virCheckNonNullArgGoto(params, error);
Patch 6: Add ability to determine which parameter was set via bool
set_poll_{max_ns|grow|shrink} values. Then use those in
the macro that sets the value to determine whether or not
the value will be set based on whether it was changed.
Patch 10: Use bool's to set_ when the value is found in the incoming
params list. Remove the check that says poll_max_ns needs
to be set. Testing proves that if it's set to 0, then the
grow and shrink values can be changed (although they do
nothing)
Patch 12: (NEW) - News article
This series attempts to resurrect the concept of being able to modify
the IOThread polling parameters; however, in a slightly different
manner than the previous series posted by posted by Pavel Hrdina
https://www.redhat.com/archives/libvir-list/2017-February/msg01047.html
https://bugzilla.redhat.com/show_bug.cgi?id=1545732
to provide some way to modify the paremters without needing to supply
QEMU command line pass through values.
It's accepted that the values being changed are fairly or extremely
low level type knobs; however, it's also shown that by being able to
turn the knob it is possible for certain, specific appliances to be
able to gain a performance benefit for the thread at the expense of
other competing threads.
Unlike the previous series, this series does not attempt to save the
polling values in the guest XML. Rather, it only modifies the live
guest's IOThread with new values. It also doesn't provide the polling
values in a virsh iothread* command, rather it uses the domstats
in order to fetch and display the values. The theory being this
leaves the onus on the higher level appliance/application to provide
the "proper guidance" and "concerns" related to changing the values
to the consumer. Not saving the values means whatever values that
are chosen do not "live" in perpetuity. Once the guest is shut down
or the IOThread removed from guest, the hypervisor default values
take over again. Perhaps not a perfect situation in terms of what
the bz requests; however, storage of default values that could
cause performance issues is not an optimal situation. So this I
figured is a "comprimise" of sorts.
If it's still felt that no we don't want to do this, then fine,
but please in doing so own the bz, state your case, and close it.
I'm 50/50 on it, but figured at least I'd present this option and
see what the concensus was.
qemu: Check for and return IOThread polling values if available
qemu: Split qemuDomainGetIOThreadsLive
qemu: Implement the ability to return IOThread stats
virsh: Add ability to display IOThread stats
lib: Introduce virDomainSetIOThreadParams
qemu: Add monitor functions to set IOThread params
qemu: Alter qemuDomainChgIOThread to take enum instead of bool
qemu: Alter qemuDomainChgIOThread to take qemuMonitorIOThreadInfo
qemu: Detect whether iothread polling is supported
qemu: Introduce qemuDomainSetIOThreadParams
tools: Add virsh iothreadset command
docs: Add news article for IOThread polling
docs/news.xml | 13 +
include/libvirt/libvirt-domain.h | 45 ++
src/driver-hypervisor.h | 8 +
src/libvirt-domain.c | 108 +++++
src/libvirt_public.syms | 5 +
src/qemu/qemu_capabilities.c | 2 +
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_driver.c | 384 ++++++++++++++++--
src/qemu/qemu_monitor.c | 19 +
src/qemu/qemu_monitor.h | 9 +
src/qemu/qemu_monitor_json.c | 50 +++
src/qemu/qemu_monitor_json.h | 4 +
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 21 +-
src/remote_protocol-structs | 10 +
.../caps_2.10.0.aarch64.xml | 1 +
.../caps_2.10.0.ppc64.xml | 1 +
.../caps_2.10.0.s390x.xml | 1 +
.../caps_2.10.0.x86_64.xml | 1 +
.../caps_2.11.0.s390x.xml | 1 +
.../caps_2.11.0.x86_64.xml | 1 +
.../caps_2.12.0.aarch64.xml | 1 +
.../caps_2.12.0.ppc64.xml | 1 +
.../caps_2.12.0.s390x.xml | 1 +
.../caps_2.12.0.x86_64.xml | 1 +
.../qemucapabilitiesdata/caps_2.9.0.ppc64.xml | 1 +
.../qemucapabilitiesdata/caps_2.9.0.s390x.xml | 1 +
.../caps_2.9.0.x86_64.xml | 1 +
.../qemucapabilitiesdata/caps_3.0.0.ppc64.xml | 1 +
.../caps_3.0.0.riscv32.xml | 1 +
.../caps_3.0.0.riscv64.xml | 1 +
.../qemucapabilitiesdata/caps_3.0.0.s390x.xml | 1 +
.../caps_3.0.0.x86_64.xml | 1 +
tools/virsh-domain-monitor.c | 7 +
tools/virsh-domain.c | 110 +++++
tools/virsh.pod | 47 ++-
36 files changed, 825 insertions(+), 37 deletions(-)
Michal Privoznik
2018-11-15 09:55:22 UTC
Permalink
v2: https://www.redhat.com/archives/libvir-list/2018-October/msg01065.html
NB: Minor mods for this are change using 4.10.0 instead of 4.9.0, merge of
qemu_capabilities conflict, and updated news.xml
v1: https://www.redhat.com/archives/libvir-list/2018-October/msg00456.html
Changes since v1 (from code review)
Patch 2: Move the job back into qemuDomainGetIOThreadsLive
Patch 3: Add check for ActiveJob before allowing, use true for
*StatsWorker, and print 'iothread' in output not 'block'
Patch 5: Use virCheckPositiveArgGoto(nparams, error) instead of using
virCheckNonNegativeArgGoto(nparams, error). And then remove
the if (nparams) before the virCheckNonNullArgGoto(params, error);
Patch 6: Add ability to determine which parameter was set via bool
set_poll_{max_ns|grow|shrink} values. Then use those in
the macro that sets the value to determine whether or not
the value will be set based on whether it was changed.
Patch 10: Use bool's to set_ when the value is found in the incoming
params list. Remove the check that says poll_max_ns needs
to be set. Testing proves that if it's set to 0, then the
grow and shrink values can be changed (although they do
nothing)
Patch 12: (NEW) - News article
This series attempts to resurrect the concept of being able to modify
the IOThread polling parameters; however, in a slightly different
manner than the previous series posted by posted by Pavel Hrdina
https://www.redhat.com/archives/libvir-list/2017-February/msg01047.html
https://bugzilla.redhat.com/show_bug.cgi?id=1545732
to provide some way to modify the paremters without needing to supply
QEMU command line pass through values.
It's accepted that the values being changed are fairly or extremely
low level type knobs; however, it's also shown that by being able to
turn the knob it is possible for certain, specific appliances to be
able to gain a performance benefit for the thread at the expense of
other competing threads.
Unlike the previous series, this series does not attempt to save the
polling values in the guest XML. Rather, it only modifies the live
guest's IOThread with new values. It also doesn't provide the polling
values in a virsh iothread* command, rather it uses the domstats
in order to fetch and display the values. The theory being this
leaves the onus on the higher level appliance/application to provide
the "proper guidance" and "concerns" related to changing the values
to the consumer. Not saving the values means whatever values that
are chosen do not "live" in perpetuity. Once the guest is shut down
or the IOThread removed from guest, the hypervisor default values
take over again. Perhaps not a perfect situation in terms of what
the bz requests; however, storage of default values that could
cause performance issues is not an optimal situation. So this I
figured is a "comprimise" of sorts.
If it's still felt that no we don't want to do this, then fine,
but please in doing so own the bz, state your case, and close it.
I'm 50/50 on it, but figured at least I'd present this option and
see what the concensus was.
qemu: Check for and return IOThread polling values if available
qemu: Split qemuDomainGetIOThreadsLive
qemu: Implement the ability to return IOThread stats
virsh: Add ability to display IOThread stats
lib: Introduce virDomainSetIOThreadParams
qemu: Add monitor functions to set IOThread params
qemu: Alter qemuDomainChgIOThread to take enum instead of bool
qemu: Alter qemuDomainChgIOThread to take qemuMonitorIOThreadInfo
qemu: Detect whether iothread polling is supported
qemu: Introduce qemuDomainSetIOThreadParams
tools: Add virsh iothreadset command
docs: Add news article for IOThread polling
docs/news.xml | 13 +
include/libvirt/libvirt-domain.h | 45 ++
src/driver-hypervisor.h | 8 +
src/libvirt-domain.c | 108 +++++
src/libvirt_public.syms | 5 +
src/qemu/qemu_capabilities.c | 2 +
src/qemu/qemu_capabilities.h | 1 +
src/qemu/qemu_driver.c | 384 ++++++++++++++++--
src/qemu/qemu_monitor.c | 19 +
src/qemu/qemu_monitor.h | 9 +
src/qemu/qemu_monitor_json.c | 50 +++
src/qemu/qemu_monitor_json.h | 4 +
src/remote/remote_driver.c | 1 +
src/remote/remote_protocol.x | 21 +-
src/remote_protocol-structs | 10 +
.../caps_2.10.0.aarch64.xml | 1 +
.../caps_2.10.0.ppc64.xml | 1 +
.../caps_2.10.0.s390x.xml | 1 +
.../caps_2.10.0.x86_64.xml | 1 +
.../caps_2.11.0.s390x.xml | 1 +
.../caps_2.11.0.x86_64.xml | 1 +
.../caps_2.12.0.aarch64.xml | 1 +
.../caps_2.12.0.ppc64.xml | 1 +
.../caps_2.12.0.s390x.xml | 1 +
.../caps_2.12.0.x86_64.xml | 1 +
.../qemucapabilitiesdata/caps_2.9.0.ppc64.xml | 1 +
.../qemucapabilitiesdata/caps_2.9.0.s390x.xml | 1 +
.../caps_2.9.0.x86_64.xml | 1 +
.../qemucapabilitiesdata/caps_3.0.0.ppc64.xml | 1 +
.../caps_3.0.0.riscv32.xml | 1 +
.../caps_3.0.0.riscv64.xml | 1 +
.../qemucapabilitiesdata/caps_3.0.0.s390x.xml | 1 +
.../caps_3.0.0.x86_64.xml | 1 +
tools/virsh-domain-monitor.c | 7 +
tools/virsh-domain.c | 110 +++++
tools/virsh.pod | 47 ++-
36 files changed, 825 insertions(+), 37 deletions(-)
ACK

Michal
Michal Privoznik
2018-11-15 09:55:25 UTC
Permalink
Post by John Ferlan
Separate out the fetch of the IOThread monitor call into a separate
helper so that a subsequent domain statistics change can fetch the raw
IOThread data and parse it as it sees fit.
---
src/qemu/qemu_driver.c | 48 ++++++++++++++++++++++++++----------------
1 file changed, 30 insertions(+), 18 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a52e2495d5..e13633c1e0 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5486,39 +5486,52 @@ qemuDomainGetMaxVcpus(virDomainPtr dom)
VIR_DOMAIN_VCPU_MAXIMUM));
}
+
static int
-qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- virDomainIOThreadInfoPtr **info)
+qemuDomainGetIOThreadsMon(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuMonitorIOThreadInfoPtr **iothreads)
{
qemuDomainObjPrivatePtr priv;
- qemuMonitorIOThreadInfoPtr *iothreads = NULL;
- virDomainIOThreadInfoPtr *info_ret = NULL;
int niothreads = 0;
- size_t i;
- int ret = -1;
-
- if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
- goto cleanup;
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("cannot list IOThreads for an inactive domain"));
I wonder if this check should go into qemuDomainGetIOThreadsLive() right
after BeginJob(). Rationale behind is that in the next patch, the
qemuDomainGetStatsIOThread() does the same check already and then it
calls this function which does the check again. Not crucial though.
Post by John Ferlan
- goto endjob;
+ return -1;
}
priv = vm->privateData;
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("IOThreads not supported with this binary"));
- goto endjob;
+ return -1;
}
qemuDomainObjEnterMonitor(driver, vm);
- niothreads = qemuMonitorGetIOThreads(priv->mon, &iothreads);
- if (qemuDomainObjExitMonitor(driver, vm) < 0)
- goto endjob;
- if (niothreads < 0)
+ niothreads = qemuMonitorGetIOThreads(priv->mon, iothreads);
+ if (qemuDomainObjExitMonitor(driver, vm) < 0 || niothreads < 0)
+ return -1;
+
+ return niothreads;
+}
+
+
+static int
+qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ virDomainIOThreadInfoPtr **info)
+{
+ qemuMonitorIOThreadInfoPtr *iothreads = NULL;
+ virDomainIOThreadInfoPtr *info_ret = NULL;
+ int niothreads = 0;
+ size_t i;
+ int ret = -1;
+
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+ goto cleanup;
+
+ if ((niothreads = qemuDomainGetIOThreadsMon(driver, vm, &iothreads)) < 0)
goto endjob;
/* Nothing to do */
@@ -5548,8 +5561,7 @@ qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
virBitmapFree(map);
}
- *info = info_ret;
- info_ret = NULL;
+ VIR_STEAL_PTR(*info, info_ret);
ret = niothreads;
Michal
John Ferlan
2018-11-15 20:18:54 UTC
Permalink
Post by Michal Privoznik
Post by John Ferlan
Separate out the fetch of the IOThread monitor call into a separate
helper so that a subsequent domain statistics change can fetch the raw
IOThread data and parse it as it sees fit.
---
src/qemu/qemu_driver.c | 48 ++++++++++++++++++++++++++----------------
1 file changed, 30 insertions(+), 18 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index a52e2495d5..e13633c1e0 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5486,39 +5486,52 @@ qemuDomainGetMaxVcpus(virDomainPtr dom)
VIR_DOMAIN_VCPU_MAXIMUM));
}
+
static int
-qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
- virDomainObjPtr vm,
- virDomainIOThreadInfoPtr **info)
+qemuDomainGetIOThreadsMon(virQEMUDriverPtr driver,
+ virDomainObjPtr vm,
+ qemuMonitorIOThreadInfoPtr **iothreads)
{
qemuDomainObjPrivatePtr priv;
- qemuMonitorIOThreadInfoPtr *iothreads = NULL;
- virDomainIOThreadInfoPtr *info_ret = NULL;
int niothreads = 0;
- size_t i;
- int ret = -1;
-
- if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
- goto cleanup;
if (!virDomainObjIsActive(vm)) {
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
_("cannot list IOThreads for an inactive domain"));
I wonder if this check should go into qemuDomainGetIOThreadsLive() right
after BeginJob(). Rationale behind is that in the next patch, the
qemuDomainGetStatsIOThread() does the same check already and then it
calls this function which does the check again. Not crucial though.
Good point - I'll move it (and change return -1 to goto endjob ;-))

Tks

John

[...]
Loading...