mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 20:45:18 +00:00
qemu: simplify CPU command line parsing
Use virStringSplit. Change the 'error' label to 'cleanup' to prevent memory leaks on error.
This commit is contained in:
parent
5debc7224a
commit
d60570b315
@ -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;
|
||||||
|
|
||||||
|
if (tokens[0] == NULL)
|
||||||
goto syntax;
|
goto syntax;
|
||||||
|
|
||||||
if ((next = strchr(p, ',')))
|
for (i = 0; tokens[i] != NULL; i++) {
|
||||||
next++;
|
if (*tokens[i] == '\0')
|
||||||
|
goto syntax;
|
||||||
|
|
||||||
if (p == val) {
|
if (i == 0) {
|
||||||
if (VIR_STRNDUP(model, p, next ? next - p - 1 : -1) < 0)
|
if (VIR_STRDUP(model, tokens[i]) < 0)
|
||||||
goto error;
|
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,
|
|||||||
} 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,
|
|||||||
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,
|
|||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user