[libvirt] [PATCH v2 5/4] Check that boot order sequence is correct

Jiri Denemark jdenemar at redhat.com
Mon Jan 17 12:46:09 UTC 2011


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 at redhat.com>
From: Jiri Denemark <jdenemar at redhat.com>
Date: Mon, 17 Jan 2011 13:25:31 +0100
Subject: [PATCH] Check that boot order sequence is correct
Mail-Followup-To: libvir-list at redhat.com

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





More information about the libvir-list mailing list