On Tue, Jan 12, 2010 at 03:25:42PM +0100, Jiri Denemark wrote:
QEMU's command line equivalent for the following domain XML
fragment
<vcpus>2</vcpus>
<cpu ...>
...
<topology sockets='1' cores='2', threads='1'/>
</cpu>
is
-smp 2,sockets=1,cores=2,threads=1
This syntax was introduced in QEMU-0.12.
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/qemu/qemu_conf.c | 137 ++++++++++++++++++++++++++++++++++++++++++++------
src/qemu/qemu_conf.h | 3 +-
2 files changed, 123 insertions(+), 17 deletions(-)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index d3da776..bc4736a 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -1,7 +1,7 @@
/*
* qemu_conf.c: QEMU configuration management
*
- * Copyright (C) 2006, 2007, 2008, 2009 Red Hat, Inc.
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -1115,6 +1115,10 @@ static unsigned int qemudComputeCmdFlags(const char *help,
flags |= QEMUD_CMD_FLAG_CHARDEV;
if (strstr(help, "-balloon"))
flags |= QEMUD_CMD_FLAG_BALLOON;
+ if (strstr(help, "cores=") &&
+ strstr(help, "threads=") &&
+ strstr(help, "sockets="))
+ flags |= QEMUD_CMD_FLAG_SMP_TOPOLOGY;
if (version >= 9000)
flags |= QEMUD_CMD_FLAG_VNC_COLON;
@@ -1900,7 +1904,6 @@ int qemudBuildCommandLine(virConnectPtr conn,
const char *migrateFrom) {
int i;
char memory[50];
- char vcpus[50];
char boot[VIR_DOMAIN_BOOT_LAST];
struct utsname ut;
int disableKQEMU = 0;
@@ -2049,7 +2052,6 @@ int qemudBuildCommandLine(virConnectPtr conn,
* is not supported, then they're out of luck anyway
*/
snprintf(memory, sizeof(memory), "%lu", def->maxmem/1024);
- snprintf(vcpus, sizeof(vcpus), "%lu", def->vcpus);
snprintf(domid, sizeof(domid), "%d", def->id);
ADD_ENV_LIT("LC_ALL=C");
@@ -2112,8 +2114,34 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG_LIT("-mem-path");
ADD_ARG_LIT(driver->hugepage_path);
}
+
ADD_ARG_LIT("-smp");
- ADD_ARG_LIT(vcpus);
+ if ((qemuCmdFlags & QEMUD_CMD_FLAG_SMP_TOPOLOGY) && def->cpu) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+ virBufferVSprintf(&buf, "%lu", def->vcpus);
+
+ if (def->cpu->sockets > 0)
+ virBufferVSprintf(&buf, ",sockets=%u",
def->cpu->sockets);
+
+ if (def->cpu->cores > 0)
+ virBufferVSprintf(&buf, ",cores=%u", def->cpu->cores);
+
+ if (def->cpu->threads > 0)
+ virBufferVSprintf(&buf, ",threads=%u",
def->cpu->threads);
+
+ if (virBufferError(&buf)) {
+ virBufferFreeAndReset(&buf);
+ goto no_memory;
+ }
+
+ ADD_ARG(virBufferContentAndReset(&buf));
+ }
+ else {
+ char vcpus[50];
+ snprintf(vcpus, sizeof(vcpus), "%lu", def->vcpus);
+ ADD_ARG_LIT(vcpus);
+ }
Can you split this piece of code out into a separate method with a
signature like
static char *qemuBuildCPUStr(virDomainDefPtr def, int qemuCmdFlags);
The main qemuBuildCommandLine method is getting out of control :-)
Also, in the case where 'def->cpu' is NULL, but QEMUD_CMD_FLAG_SMP_TOPOLOGY
is available, I think we should explicitly set an arg based on
sockets=def->vcpus
cores=1
threads=1
so that we avoid relying on any changable QEMU default values.
if (qemuCmdFlags & QEMUD_CMD_FLAG_NAME) {
ADD_ARG_LIT("-name");
@@ -3729,6 +3757,27 @@ error:
}
+static virCPUDefPtr
+qemuInitGuestCPU(virConnectPtr conn,
+ virDomainDefPtr dom)
+{
+ if (!dom->cpu) {
+ virCPUDefPtr cpu;
+
+ if (VIR_ALLOC(cpu) < 0) {
+ virReportOOMError(conn);
+ return NULL;
+ }
+
+ cpu->type = VIR_CPU_TYPE_GUEST;
+ cpu->match = VIR_CPU_MATCH_EXACT;
+ dom->cpu = cpu;
+ }
+
+ return dom->cpu;
+}
+
+
static int
qemuParseCommandLineCPU(virConnectPtr conn,
virDomainDefPtr dom,
@@ -3738,10 +3787,8 @@ qemuParseCommandLineCPU(virConnectPtr conn,
const char *p = val;
const char *next;
- if (VIR_ALLOC(cpu) < 0)
- goto no_memory;
-
- cpu->type = VIR_CPU_TYPE_GUEST;
+ if (!(cpu = qemuInitGuestCPU(conn, dom)))
+ goto error;
do {
if (*p == '\0' || *p == ',')
@@ -3785,7 +3832,6 @@ qemuParseCommandLineCPU(virConnectPtr conn,
}
} while ((p = next));
- dom->cpu = cpu;
return 0;
syntax:
@@ -3796,7 +3842,71 @@ syntax:
no_memory:
virReportOOMError(conn);
error:
- virCPUDefFree(cpu);
+ return -1;
+}
+
+
+static int
+qemuParseCommandLineSmp(virConnectPtr conn,
+ virDomainDefPtr dom,
+ const char *val)
+{
+ const char *p = val;
+ const char *next;
+ const char *const options[] = { "sockets=", "cores=",
"threads=" };
+ unsigned int topology[] = { 0, 0, 0 };
+ char *end;
+
+ do {
+ if (*p == '\0' || *p == ',')
+ goto syntax;
+
+ if ((next = strchr(p, ',')))
+ next++;
+
+ if (c_isdigit(*p)) {
+ int n;
+ if (virStrToLong_i(p, &end, 10, &n) < 0 ||
+ !end || (*end != ',' && *end != '\0'))
+ goto syntax;
+ dom->vcpus = n;
+ } else {
+ int i;
+ int n = -1;
+ for (i = 0; i < ARRAY_CARDINALITY(options); i++) {
+ if (STRPREFIX(p, options[i])) {
+ p += strlen(options[i]);
+ if (virStrToLong_i(p, &end, 10, &n) < 0 ||
+ !end || (*end != ',' && *end != '\0'))
+ goto syntax;
+ topology[i] = n;
+ break;
+ }
+ }
+
+ if (n < 0)
+ goto syntax;
+ }
+ } while ((p = next));
If you strip off the initial CPU count value, then you can use
qemuParseCommandLineKeywords
to parse the reset of the name=value args.
+
+ if (topology[0] && topology[1] && topology[2]) {
+ virCPUDefPtr cpu;
+
+ if (!(cpu = qemuInitGuestCPU(conn, dom)))
+ goto error;
+
+ cpu->sockets = topology[0];
+ cpu->cores = topology[1];
+ cpu->threads = topology[2];
+ } else if (topology[0] || topology[1] || topology[2])
+ goto syntax;
+
+ return 0;
+
+syntax:
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("cannot parse CPU topology '%s'"), val);
+error:
return -1;
}
@@ -3948,14 +4058,9 @@ virDomainDefPtr qemuParseCommandLine(virConnectPtr conn,
}
def->memory = def->maxmem = mem * 1024;
} else if (STREQ(arg, "-smp")) {
- int vcpus;
WANT_VALUE();
- if (virStrToLong_i(val, NULL, 10, &vcpus) < 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, \
- _("cannot parse CPU count '%s'"),
val);
+ if (qemuParseCommandLineSmp(conn, def, val) < 0)
goto error;
- }
- def->vcpus = vcpus;
} else if (STREQ(arg, "-uuid")) {
WANT_VALUE();
if (virUUIDParse(val, def->uuid) < 0) {
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 82254ca..3f74cc9 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -1,7 +1,7 @@
/*
* qemu_conf.h: QEMU configuration management
*
- * Copyright (C) 2006, 2007, 2009 Red Hat, Inc.
+ * Copyright (C) 2006, 2007, 2009, 2010 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -78,6 +78,7 @@ enum qemud_cmd_flags {
QEMUD_CMD_FLAG_ENABLE_KVM = (1 << 23), /* Is the -enable-kvm flag available
to "enable KVM full virtualization support" */
QEMUD_CMD_FLAG_MONITOR_JSON = (1 << 24), /* JSON mode for monitor */
QEMUD_CMD_FLAG_BALLOON = (1 << 25), /* -balloon available */
+ QEMUD_CMD_FLAG_SMP_TOPOLOGY = (1 << 26), /* Is sockets=s,cores=c,threads=t
available for -smp? */
};
/* Main driver state */
--
Regards,
Daniel
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|