提交 f38b654e 编写于 作者: D Daniel P. Berrange

Add API for 'info cpus' monitor command

* src/qemu/qemu_monitor.h, src/qemu/qemu_monitor.c: Add a new
  qemuMonitorGetCPUInfo() command
* src/qemu/qemu_driver.c: Refactor qemudDetectVcpuPIDs to
  use qemuMonitorGetCPUInfo()
上级 a541c762
......@@ -110,8 +110,8 @@ static int qemudDomainGetMaxVcpus(virDomainPtr dom);
static int qemudDomainSetMemoryBalloon(virConnectPtr conn,
virDomainObjPtr vm,
unsigned long newmem);
static int qemudDetectVcpuPIDs(virConnectPtr conn,
virDomainObjPtr vm);
static int qemuDetectVcpuPIDs(virConnectPtr conn,
virDomainObjPtr vm);
static int qemuUpdateActivePciHostdevs(struct qemud_driver *driver,
virDomainDefPtr def);
......@@ -1186,100 +1186,40 @@ qemudWaitForMonitor(virConnectPtr conn,
}
static int
qemudDetectVcpuPIDs(virConnectPtr conn,
virDomainObjPtr vm) {
char *qemucpus = NULL;
char *line;
int lastVcpu = -1;
/* Only KVM has seperate threads for CPUs,
others just use main QEMU process for CPU */
if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM)
vm->nvcpupids = 1;
else
vm->nvcpupids = vm->def->vcpus;
if (VIR_ALLOC_N(vm->vcpupids, vm->nvcpupids) < 0) {
virReportOOMError(conn);
return -1;
}
qemuDetectVcpuPIDs(virConnectPtr conn,
virDomainObjPtr vm) {
pid_t *cpupids = NULL;
int ncpupids;
if (vm->def->virtType != VIR_DOMAIN_VIRT_KVM) {
vm->nvcpupids = 1;
if (VIR_ALLOC_N(vm->vcpupids, vm->nvcpupids) < 0) {
virReportOOMError(conn);
return -1;
}
vm->vcpupids[0] = vm->pid;
return 0;
}
if (qemudMonitorCommand(vm, "info cpus", &qemucpus) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot run monitor command to fetch CPU thread info"));
VIR_FREE(vm->vcpupids);
vm->nvcpupids = 0;
return -1;
}
/*
* This is the gross format we're about to parse :-{
*
* (qemu) info cpus
* * CPU #0: pc=0x00000000000f0c4a thread_id=30019
* CPU #1: pc=0x00000000fffffff0 thread_id=30020
* CPU #2: pc=0x00000000fffffff0 thread_id=30021
*
*/
line = qemucpus;
do {
char *offset = strchr(line, '#');
char *end = NULL;
int vcpu = 0, tid = 0;
/* See if we're all done */
if (offset == NULL)
break;
/* What follows is now all KVM specific */
/* Extract VCPU number */
if (virStrToLong_i(offset + 1, &end, 10, &vcpu) < 0)
goto error;
if (end == NULL || *end != ':')
goto error;
/* Extract host Thread ID */
if ((offset = strstr(line, "thread_id=")) == NULL)
goto error;
if (virStrToLong_i(offset + strlen("thread_id="), &end, 10, &tid) < 0)
goto error;
if (end == NULL || !c_isspace(*end))
goto error;
/* Validate the VCPU is in expected range & order */
if (vcpu > vm->nvcpupids ||
vcpu != (lastVcpu + 1))
goto error;
lastVcpu = vcpu;
vm->vcpupids[vcpu] = tid;
/* Skip to next data line */
line = strchr(offset, '\r');
if (line == NULL)
line = strchr(offset, '\n');
} while (line != NULL);
/* Validate we got data for all VCPUs we expected */
if (lastVcpu != (vm->def->vcpus - 1))
goto error;
if ((ncpupids = qemuMonitorGetCPUInfo(vm, &cpupids)) < 0)
return -1;
VIR_FREE(qemucpus);
return 0;
/* Treat failure to get VCPU<->PID mapping as non-fatal */
if (ncpupids == 0)
return 0;
error:
VIR_FREE(vm->vcpupids);
vm->nvcpupids = 0;
VIR_FREE(qemucpus);
if (ncpupids != vm->def->vcpus) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
_("got wrong number of vCPU pids from QEMU monitor. got %d, wanted %d"),
ncpupids, (int)vm->def->vcpus);
VIR_FREE(cpupids);
return -1;
}
/* Explicitly return success, not error. Older KVM does
not have vCPU -> Thread mapping info and we don't
want to break its use. This merely disables ability
to pin vCPUS with libvirt */
vm->nvcpupids = ncpupids;
vm->vcpupids = cpupids;
return 0;
}
......@@ -2202,7 +2142,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
goto cleanup;
if ((qemudWaitForMonitor(conn, driver, vm, pos) < 0) ||
(qemudDetectVcpuPIDs(conn, vm) < 0) ||
(qemuDetectVcpuPIDs(conn, vm) < 0) ||
(qemudInitCpus(conn, vm, migrateFrom) < 0) ||
(qemudInitPasswords(conn, driver, vm) < 0) ||
(qemudDomainSetMemoryBalloon(conn, vm, vm->def->memory) < 0) ||
......
......@@ -31,6 +31,7 @@
#include "qemu_monitor_text.h"
#include "qemu_conf.h"
#include "c-ctype.h"
#include "memory.h"
#include "logging.h"
#include "driver.h"
......@@ -435,3 +436,87 @@ qemudMonitorSendCont(virConnectPtr conn,
VIR_FREE(reply);
return 0;
}
int qemuMonitorGetCPUInfo(const virDomainObjPtr vm,
int **pids)
{
char *qemucpus = NULL;
char *line;
int lastVcpu = -1;
pid_t *cpupids = NULL;
size_t ncpupids = 0;
if (qemudMonitorCommand(vm, "info cpus", &qemucpus) < 0) {
qemudReportError(NULL, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("cannot run monitor command to fetch CPU thread info"));
return -1;
}
/*
* This is the gross format we're about to parse :-{
*
* (qemu) info cpus
* * CPU #0: pc=0x00000000000f0c4a thread_id=30019
* CPU #1: pc=0x00000000fffffff0 thread_id=30020
* CPU #2: pc=0x00000000fffffff0 thread_id=30021
*
*/
line = qemucpus;
do {
char *offset = strchr(line, '#');
char *end = NULL;
int vcpu = 0, tid = 0;
/* See if we're all done */
if (offset == NULL)
break;
/* Extract VCPU number */
if (virStrToLong_i(offset + 1, &end, 10, &vcpu) < 0)
goto error;
if (end == NULL || *end != ':')
goto error;
/* Extract host Thread ID */
if ((offset = strstr(line, "thread_id=")) == NULL)
goto error;
if (virStrToLong_i(offset + strlen("thread_id="), &end, 10, &tid) < 0)
goto error;
if (end == NULL || !c_isspace(*end))
goto error;
if (vcpu != (lastVcpu + 1))
goto error;
if (VIR_REALLOC_N(cpupids, ncpupids+1) < 0)
goto error;
cpupids[ncpupids++] = tid;
lastVcpu = vcpu;
/* Skip to next data line */
line = strchr(offset, '\r');
if (line == NULL)
line = strchr(offset, '\n');
} while (line != NULL);
/* Validate we got data for all VCPUs we expected */
VIR_FREE(qemucpus);
*pids = cpupids;
return ncpupids;
error:
VIR_FREE(qemucpus);
VIR_FREE(cpupids);
/* Returning 0 to indicate non-fatal failure, since
* older QEMU does not have VCPU<->PID mapping and
* we don't want to fail on that
*/
return 0;
}
......@@ -68,5 +68,7 @@ int qemudMonitorCommandExtra(const virDomainObjPtr vm,
int qemudMonitorSendCont(virConnectPtr conn,
const virDomainObjPtr vm);
#endif /* QEMU_MONITOR_TEXT_H */
int qemuMonitorGetCPUInfo(const virDomainObjPtr vm,
int **pids);
#endif /* QEMU_MONITOR_TEXT_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册