提交 d60570b3 编写于 作者: J Ján Tomko

qemu: simplify CPU command line parsing

Use virStringSplit. Change the 'error' label to 'cleanup' to prevent
memory leaks on error.
上级 5debc722
...@@ -9623,73 +9623,68 @@ qemuParseCommandLineCPU(virDomainDefPtr dom, ...@@ -9623,73 +9623,68 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
const char *val) const char *val)
{ {
virCPUDefPtr cpu = NULL; virCPUDefPtr cpu = NULL;
const char *p = val; char **tokens;
const char *next;
char *model = NULL; char *model = NULL;
int ret = -1;
int i;
do { if (!(tokens = virStringSplit(val, ",", 0)))
if (*p == '\0' || *p == ',') goto cleanup;
goto syntax;
if ((next = strchr(p, ','))) if (tokens[0] == NULL)
next++; goto syntax;
if (p == val) { for (i = 0; tokens[i] != NULL; i++) {
if (VIR_STRNDUP(model, p, next ? next - p - 1 : -1) < 0) if (*tokens[i] == '\0')
goto error; goto syntax;
if (i == 0) {
if (VIR_STRDUP(model, tokens[i]) < 0)
goto cleanup;
if (!STREQ(model, "qemu32") && !STREQ(model, "qemu64")) { if (!STREQ(model, "qemu32") && !STREQ(model, "qemu64")) {
if (!(cpu = qemuInitGuestCPU(dom))) if (!(cpu = qemuInitGuestCPU(dom)))
goto error; goto cleanup;
cpu->model = model; cpu->model = model;
model = NULL; model = NULL;
} }
} else if (*p == '+' || *p == '-') { } else if (*tokens[i] == '+' || *tokens[i] == '-') {
char *feature; const char *feature = tokens[i] + 1; /* '+' or '-' */
int policy; int policy;
int ret = 0;
if (*p == '+') if (*tokens[i] == '+')
policy = VIR_CPU_FEATURE_REQUIRE; policy = VIR_CPU_FEATURE_REQUIRE;
else else
policy = VIR_CPU_FEATURE_DISABLE; policy = VIR_CPU_FEATURE_DISABLE;
p++; if (*feature == '\0')
if (*p == '\0' || *p == ',')
goto syntax; goto syntax;
if (VIR_STRNDUP(feature, p, next ? next - p - 1 : -1) < 0)
goto error;
if (STREQ(feature, "kvmclock")) { if (STREQ(feature, "kvmclock")) {
bool present = (policy == VIR_CPU_FEATURE_REQUIRE); bool present = (policy == VIR_CPU_FEATURE_REQUIRE);
int i; int j;
for (i = 0; i < dom->clock.ntimers; i++) { for (j = 0; j < dom->clock.ntimers; j++) {
if (dom->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK) { if (dom->clock.timers[j]->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK)
break; break;
}
} }
if (i == dom->clock.ntimers) { if (j == dom->clock.ntimers) {
if (VIR_REALLOC_N(dom->clock.timers, i+1) < 0 || if (VIR_REALLOC_N(dom->clock.timers, j + 1) < 0 ||
VIR_ALLOC(dom->clock.timers[i]) < 0) VIR_ALLOC(dom->clock.timers[j]) < 0)
goto no_memory; goto no_memory;
dom->clock.timers[i]->name = VIR_DOMAIN_TIMER_NAME_KVMCLOCK; dom->clock.timers[j]->name = VIR_DOMAIN_TIMER_NAME_KVMCLOCK;
dom->clock.timers[i]->present = -1; dom->clock.timers[j]->present = present;
dom->clock.timers[i]->tickpolicy = -1; dom->clock.timers[j]->tickpolicy = -1;
dom->clock.timers[i]->track = -1; dom->clock.timers[j]->track = -1;
dom->clock.ntimers++; dom->clock.ntimers++;
} } else if (dom->clock.timers[j]->present != -1 &&
dom->clock.timers[j]->present != present) {
if (dom->clock.timers[i]->present != -1 &&
dom->clock.timers[i]->present != present) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("conflicting occurrences of kvmclock feature")); _("conflicting occurrences of kvmclock feature"));
goto error; goto cleanup;
} }
dom->clock.timers[i]->present = present;
} else if (STREQ(feature, "kvm_pv_eoi")) { } else if (STREQ(feature, "kvm_pv_eoi")) {
if (policy == VIR_CPU_FEATURE_REQUIRE) if (policy == VIR_CPU_FEATURE_REQUIRE)
dom->apic_eoi = VIR_DOMAIN_FEATURE_STATE_ON; dom->apic_eoi = VIR_DOMAIN_FEATURE_STATE_ON;
...@@ -9698,36 +9693,29 @@ qemuParseCommandLineCPU(virDomainDefPtr dom, ...@@ -9698,36 +9693,29 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
} else { } else {
if (!cpu) { if (!cpu) {
if (!(cpu = qemuInitGuestCPU(dom))) if (!(cpu = qemuInitGuestCPU(dom)))
goto error; goto cleanup;
cpu->model = model; cpu->model = model;
model = NULL; model = NULL;
} }
ret = virCPUDefAddFeature(cpu, feature, policy); if (virCPUDefAddFeature(cpu, feature, policy) < 0)
goto cleanup;
} }
} else if (STRPREFIX(tokens[i], "hv_")) {
VIR_FREE(feature); const char *feature = tokens[i] + 3; /* "hv_" */
if (ret < 0)
goto error;
} else if (STRPREFIX(p, "hv_")) {
char *feature;
int f; int f;
p += 3; /* "hv_" */
if (*p == '\0' || *p == ',') if (*feature == '\0')
goto syntax; goto syntax;
if (VIR_STRNDUP(feature, p, next ? next - p - 1 : -1) < 0)
goto error;
dom->features |= (1 << VIR_DOMAIN_FEATURE_HYPERV); dom->features |= (1 << VIR_DOMAIN_FEATURE_HYPERV);
if ((f = virDomainHypervTypeFromString(feature)) < 0) { if ((f = virDomainHypervTypeFromString(feature)) < 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("unsupported HyperV Enlightenment feature " _("unsupported HyperV Enlightenment feature "
"'%s'"), feature); "'%s'"), feature);
goto error; goto cleanup;
} }
switch ((enum virDomainHyperv) f) { switch ((enum virDomainHyperv) f) {
...@@ -9738,21 +9726,17 @@ qemuParseCommandLineCPU(virDomainDefPtr dom, ...@@ -9738,21 +9726,17 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
case VIR_DOMAIN_HYPERV_LAST: case VIR_DOMAIN_HYPERV_LAST:
break; break;
} }
VIR_FREE(feature);
} }
} while ((p = next)); }
if (dom->os.arch == VIR_ARCH_X86_64) { if (dom->os.arch == VIR_ARCH_X86_64) {
bool is_32bit = false; bool is_32bit = false;
if (cpu) { if (cpu) {
union cpuData *cpuData = NULL; union cpuData *cpuData = NULL;
int ret;
ret = cpuEncode(VIR_ARCH_X86_64, cpu, NULL, &cpuData, if (cpuEncode(VIR_ARCH_X86_64, cpu, NULL, &cpuData,
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL) < 0)
if (ret < 0) goto cleanup;
goto error;
is_32bit = (cpuHasFeature(VIR_ARCH_X86_64, cpuData, "lm") != 1); is_32bit = (cpuHasFeature(VIR_ARCH_X86_64, cpuData, "lm") != 1);
cpuDataFree(VIR_ARCH_X86_64, cpuData); cpuDataFree(VIR_ARCH_X86_64, cpuData);
...@@ -9760,22 +9744,25 @@ qemuParseCommandLineCPU(virDomainDefPtr dom, ...@@ -9760,22 +9744,25 @@ qemuParseCommandLineCPU(virDomainDefPtr dom,
is_32bit = STREQ(model, "qemu32"); is_32bit = STREQ(model, "qemu32");
} }
if (is_32bit) { if (is_32bit)
dom->os.arch = VIR_ARCH_I686; dom->os.arch = VIR_ARCH_I686;
}
} }
ret = 0;
cleanup:
VIR_FREE(model); VIR_FREE(model);
return 0; virStringFreeList(tokens);
return ret;
syntax: syntax:
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("unknown CPU syntax '%s'"), val); _("unknown CPU syntax '%s'"), val);
goto error; goto cleanup;
no_memory: no_memory:
virReportOOMError(); virReportOOMError();
error: goto cleanup;
return -1;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册