Since I haven't pushed the series yet, I can easily squash the following patch into patch 2/4. Jirka >From 5302f9ca43e26bd23230ba84e169a0e9109d04e8 Mon Sep 17 00:00:00 2001 Message-Id: <5302f9ca43e26bd23230ba84e169a0e9109d04e8.1295268171.git.jdenemar@xxxxxxxxxx> From: Jiri Denemark <jdenemar@xxxxxxxxxx> Date: Mon, 17 Jan 2011 13:25:31 +0100 Subject: [PATCH] Check that boot order sequence is correct Mail-Followup-To: libvir-list@xxxxxxxxxx The boot order sequence has to be contiguous starting from 1 and without duplicates. --- src/conf/domain_conf.c | 66 ++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 53 insertions(+), 13 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index bf8c5fa..645767e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -46,6 +46,7 @@ #include "ignore-value.h" #include "storage_file.h" #include "files.h" +#include "bitmap.h" #define VIR_FROM_THIS VIR_FROM_DOMAIN @@ -1531,7 +1532,8 @@ cleanup: static int virDomainDeviceBootParseXML(xmlNodePtr node, - int *bootIndex) + int *bootIndex, + virBitmapPtr bootMap) { char *order; int boot; @@ -1550,6 +1552,20 @@ virDomainDeviceBootParseXML(xmlNodePtr node, goto cleanup; } + if (bootMap) { + bool set; + if (virBitmapGetBit(bootMap, boot - 1, &set) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("boot orders have to be contiguous and starting from 1")); + goto cleanup; + } else if (set) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("boot order %d used for more than one device"), boot); + goto cleanup; + } + ignore_value(virBitmapSetBit(bootMap, boot - 1)); + } + *bootIndex = boot; ret = 0; @@ -1643,7 +1659,9 @@ virDomainDiskDefAssignAddress(virCapsPtr caps, virDomainDiskDefPtr def) static virDomainDiskDefPtr virDomainDiskDefParseXML(virCapsPtr caps, xmlNodePtr node, - int flags) { + virBitmapPtr bootMap, + int flags) +{ virDomainDiskDefPtr def; xmlNodePtr cur, host; char *type = NULL; @@ -1790,7 +1808,8 @@ virDomainDiskDefParseXML(virCapsPtr caps, (xmlStrEqual(cur->name, BAD_CAST "serial"))) { serial = (char *)xmlNodeGetContent(cur); } else if (xmlStrEqual(cur->name, BAD_CAST "boot")) { - if (virDomainDeviceBootParseXML(cur, &def->bootIndex)) + if (virDomainDeviceBootParseXML(cur, &def->bootIndex, + bootMap)) goto error; } } @@ -2329,7 +2348,9 @@ static virDomainNetDefPtr virDomainNetDefParseXML(virCapsPtr caps, xmlNodePtr node, xmlXPathContextPtr ctxt, - int flags ATTRIBUTE_UNUSED) { + virBitmapPtr bootMap, + int flags ATTRIBUTE_UNUSED) +{ virDomainNetDefPtr def; xmlNodePtr cur; char *macaddr = NULL; @@ -2440,7 +2461,8 @@ virDomainNetDefParseXML(virCapsPtr caps, /* Legacy back-compat. Don't add any more attributes here */ devaddr = virXMLPropString(cur, "devaddr"); } else if (xmlStrEqual(cur->name, BAD_CAST "boot")) { - if (virDomainDeviceBootParseXML(cur, &def->bootIndex)) + if (virDomainDeviceBootParseXML(cur, &def->bootIndex, + bootMap)) goto error; } } @@ -4429,7 +4451,8 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps, if (xmlStrEqual(node->name, BAD_CAST "disk")) { dev->type = VIR_DOMAIN_DEVICE_DISK; - if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node, flags))) + if (!(dev->data.disk = virDomainDiskDefParseXML(caps, node, + NULL, flags))) goto error; } else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) { dev->type = VIR_DOMAIN_DEVICE_FS; @@ -4437,7 +4460,8 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps, goto error; } else if (xmlStrEqual(node->name, BAD_CAST "interface")) { dev->type = VIR_DOMAIN_DEVICE_NET; - if (!(dev->data.net = virDomainNetDefParseXML(caps, node, ctxt, flags))) + if (!(dev->data.net = virDomainNetDefParseXML(caps, node, ctxt, + NULL, flags))) goto error; } else if (xmlStrEqual(node->name, BAD_CAST "input")) { dev->type = VIR_DOMAIN_DEVICE_INPUT; @@ -4708,15 +4732,21 @@ static char *virDomainDefDefaultEmulator(virDomainDefPtr def, static int virDomainDefParseBootXML(xmlXPathContextPtr ctxt, - virDomainDefPtr def) + virDomainDefPtr def, + unsigned long *bootCount) { xmlNodePtr *nodes = NULL; int i, n; char *bootstr; int ret = -1; - bool deviceBoot; + unsigned long deviceBoot; - deviceBoot = virXPathBoolean("boolean(./devices/*/boot)", ctxt) > 0; + if (virXPathULong("count(./devices/disk[boot]" + "|./devices/interface[boot])", ctxt, &deviceBoot) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot count boot devices")); + goto cleanup; + } /* analysis of the boot devices */ if ((n = virXPathNodeSet("./os/boot", ctxt, &nodes)) < 0) { @@ -4764,6 +4794,7 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt, VIR_FREE(bootstr); } + *bootCount = deviceBoot; ret = 0; cleanup: @@ -4784,6 +4815,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, virDomainDefPtr def; unsigned long count; bool uuid_generated = false; + virBitmapPtr bootMap = NULL; + unsigned long bootMapSize = 0; if (VIR_ALLOC(def) < 0) { virReportOOMError(); @@ -5100,9 +5133,11 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, def->os.loader = virXPathString("string(./os/loader[1])", ctxt); } - if (STREQ(def->os.type, "hvm") && - virDomainDefParseBootXML(ctxt, def) < 0) { - goto error; + if (STREQ(def->os.type, "hvm")) { + if (virDomainDefParseBootXML(ctxt, def, &bootMapSize) < 0) + goto error; + if (bootMapSize && !(bootMap = virBitmapAlloc(bootMapSize))) + goto no_memory; } def->emulator = virXPathString("string(./devices/emulator[1])", ctxt); @@ -5123,6 +5158,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, for (i = 0 ; i < n ; i++) { virDomainDiskDefPtr disk = virDomainDiskDefParseXML(caps, nodes[i], + bootMap, flags); if (!disk) goto error; @@ -5179,6 +5215,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, virDomainNetDefPtr net = virDomainNetDefParseXML(caps, nodes[i], ctxt, + bootMap, flags); if (!net) goto error; @@ -5578,6 +5615,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, if (virDomainDefAddImplicitControllers(def) < 0) goto error; + virBitmapFree(bootMap); + return def; no_memory: @@ -5587,6 +5626,7 @@ no_memory: error: VIR_FREE(tmp); VIR_FREE(nodes); + virBitmapFree(bootMap); virDomainDefFree(def); return NULL; } -- 1.7.4.rc2 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list