[libvirt] [PATCH 0/3] Check CPU features during migration

Jiri Denemark (3): cpuUpdate() for updating guest CPU according to host CPU Helper function for making a deep-copy of virCPUDefPtr Introduce UPDATE_CPU flag for virDomainGetXMLDesc include/libvirt/libvirt.h.in | 5 +- src/conf/cpu_conf.c | 37 ++++++++++ src/conf/cpu_conf.h | 3 + src/cpu/cpu.c | 22 ++++++ src/cpu/cpu.h | 9 +++ src/cpu/cpu_generic.c | 1 + src/cpu/cpu_x86.c | 161 +++++++++++++++++++++++++++++++++++++----- src/libvirt.c | 3 +- src/libvirt_private.syms | 2 + src/qemu/qemu_driver.c | 54 ++++++++++++-- tools/virsh.c | 4 + 11 files changed, 273 insertions(+), 28 deletions(-)

Useful mainly for migration. cpuUpdate changes guest CPU requirements in the following way: - match == "strict" || match == "exact" - optional features which are supported by host CPU are changed into required features - optional features which are not supported by host CPU are disabled - all other features remain untouched - match == "minimum" - match is changed into "exact" - optional features and all features not mentioned in guest CPU specification which are supported by host CPU become required features - other optional features are disabled - oll other features remain untouched This ensures that no feature will suddenly disappear from the guest after migration. --- src/cpu/cpu.c | 22 ++++++ src/cpu/cpu.h | 9 +++ src/cpu/cpu_generic.c | 1 + src/cpu/cpu_x86.c | 161 +++++++++++++++++++++++++++++++++++++++++----- src/libvirt_private.syms | 1 + 5 files changed, 177 insertions(+), 17 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 183862a..4a1588d 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -403,3 +403,25 @@ cpuBaseline(virCPUDefPtr *cpus, return cpu; } + + +int +cpuUpdate(virCPUDefPtr guest, + const virCPUDefPtr host) +{ + struct cpuArchDriver *driver; + + VIR_DEBUG("guest=%p, host=%p", guest, host); + + if ((driver = cpuGetSubDriver(host->arch)) == NULL) + return -1; + + if (driver->update == NULL) { + virCPUReportError(VIR_ERR_NO_SUPPORT, + _("cannot update guest CPU data for %s architecture"), + host->arch); + return -1; + } + + return driver->update(guest, host); +} diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index a2d79fe..1494a7f 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -76,6 +76,10 @@ typedef virCPUDefPtr const char **models, unsigned int nmodels); +typedef int +(*cpuArchUpdate) (virCPUDefPtr guest, + const virCPUDefPtr host); + struct cpuArchDriver { const char *name; @@ -88,6 +92,7 @@ struct cpuArchDriver { cpuArchNodeData nodeData; cpuArchGuestData guestData; cpuArchBaseline baseline; + cpuArchUpdate update; }; @@ -138,4 +143,8 @@ cpuBaseline (virCPUDefPtr *cpus, const char **models, unsigned int nmodels); +extern int +cpuUpdate (virCPUDefPtr guest, + const virCPUDefPtr host); + #endif /* __VIR_CPU_H__ */ diff --git a/src/cpu/cpu_generic.c b/src/cpu/cpu_generic.c index 113af2f..a39f262 100644 --- a/src/cpu/cpu_generic.c +++ b/src/cpu/cpu_generic.c @@ -219,4 +219,5 @@ struct cpuArchDriver cpuDriverGeneric = { .nodeData = NULL, .guestData = NULL, .baseline = genericBaseline, + .update = NULL, }; diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 4bb556c..e49f7c0 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -249,6 +249,33 @@ x86DataFromModel(const struct x86_model *model) } +/* also removes all detected features from data */ +static int +x86DataToCPUFeatures(virCPUDefPtr cpu, + int policy, + union cpuData *data, + const struct x86_map *map) +{ + const struct x86_feature *feature = map->features; + struct cpuX86cpuid *cpuid; + unsigned int i; + + while (feature != NULL) { + for (i = 0; i < feature->ncpuid; i++) { + if ((cpuid = x86DataCpuid(data, feature->cpuid[i].function)) + && x86cpuidMatchMasked(cpuid, feature->cpuid + i)) { + x86cpuidClearBits(cpuid, feature->cpuid + i); + if (virCPUDefAddFeature(cpu, feature->name, policy) < 0) + return -1; + } + } + feature = feature->next; + } + + return 0; +} + + static virCPUDefPtr x86DataToCPU(const union cpuData *data, const struct x86_model *model, @@ -256,9 +283,7 @@ x86DataToCPU(const union cpuData *data, { virCPUDefPtr cpu; union cpuData *tmp = NULL; - struct cpuX86cpuid *cpuid; - const struct x86_feature *feature; - int i; + unsigned int i; if (VIR_ALLOC(cpu) < 0 || (cpu->model = strdup(model->name)) == NULL || @@ -270,20 +295,8 @@ x86DataToCPU(const union cpuData *data, model->cpuid + i); } - feature = map->features; - while (feature != NULL) { - for (i = 0; i < feature->ncpuid; i++) { - if ((cpuid = x86DataCpuid(tmp, feature->cpuid[i].function)) - && x86cpuidMatchMasked(cpuid, feature->cpuid + i)) { - x86cpuidClearBits(cpuid, feature->cpuid + i); - if (virCPUDefAddFeature(cpu, feature->name, - VIR_CPU_FEATURE_REQUIRE) < 0) - goto error; - } - } - - feature = feature->next; - } + if (x86DataToCPUFeatures(cpu, VIR_CPU_FEATURE_REQUIRE, tmp, map)) + goto error; cleanup: x86DataFree(tmp); @@ -560,6 +573,29 @@ x86ModelMergeFeature(struct x86_model *model, } +static bool +x86ModelHasFeature(struct x86_model *model, + const struct x86_feature *feature) +{ + unsigned int i; + struct cpuX86cpuid *cpuid; + struct cpuX86cpuid *model_cpuid; + + if (feature == NULL) + return false; + + for (i = 0; i < feature->ncpuid; i++) { + cpuid = feature->cpuid + i; + model_cpuid = x86cpuidFind(model->cpuid, model->ncpuid, + cpuid->function); + if (!x86cpuidMatchMasked(model_cpuid, cpuid)) + return false; + } + + return true; +} + + static struct x86_model * x86ModelFromCPU(const virCPUDefPtr cpu, const struct x86_map *map, @@ -610,6 +646,47 @@ error: } +static int +x86ModelSubtractCPU(struct x86_model *model, + const virCPUDefPtr cpu, + const struct x86_map *map) +{ + const struct x86_model *cpu_model; + unsigned int i; + + if (!(cpu_model = x86ModelFind(map, cpu->model))) { + virCPUReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown CPU model %s"), + cpu->model); + return -1; + } + + x86ModelSubtract(model, cpu_model); + + for (i = 0; i < cpu->nfeatures; i++) { + const struct x86_feature *feature; + unsigned int j; + + if (!(feature = x86FeatureFind(map, cpu->features[i].name))) { + virCPUReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown CPU feature %s"), + cpu->features[i].name); + return -1; + } + + for (j = 0; j < feature->ncpuid; j++) { + struct cpuX86cpuid *cpuid; + cpuid = x86cpuidFind(model->cpuid, model->ncpuid, + feature->cpuid[j].function); + if (cpuid) + x86cpuidClearBits(cpuid, feature->cpuid + j); + } + } + + return 0; +} + + static enum compare_result x86ModelCompare(const struct x86_model *model1, const struct x86_model *model2) @@ -1277,6 +1354,55 @@ error: } +static int +x86Update(virCPUDefPtr guest, + const virCPUDefPtr host) +{ + int ret = -1; + unsigned int i; + struct x86_map *map; + struct x86_model *host_model = NULL; + union cpuData *data = NULL; + + if (!(map = x86LoadMap()) || + !(host_model = x86ModelFromCPU(host, map, 0))) + goto cleanup; + + for (i = 0; i < guest->nfeatures; i++) { + if (guest->features[i].policy == VIR_CPU_FEATURE_OPTIONAL) { + const struct x86_feature *feature; + if (!(feature = x86FeatureFind(map, guest->features[i].name))) { + virCPUReportError(VIR_ERR_INTERNAL_ERROR, + _("Unknown CPU feature %s"), + guest->features[i].name); + goto cleanup; + } + + if (x86ModelHasFeature(host_model, feature)) + guest->features[i].policy = VIR_CPU_FEATURE_REQUIRE; + else + guest->features[i].policy = VIR_CPU_FEATURE_DISABLE; + } + } + + if (guest->match == VIR_CPU_MATCH_MINIMUM) { + guest->match = VIR_CPU_MATCH_EXACT; + if (x86ModelSubtractCPU(host_model, guest, map) + || !(data = x86DataFromModel(host_model)) + || x86DataToCPUFeatures(guest, VIR_CPU_FEATURE_REQUIRE, data, map)) + goto cleanup; + } + + ret = 0; + +cleanup: + x86MapFree(map); + x86ModelFree(host_model); + x86DataFree(data); + return ret; +} + + struct cpuArchDriver cpuDriverX86 = { .name = "x86", .arch = archs, @@ -1292,4 +1418,5 @@ struct cpuArchDriver cpuDriverX86 = { #endif .guestData = x86GuestData, .baseline = x86Baseline, + .update = x86Update, }; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f1ad6db..9c16a6d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -81,6 +81,7 @@ cpuDecode; cpuEncode; cpuGuestData; cpuNodeData; +cpuUpdate; # cpu_conf.h -- 1.7.0.3

On 03/26/2010 07:11 AM, Jiri Denemark wrote:
Useful mainly for migration. cpuUpdate changes guest CPU requirements in the following way:
- match == "strict" || match == "exact" - optional features which are supported by host CPU are changed into required features - optional features which are not supported by host CPU are disabled - all other features remain untouched - match == "minimum" - match is changed into "exact" - optional features and all features not mentioned in guest CPU specification which are supported by host CPU become required features - other optional features are disabled - oll other features remain untouched
s/oll/all/ Other than that, ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Fri, Mar 26, 2010 at 02:11:34PM +0100, Jiri Denemark wrote:
Useful mainly for migration. cpuUpdate changes guest CPU requirements in the following way:
- match == "strict" || match == "exact" - optional features which are supported by host CPU are changed into required features - optional features which are not supported by host CPU are disabled - all other features remain untouched - match == "minimum" - match is changed into "exact" - optional features and all features not mentioned in guest CPU specification which are supported by host CPU become required features - other optional features are disabled - oll other features remain untouched
This ensures that no feature will suddenly disappear from the guest after migration.
ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

--- src/conf/cpu_conf.c | 37 +++++++++++++++++++++++++++++++++++++ src/conf/cpu_conf.h | 3 +++ src/libvirt_private.syms | 1 + 3 files changed, 41 insertions(+), 0 deletions(-) diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 612e376..cf91930 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -67,6 +67,43 @@ virCPUDefFree(virCPUDefPtr def) } +virCPUDefPtr +virCPUDefCopy(const virCPUDefPtr cpu) +{ + virCPUDefPtr copy; + unsigned int i; + + if (!cpu) + return NULL; + + if (VIR_ALLOC(copy) < 0 + || (cpu->arch && !(copy->arch = strdup(cpu->arch))) + || (cpu->model && !(copy->model = strdup(cpu->model))) + || VIR_ALLOC_N(copy->features, cpu->nfeatures) < 0) + goto no_memory; + + copy->type = cpu->type; + copy->match = cpu->match; + copy->sockets = cpu->sockets; + copy->cores = cpu->cores; + copy->threads = cpu->threads; + copy->nfeatures = cpu->nfeatures; + + for (i = 0; i < copy->nfeatures; i++) { + copy->features[i].policy = cpu->features[i].policy; + if (!(copy->features[i].name = strdup(cpu->features[i].name))) + goto no_memory; + } + + return copy; + +no_memory: + virReportOOMError(); + virCPUDefFree(copy); + return NULL; +} + + #ifndef PROXY virCPUDefPtr virCPUDefParseXML(const xmlNodePtr node, diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index bb8a844..a30991d 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -83,6 +83,9 @@ struct _virCPUDef { void virCPUDefFree(virCPUDefPtr def); +virCPUDefPtr +virCPUDefCopy(const virCPUDefPtr cpu); + # ifndef PROXY virCPUDefPtr virCPUDefParseXML(const xmlNodePtr node, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 9c16a6d..0ae143c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -90,6 +90,7 @@ virCPUDefParseXML; virCPUDefFormat; virCPUDefFormatBuf; virCPUDefAddFeature; +virCPUDefCopy; # datatypes.h -- 1.7.0.3

