qemu: use query-cpus-fast in JSON monitor

Use query-cpus-fast instead of query-cpus if supported by QEMU.
Based on the QEMU_CAPS_QUERY_CPUS_FAST capability.

Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
Viktor Mihajlovski 2018-04-04 16:45:03 +02:00 committed by John Ferlan
parent 56665e9984
commit 41e335f99b
6 changed files with 65 additions and 31 deletions

View File

@ -9035,15 +9035,19 @@ qemuDomainRefreshVcpuInfo(virQEMUDriverPtr driver,
size_t maxvcpus = virDomainDefGetVcpusMax(vm->def); size_t maxvcpus = virDomainDefGetVcpusMax(vm->def);
size_t i; size_t i;
bool hotplug; bool hotplug;
bool fast;
int rc; int rc;
int ret = -1; int ret = -1;
hotplug = qemuDomainSupportsNewVcpuHotplug(vm); hotplug = qemuDomainSupportsNewVcpuHotplug(vm);
fast = virQEMUCapsGet(QEMU_DOMAIN_PRIVATE(vm)->qemuCaps,
QEMU_CAPS_QUERY_CPUS_FAST);
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
return -1; return -1;
rc = qemuMonitorGetCPUInfo(qemuDomainGetMonitor(vm), &info, maxvcpus, hotplug); rc = qemuMonitorGetCPUInfo(qemuDomainGetMonitor(vm), &info, maxvcpus,
hotplug, fast);
if (qemuDomainObjExitMonitor(driver, vm) < 0) if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup; goto cleanup;
@ -9062,7 +9066,7 @@ qemuDomainRefreshVcpuInfo(virQEMUDriverPtr driver,
* thread, but it runs every vCPU in that same thread. So it * thread, but it runs every vCPU in that same thread. So it
* is impossible to setup different affinity per thread. * is impossible to setup different affinity per thread.
* *
* What's more the 'query-cpus' command returns bizarre * What's more the 'query-cpus[-fast]' command returns bizarre
* data for the threads. It gives the TCG thread for the * data for the threads. It gives the TCG thread for the
* vCPU 0, but for vCPUs 1-> N, it actually replies with * vCPU 0, but for vCPUs 1-> N, it actually replies with
* the main process thread ID. * the main process thread ID.
@ -9150,6 +9154,7 @@ qemuDomainRefreshVcpuHalted(virQEMUDriverPtr driver,
virBitmapPtr haltedmap = NULL; virBitmapPtr haltedmap = NULL;
size_t i; size_t i;
int ret = -1; int ret = -1;
bool fast;
/* Not supported currently for TCG, see qemuDomainRefreshVcpuInfo */ /* Not supported currently for TCG, see qemuDomainRefreshVcpuInfo */
if (vm->def->virtType == VIR_DOMAIN_VIRT_QEMU) if (vm->def->virtType == VIR_DOMAIN_VIRT_QEMU)
@ -9163,8 +9168,10 @@ qemuDomainRefreshVcpuHalted(virQEMUDriverPtr driver,
if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0) if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
return -1; return -1;
haltedmap = qemuMonitorGetCpuHalted(qemuDomainGetMonitor(vm), maxvcpus); fast = virQEMUCapsGet(QEMU_DOMAIN_PRIVATE(vm)->qemuCaps,
QEMU_CAPS_QUERY_CPUS_FAST);
haltedmap = qemuMonitorGetCpuHalted(qemuDomainGetMonitor(vm), maxvcpus,
fast);
if (qemuDomainObjExitMonitor(driver, vm) < 0 || !haltedmap) if (qemuDomainObjExitMonitor(driver, vm) < 0 || !haltedmap)
goto cleanup; goto cleanup;

View File

@ -1847,15 +1847,16 @@ qemuMonitorGetCPUInfoLegacy(struct qemuMonitorQueryCpusEntry *cpuentries,
* *
* This function stitches together data retrieved via query-hotpluggable-cpus * This function stitches together data retrieved via query-hotpluggable-cpus
* which returns entities on the hotpluggable level (which may describe more * which returns entities on the hotpluggable level (which may describe more
* than one guest logical vcpu) with the output of query-cpus, having an entry * than one guest logical vcpu) with the output of query-cpus (or
* per enabled guest logical vcpu. * query-cpus-fast), having an entry per enabled guest logical vcpu.
* *
* query-hotpluggable-cpus conveys following information: * query-hotpluggable-cpus conveys following information:
* - topology information and number of logical vcpus this entry creates * - topology information and number of logical vcpus this entry creates
* - device type name of the entry that needs to be used when hotplugging * - device type name of the entry that needs to be used when hotplugging
* - qom path in qemu which can be used to map the entry against query-cpus * - qom path in qemu which can be used to map the entry against
* query-cpus[-fast]
* *
* query-cpus conveys following information: * query-cpus[-fast] conveys following information:
* - thread id of a given guest logical vcpu * - thread id of a given guest logical vcpu
* - order in which the vcpus were inserted * - order in which the vcpus were inserted
* - qom path to allow mapping the two together * - qom path to allow mapping the two together
@ -1890,7 +1891,7 @@ qemuMonitorGetCPUInfoHotplug(struct qemuMonitorQueryHotpluggableCpusEntry *hotpl
for (i = 0; i < nhotplugvcpus; i++) for (i = 0; i < nhotplugvcpus; i++)
totalvcpus += hotplugvcpus[i].vcpus; totalvcpus += hotplugvcpus[i].vcpus;
/* trim '/thread...' suffix from the data returned by query-cpus */ /* trim '/thread...' suffix from the data returned by query-cpus[-fast] */
for (i = 0; i < ncpuentries; i++) { for (i = 0; i < ncpuentries; i++) {
if (cpuentries[i].qom_path && if (cpuentries[i].qom_path &&
(tmp = strstr(cpuentries[i].qom_path, "/thread"))) (tmp = strstr(cpuentries[i].qom_path, "/thread")))
@ -1903,7 +1904,7 @@ qemuMonitorGetCPUInfoHotplug(struct qemuMonitorQueryHotpluggableCpusEntry *hotpl
} }
/* Note the order in which the hotpluggable entities are inserted by /* Note the order in which the hotpluggable entities are inserted by
* matching them to the query-cpus entries */ * matching them to the query-cpus[-fast] entries */
for (i = 0; i < ncpuentries; i++) { for (i = 0; i < ncpuentries; i++) {
for (j = 0; j < nhotplugvcpus; j++) { for (j = 0; j < nhotplugvcpus; j++) {
if (!cpuentries[i].qom_path || if (!cpuentries[i].qom_path ||
@ -1958,7 +1959,7 @@ qemuMonitorGetCPUInfoHotplug(struct qemuMonitorQueryHotpluggableCpusEntry *hotpl
} }
if (anyvcpu == maxvcpus) { if (anyvcpu == maxvcpus) {
VIR_DEBUG("too many query-cpus entries for a given " VIR_DEBUG("too many query-cpus[-fast] entries for a given "
"query-hotpluggable-cpus entry"); "query-hotpluggable-cpus entry");
return -1; return -1;
} }
@ -1986,6 +1987,7 @@ qemuMonitorGetCPUInfoHotplug(struct qemuMonitorQueryHotpluggableCpusEntry *hotpl
* @vcpus: pointer filled by array of qemuMonitorCPUInfo structures * @vcpus: pointer filled by array of qemuMonitorCPUInfo structures
* @maxvcpus: total possible number of vcpus * @maxvcpus: total possible number of vcpus
* @hotplug: query data relevant for hotplug support * @hotplug: query data relevant for hotplug support
* @fast: use QMP query-cpus-fast if supported
* *
* Detects VCPU information. If qemu doesn't support or fails reporting * Detects VCPU information. If qemu doesn't support or fails reporting
* information this function will return success as other parts of libvirt * information this function will return success as other parts of libvirt
@ -1998,7 +2000,8 @@ int
qemuMonitorGetCPUInfo(qemuMonitorPtr mon, qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
qemuMonitorCPUInfoPtr *vcpus, qemuMonitorCPUInfoPtr *vcpus,
size_t maxvcpus, size_t maxvcpus,
bool hotplug) bool hotplug,
bool fast)
{ {
struct qemuMonitorQueryHotpluggableCpusEntry *hotplugcpus = NULL; struct qemuMonitorQueryHotpluggableCpusEntry *hotplugcpus = NULL;
size_t nhotplugcpus = 0; size_t nhotplugcpus = 0;
@ -2024,7 +2027,8 @@ qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
goto cleanup; goto cleanup;
if (mon->json) if (mon->json)
rc = qemuMonitorJSONQueryCPUs(mon, &cpuentries, &ncpuentries, hotplug); rc = qemuMonitorJSONQueryCPUs(mon, &cpuentries, &ncpuentries, hotplug,
fast);
else else
rc = qemuMonitorTextQueryCPUs(mon, &cpuentries, &ncpuentries); rc = qemuMonitorTextQueryCPUs(mon, &cpuentries, &ncpuentries);
@ -2062,11 +2066,12 @@ qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
* qemuMonitorGetCpuHalted: * qemuMonitorGetCpuHalted:
* *
* Returns a bitmap of vcpu id's that are halted. The id's correspond to the * Returns a bitmap of vcpu id's that are halted. The id's correspond to the
* 'CPU' field as reported by query-cpus'. * 'CPU' field as reported by query-cpus[-fast]'.
*/ */
virBitmapPtr virBitmapPtr
qemuMonitorGetCpuHalted(qemuMonitorPtr mon, qemuMonitorGetCpuHalted(qemuMonitorPtr mon,
size_t maxvcpus) size_t maxvcpus,
bool fast ATTRIBUTE_UNUSED)
{ {
struct qemuMonitorQueryCpusEntry *cpuentries = NULL; struct qemuMonitorQueryCpusEntry *cpuentries = NULL;
size_t ncpuentries = 0; size_t ncpuentries = 0;
@ -2077,7 +2082,8 @@ qemuMonitorGetCpuHalted(qemuMonitorPtr mon,
QEMU_CHECK_MONITOR_NULL(mon); QEMU_CHECK_MONITOR_NULL(mon);
if (mon->json) if (mon->json)
rc = qemuMonitorJSONQueryCPUs(mon, &cpuentries, &ncpuentries, false); rc = qemuMonitorJSONQueryCPUs(mon, &cpuentries, &ncpuentries, false,
false);
else else
rc = qemuMonitorTextQueryCPUs(mon, &cpuentries, &ncpuentries); rc = qemuMonitorTextQueryCPUs(mon, &cpuentries, &ncpuentries);

View File

@ -542,8 +542,11 @@ void qemuMonitorCPUInfoFree(qemuMonitorCPUInfoPtr list,
int qemuMonitorGetCPUInfo(qemuMonitorPtr mon, int qemuMonitorGetCPUInfo(qemuMonitorPtr mon,
qemuMonitorCPUInfoPtr *vcpus, qemuMonitorCPUInfoPtr *vcpus,
size_t maxvcpus, size_t maxvcpus,
bool hotplug); bool hotplug,
virBitmapPtr qemuMonitorGetCpuHalted(qemuMonitorPtr mon, size_t maxvcpus); bool fast);
virBitmapPtr qemuMonitorGetCpuHalted(qemuMonitorPtr mon,
size_t maxvcpus,
bool fast);
int qemuMonitorGetVirtType(qemuMonitorPtr mon, int qemuMonitorGetVirtType(qemuMonitorPtr mon,
virDomainVirtType *virtType); virDomainVirtType *virtType);

View File

@ -1532,7 +1532,8 @@ int qemuMonitorJSONSystemReset(qemuMonitorPtr mon)
static int static int
qemuMonitorJSONExtractCPUInfo(virJSONValuePtr data, qemuMonitorJSONExtractCPUInfo(virJSONValuePtr data,
struct qemuMonitorQueryCpusEntry **entries, struct qemuMonitorQueryCpusEntry **entries,
size_t *nentries) size_t *nentries,
bool fast)
{ {
struct qemuMonitorQueryCpusEntry *cpus = NULL; struct qemuMonitorQueryCpusEntry *cpus = NULL;
int ret = -1; int ret = -1;
@ -1557,11 +1558,19 @@ qemuMonitorJSONExtractCPUInfo(virJSONValuePtr data,
} }
/* Some older qemu versions don't report the thread_id so treat this as /* Some older qemu versions don't report the thread_id so treat this as
* non-fatal, simply returning no data */ * non-fatal, simply returning no data.
ignore_value(virJSONValueObjectGetNumberInt(entry, "CPU", &cpuid)); * The return data of query-cpus-fast has different field names
ignore_value(virJSONValueObjectGetNumberInt(entry, "thread_id", &thread)); */
ignore_value(virJSONValueObjectGetBoolean(entry, "halted", &halted)); if (fast) {
qom_path = virJSONValueObjectGetString(entry, "qom_path"); ignore_value(virJSONValueObjectGetNumberInt(entry, "cpu-index", &cpuid));
ignore_value(virJSONValueObjectGetNumberInt(entry, "thread-id", &thread));
qom_path = virJSONValueObjectGetString(entry, "qom-path");
} else {
ignore_value(virJSONValueObjectGetNumberInt(entry, "CPU", &cpuid));
ignore_value(virJSONValueObjectGetNumberInt(entry, "thread_id", &thread));
ignore_value(virJSONValueObjectGetBoolean(entry, "halted", &halted));
qom_path = virJSONValueObjectGetString(entry, "qom_path");
}
cpus[i].qemu_id = cpuid; cpus[i].qemu_id = cpuid;
cpus[i].tid = thread; cpus[i].tid = thread;
@ -1586,10 +1595,12 @@ qemuMonitorJSONExtractCPUInfo(virJSONValuePtr data,
* @mon: monitor object * @mon: monitor object
* @entries: filled with detected entries on success * @entries: filled with detected entries on success
* @nentries: number of entries returned * @nentries: number of entries returned
* @force: force exit on error
* @fast: use query-cpus-fast
* *
* Queries qemu for cpu-related information. Failure to execute the command or * Queries qemu for cpu-related information. Failure to execute the command or
* extract results does not produce an error as libvirt can continue without * extract results does not produce an error as libvirt can continue without
* this information. * this information, unless the caller has specified @force == true.
* *
* Returns 0 on success, -1 on a fatal error (oom ...) and -2 if the * Returns 0 on success, -1 on a fatal error (oom ...) and -2 if the
* query failed gracefully. * query failed gracefully.
@ -1598,13 +1609,19 @@ int
qemuMonitorJSONQueryCPUs(qemuMonitorPtr mon, qemuMonitorJSONQueryCPUs(qemuMonitorPtr mon,
struct qemuMonitorQueryCpusEntry **entries, struct qemuMonitorQueryCpusEntry **entries,
size_t *nentries, size_t *nentries,
bool force) bool force,
bool fast)
{ {
int ret = -1; int ret = -1;
virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-cpus", NULL); virJSONValuePtr cmd;
virJSONValuePtr reply = NULL; virJSONValuePtr reply = NULL;
virJSONValuePtr data; virJSONValuePtr data;
if (fast)
cmd = qemuMonitorJSONMakeCommand("query-cpus-fast", NULL);
else
cmd = qemuMonitorJSONMakeCommand("query-cpus", NULL);
if (!cmd) if (!cmd)
return -1; return -1;
@ -1619,7 +1636,7 @@ qemuMonitorJSONQueryCPUs(qemuMonitorPtr mon,
goto cleanup; goto cleanup;
} }
ret = qemuMonitorJSONExtractCPUInfo(data, entries, nentries); ret = qemuMonitorJSONExtractCPUInfo(data, entries, nentries, fast);
cleanup: cleanup:
virJSONValueFree(cmd); virJSONValueFree(cmd);

View File

@ -60,7 +60,8 @@ int qemuMonitorJSONSystemReset(qemuMonitorPtr mon);
int qemuMonitorJSONQueryCPUs(qemuMonitorPtr mon, int qemuMonitorJSONQueryCPUs(qemuMonitorPtr mon,
struct qemuMonitorQueryCpusEntry **entries, struct qemuMonitorQueryCpusEntry **entries,
size_t *nentries, size_t *nentries,
bool force); bool force,
bool fast);
int qemuMonitorJSONGetVirtType(qemuMonitorPtr mon, int qemuMonitorJSONGetVirtType(qemuMonitorPtr mon,
virDomainVirtType *virtType); virDomainVirtType *virtType);
int qemuMonitorJSONUpdateVideoMemorySize(qemuMonitorPtr mon, int qemuMonitorJSONUpdateVideoMemorySize(qemuMonitorPtr mon,

View File

@ -1425,7 +1425,7 @@ testQemuMonitorJSONqemuMonitorJSONQueryCPUs(const void *data)
goto cleanup; goto cleanup;
if (qemuMonitorJSONQueryCPUs(qemuMonitorTestGetMonitor(test), if (qemuMonitorJSONQueryCPUs(qemuMonitorTestGetMonitor(test),
&cpudata, &ncpudata, true) < 0) &cpudata, &ncpudata, true, false) < 0)
goto cleanup; goto cleanup;
if (ncpudata != 4) { if (ncpudata != 4) {
@ -2638,7 +2638,7 @@ testQemuMonitorCPUInfo(const void *opaque)
goto cleanup; goto cleanup;
rc = qemuMonitorGetCPUInfo(qemuMonitorTestGetMonitor(test), rc = qemuMonitorGetCPUInfo(qemuMonitorTestGetMonitor(test),
&vcpus, data->maxvcpus, true); &vcpus, data->maxvcpus, true, false);
if (rc < 0) if (rc < 0)
goto cleanup; goto cleanup;