On 03/26/2010 07:11 AM, Jiri Denemark wrote:
+virCPUDefPtr +virCPUDefCopy(const virCPUDefPtr cpu);
ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Fri, Mar 26, 2010 at 02:11:35PM +0100, Jiri Denemark wrote:
--- src/conf/cpu_conf.c | 37 +++++++++++++++++++++++++++++++++++++ src/conf/cpu_conf.h | 3 +++ src/libvirt_private.syms | 1 + 3 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 612e376..cf91930 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -67,6 +67,43 @@ virCPUDefFree(virCPUDefPtr def) }
+virCPUDefPtr +virCPUDefCopy(const virCPUDefPtr cpu) +{ + virCPUDefPtr copy; + unsigned int i; + + if (!cpu) + return NULL; + + if (VIR_ALLOC(copy) < 0 + || (cpu->arch && !(copy->arch = strdup(cpu->arch))) + || (cpu->model && !(copy->model = strdup(cpu->model))) + || VIR_ALLOC_N(copy->features, cpu->nfeatures) < 0) + goto no_memory; + + copy->type = cpu->type; + copy->match = cpu->match; + copy->sockets = cpu->sockets; + copy->cores = cpu->cores; + copy->threads = cpu->threads; + copy->nfeatures = cpu->nfeatures; + + for (i = 0; i < copy->nfeatures; i++) { + copy->features[i].policy = cpu->features[i].policy; + if (!(copy->features[i].name = strdup(cpu->features[i].name))) + goto no_memory; + } + + return copy; + +no_memory: + virReportOOMError(); + virCPUDefFree(copy); + return NULL; +} +
Somehow I was expecting something recursive due to deep-copy title ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

This flag is used in migration prepare step to send updated XML definition of a guest. Also ``virsh dumpxml --update-cpu [--inactive] guest'' command can be used to see the updated CPU requirements. --- include/libvirt/libvirt.h.in | 5 ++- src/libvirt.c | 3 +- src/qemu/qemu_driver.c | 54 +++++++++++++++++++++++++++++++++++------ tools/virsh.c | 4 +++ 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index aaefa09..d22443e 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -686,8 +686,9 @@ int virDomainGetSecurityLabel (virDomainPtr domain, */ typedef enum { - VIR_DOMAIN_XML_SECURE = 1, /* dump security sensitive information too */ - VIR_DOMAIN_XML_INACTIVE = 2/* dump inactive domain information */ + VIR_DOMAIN_XML_SECURE = (1 << 0), /* dump security sensitive information too */ + VIR_DOMAIN_XML_INACTIVE = (1 << 1), /* dump inactive domain information */ + VIR_DOMAIN_XML_UPDATE_CPU = (1 << 2), /* update guest CPU requirements to match the CPU the guest is currently running on */ } virDomainXMLFlags; char * virDomainGetXMLDesc (virDomainPtr domain, diff --git a/src/libvirt.c b/src/libvirt.c index 7b74fd9..e540630 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -3176,7 +3176,8 @@ virDomainMigrateVersion2 (virDomainPtr domain, return NULL; } dom_xml = domain->conn->driver->domainDumpXML (domain, - VIR_DOMAIN_XML_SECURE); + VIR_DOMAIN_XML_SECURE | + VIR_DOMAIN_XML_UPDATE_CPU); if (!dom_xml) return NULL; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2c81d68..9e133b6 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5350,6 +5350,44 @@ cleanup: } +static char *qemudVMDumpXML(struct qemud_driver *driver, + virDomainObjPtr vm, + int flags) +{ + char *ret = NULL; + virCPUDefPtr cpu = NULL; + virDomainDefPtr def; + virCPUDefPtr def_cpu; + + if ((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef) + def = vm->newDef; + else + def = vm->def; + def_cpu = def->cpu; + + /* Update guest CPU requirements according to host CPU */ + if ((flags & VIR_DOMAIN_XML_UPDATE_CPU) && def_cpu && def_cpu->model) { + if (!driver->caps || !driver->caps->host.cpu) { + qemuReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("cannot get host CPU capabilities")); + goto cleanup; + } + + if (!(cpu = virCPUDefCopy(def_cpu)) + || cpuUpdate(cpu, driver->caps->host.cpu)) + goto cleanup; + def->cpu = cpu; + } + + ret = virDomainDefFormat(def, flags); + +cleanup: + def->cpu = def_cpu; + virCPUDefFree(cpu); + return ret; +} + + static char *qemudDomainDumpXML(virDomainPtr dom, int flags) { struct qemud_driver *driver = dom->conn->privateData; @@ -5360,7 +5398,6 @@ static char *qemudDomainDumpXML(virDomainPtr dom, qemuDriverLock(driver); vm = virDomainFindByUUID(&driver->domains, dom->uuid); - qemuDriverUnlock(driver); if (!vm) { char uuidstr[VIR_UUID_STRING_BUFLEN]; @@ -5376,12 +5413,12 @@ static char *qemudDomainDumpXML(virDomainPtr dom, /* Don't delay if someone's using the monitor, just use * existing most recent data instead */ if (!priv->jobActive) { - if (qemuDomainObjBeginJob(vm) < 0) + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) goto cleanup; - qemuDomainObjEnterMonitor(vm); + qemuDomainObjEnterMonitorWithDriver(driver, vm); err = qemuMonitorGetBalloonInfo(priv->mon, &balloon); - qemuDomainObjExitMonitor(vm); + qemuDomainObjExitMonitorWithDriver(driver, vm); if (qemuDomainObjEndJob(vm) == 0) { vm = NULL; goto cleanup; @@ -5394,13 +5431,12 @@ static char *qemudDomainDumpXML(virDomainPtr dom, } } - ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ? - vm->newDef : vm->def, - flags); + ret = qemudVMDumpXML(driver, vm, flags); cleanup: if (vm) virDomainObjUnlock(vm); + qemuDriverUnlock(driver); return ret; } @@ -9050,7 +9086,9 @@ static int doPeer2PeerMigrate(virDomainPtr dom, goto cleanup; } - dom_xml = virDomainDefFormat(vm->def, VIR_DOMAIN_XML_SECURE); + dom_xml = qemudVMDumpXML(driver, vm, + VIR_DOMAIN_XML_SECURE | + VIR_DOMAIN_XML_UPDATE_CPU); if (!dom_xml) { qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to get domain xml")); diff --git a/tools/virsh.c b/tools/virsh.c index 32895b2..95a7f7e 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -2504,6 +2504,7 @@ static const vshCmdOptDef opts_dumpxml[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, {"inactive", VSH_OT_BOOL, 0, N_("show inactive defined XML")}, {"security-info", VSH_OT_BOOL, 0, N_("include security sensitive information in XML dump")}, + {"update-cpu", VSH_OT_BOOL, 0, N_("update guest CPU according to host CPU")}, {NULL, 0, 0, NULL} }; @@ -2516,11 +2517,14 @@ cmdDumpXML(vshControl *ctl, const vshCmd *cmd) int flags = 0; int inactive = vshCommandOptBool(cmd, "inactive"); int secure = vshCommandOptBool(cmd, "security-info"); + int update = vshCommandOptBool(cmd, "update-cpu"); if (inactive) flags |= VIR_DOMAIN_XML_INACTIVE; if (secure) flags |= VIR_DOMAIN_XML_SECURE; + if (update) + flags |= VIR_DOMAIN_XML_UPDATE_CPU; if (!vshConnectionUsability(ctl, ctl->conn, TRUE)) return FALSE; -- 1.7.0.3

On 03/26/2010 07:11 AM, Jiri Denemark wrote:
This flag is used in migration prepare step to send updated XML definition of a guest.
Also ``virsh dumpxml --update-cpu [--inactive] guest'' command can be used to see the updated CPU requirements.
+++ b/tools/virsh.c @@ -2504,6 +2504,7 @@ static const vshCmdOptDef opts_dumpxml[] = { {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, {"inactive", VSH_OT_BOOL, 0, N_("show inactive defined XML")}, {"security-info", VSH_OT_BOOL, 0, N_("include security sensitive information in XML dump")}, + {"update-cpu", VSH_OT_BOOL, 0, N_("update guest CPU according to host CPU")}, {NULL, 0, 0, NULL} };
ACK, but could you also update tools/libvirsh.pod to mention this in the man page (either rebase this patch, or a followup patch)? -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Fri, Mar 26, 2010 at 02:11:36PM +0100, Jiri Denemark wrote:
This flag is used in migration prepare step to send updated XML definition of a guest.
Also ``virsh dumpxml --update-cpu [--inactive] guest'' command can be used to see the updated CPU requirements. --- include/libvirt/libvirt.h.in | 5 ++- src/libvirt.c | 3 +- src/qemu/qemu_driver.c | 54 +++++++++++++++++++++++++++++++++++------ tools/virsh.c | 4 +++ 4 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index aaefa09..d22443e 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -686,8 +686,9 @@ int virDomainGetSecurityLabel (virDomainPtr domain, */
typedef enum { - VIR_DOMAIN_XML_SECURE = 1, /* dump security sensitive information too */ - VIR_DOMAIN_XML_INACTIVE = 2/* dump inactive domain information */ + VIR_DOMAIN_XML_SECURE = (1 << 0), /* dump security sensitive information too */ + VIR_DOMAIN_XML_INACTIVE = (1 << 1), /* dump inactive domain information */ + VIR_DOMAIN_XML_UPDATE_CPU = (1 << 2), /* update guest CPU requirements to match the CPU the guest is currently running on */ } virDomainXMLFlags;
Somehow this is not an enum anymore since we logically or the values, but it is not a serious problem. ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

typedef enum { - VIR_DOMAIN_XML_SECURE = 1, /* dump security sensitive information too */ - VIR_DOMAIN_XML_INACTIVE = 2/* dump inactive domain information */ + VIR_DOMAIN_XML_SECURE = (1 << 0), /* dump security sensitive information too */ + VIR_DOMAIN_XML_INACTIVE = (1 << 1), /* dump inactive domain information */ + VIR_DOMAIN_XML_UPDATE_CPU = (1 << 2), /* update guest CPU requirements to match the CPU the guest is currently running on */ } virDomainXMLFlags;
Somehow this is not an enum anymore since we logically or the values, but it is not a serious problem.
It's been so for ever. This visual renumbering just makes it more visible to avoid adding new item with inappropriate value. Jirka

Jiri Denemark (3): cpuUpdate() for updating guest CPU according to host CPU Helper function for making a deep-copy of virCPUDefPtr Introduce UPDATE_CPU flag for virDomainGetXMLDesc
I fixed the typo in commit message in 1/3 and pushed these patches. The documentation patch for virsh.pod will be done as a follow up patch. Jirka
participants (3)
-
Daniel Veillard
-
Eric Blake
-
Jiri Denemark