conf: Allow for non-contiguous device boot orders

This patch adds the ability to configure non-contiguous boot orders on boot
devices. This allows unplugging devices that have boot order specified without
breaking migration.

The new code now uses a slightly less memory efficient approach to store the
boot order fields in a hashtable instead of a bitmap.
This commit is contained in:
Peter Krempa 2013-04-04 15:29:16 +02:00
parent e7b0382945
commit 039a3283fc

View File

@ -3119,7 +3119,7 @@ cleanup:
static int static int
virDomainDeviceBootParseXML(xmlNodePtr node, virDomainDeviceBootParseXML(xmlNodePtr node,
int *bootIndex, int *bootIndex,
virBitmapPtr bootMap) virHashTablePtr bootHash)
{ {
char *order; char *order;
int boot; int boot;
@ -3138,18 +3138,16 @@ virDomainDeviceBootParseXML(xmlNodePtr node,
goto cleanup; goto cleanup;
} }
if (bootMap) { if (bootHash) {
bool set; if (virHashLookup(bootHash, order)) {
if (virBitmapGetBit(bootMap, boot - 1, &set) < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("boot order '%s' used for more than one device"),
_("boot orders have to be contiguous and starting from 1")); order);
goto cleanup;
} else if (set) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("boot order %d used for more than one device"), boot);
goto cleanup; goto cleanup;
} }
ignore_value(virBitmapSetBit(bootMap, boot - 1));
if (virHashAddEntry(bootHash, order, (void *) 1) < 0)
goto cleanup;
} }
*bootIndex = boot; *bootIndex = boot;
@ -3165,7 +3163,7 @@ cleanup:
*/ */
static int static int
virDomainDeviceInfoParseXML(xmlNodePtr node, virDomainDeviceInfoParseXML(xmlNodePtr node,
virBitmapPtr bootMap, virHashTablePtr bootHash,
virDomainDeviceInfoPtr info, virDomainDeviceInfoPtr info,
unsigned int flags) unsigned int flags)
{ {
@ -3216,7 +3214,7 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
} }
if (boot) { if (boot) {
if (virDomainDeviceBootParseXML(boot, &info->bootIndex, bootMap)) if (virDomainDeviceBootParseXML(boot, &info->bootIndex, bootHash))
goto cleanup; goto cleanup;
} }
@ -4237,7 +4235,7 @@ static virDomainDiskDefPtr
virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt, virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
xmlNodePtr node, xmlNodePtr node,
xmlXPathContextPtr ctxt, xmlXPathContextPtr ctxt,
virBitmapPtr bootMap, virHashTablePtr bootHash,
virSecurityLabelDefPtr* vmSeclabels, virSecurityLabelDefPtr* vmSeclabels,
int nvmSeclabels, int nvmSeclabels,
unsigned int flags) unsigned int flags)
@ -4968,7 +4966,7 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
} }
def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
} else { } else {
if (virDomainDeviceInfoParseXML(node, bootMap, &def->info, if (virDomainDeviceInfoParseXML(node, bootHash, &def->info,
flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT) < 0) flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT) < 0)
goto error; goto error;
} }
@ -5631,7 +5629,7 @@ static virDomainNetDefPtr
virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
xmlNodePtr node, xmlNodePtr node,
xmlXPathContextPtr ctxt, xmlXPathContextPtr ctxt,
virBitmapPtr bootMap, virHashTablePtr bootHash,
unsigned int flags) unsigned int flags)
{ {
virDomainNetDefPtr def; virDomainNetDefPtr def;
@ -5826,7 +5824,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
} }
def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
} else { } else {
if (virDomainDeviceInfoParseXML(node, bootMap, &def->info, if (virDomainDeviceInfoParseXML(node, bootHash, &def->info,
flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT
| VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) < 0) | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) < 0)
goto error; goto error;
@ -8278,7 +8276,7 @@ error:
static virDomainHostdevDefPtr static virDomainHostdevDefPtr
virDomainHostdevDefParseXML(const xmlNodePtr node, virDomainHostdevDefParseXML(const xmlNodePtr node,
xmlXPathContextPtr ctxt, xmlXPathContextPtr ctxt,
virBitmapPtr bootMap, virHashTablePtr bootHash,
unsigned int flags) unsigned int flags)
{ {
virDomainHostdevDefPtr def; virDomainHostdevDefPtr def;
@ -8319,7 +8317,7 @@ virDomainHostdevDefParseXML(const xmlNodePtr node,
} }
if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
if (virDomainDeviceInfoParseXML(node, bootMap, def->info, if (virDomainDeviceInfoParseXML(node, bootHash, def->info,
flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT
| VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) < 0) | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) < 0)
goto error; goto error;
@ -8353,7 +8351,7 @@ error:
static virDomainRedirdevDefPtr static virDomainRedirdevDefPtr
virDomainRedirdevDefParseXML(const xmlNodePtr node, virDomainRedirdevDefParseXML(const xmlNodePtr node,
virBitmapPtr bootMap, virHashTablePtr bootHash,
unsigned int flags) unsigned int flags)
{ {
xmlNodePtr cur; xmlNodePtr cur;
@ -8403,7 +8401,7 @@ virDomainRedirdevDefParseXML(const xmlNodePtr node,
def->source.chr.data.spicevmc = VIR_DOMAIN_CHR_SPICEVMC_USBREDIR; def->source.chr.data.spicevmc = VIR_DOMAIN_CHR_SPICEVMC_USBREDIR;
} }
if (virDomainDeviceInfoParseXML(node, bootMap, &def->info, if (virDomainDeviceInfoParseXML(node, bootHash, &def->info,
flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT) < 0) flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT) < 0)
goto error; goto error;
@ -9405,8 +9403,7 @@ virDomainDefGetDefaultEmulator(virDomainDefPtr def,
static int static int
virDomainDefParseBootXML(xmlXPathContextPtr ctxt, virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
virDomainDefPtr def, virDomainDefPtr def)
unsigned long *bootCount)
{ {
xmlNodePtr *nodes = NULL; xmlNodePtr *nodes = NULL;
int i, n; int i, n;
@ -9503,7 +9500,6 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
def->os.bios.rt_set = true; def->os.bios.rt_set = true;
} }
*bootCount = deviceBoot;
ret = 0; ret = 0;
cleanup: cleanup:
@ -9701,8 +9697,7 @@ virDomainDefParseXML(xmlDocPtr xml,
virDomainDefPtr def; virDomainDefPtr def;
unsigned long count; unsigned long count;
bool uuid_generated = false; bool uuid_generated = false;
virBitmapPtr bootMap = NULL; virHashTablePtr bootHash = NULL;
unsigned long bootMapSize = 0;
xmlNodePtr cur; xmlNodePtr cur;
bool usb_none = false; bool usb_none = false;
bool usb_other = false; bool usb_other = false;
@ -10584,10 +10579,10 @@ virDomainDefParseXML(xmlDocPtr xml,
} }
if (STREQ(def->os.type, "hvm")) { if (STREQ(def->os.type, "hvm")) {
if (virDomainDefParseBootXML(ctxt, def, &bootMapSize) < 0) if (virDomainDefParseBootXML(ctxt, def) < 0)
goto error;
if (!(bootHash = virHashCreate(5, NULL)))
goto error; goto error;
if (bootMapSize && !(bootMap = virBitmapNew(bootMapSize)))
goto no_memory;
} }
def->emulator = virXPathString("string(./devices/emulator[1])", ctxt); def->emulator = virXPathString("string(./devices/emulator[1])", ctxt);
@ -10603,7 +10598,7 @@ virDomainDefParseXML(xmlDocPtr xml,
virDomainDiskDefPtr disk = virDomainDiskDefParseXML(xmlopt, virDomainDiskDefPtr disk = virDomainDiskDefParseXML(xmlopt,
nodes[i], nodes[i],
ctxt, ctxt,
bootMap, bootHash,
def->seclabels, def->seclabels,
def->nseclabels, def->nseclabels,
flags); flags);
@ -10703,7 +10698,7 @@ virDomainDefParseXML(xmlDocPtr xml,
virDomainNetDefPtr net = virDomainNetDefParseXML(xmlopt, virDomainNetDefPtr net = virDomainNetDefParseXML(xmlopt,
nodes[i], nodes[i],
ctxt, ctxt,
bootMap, bootHash,
flags); flags);
if (!net) if (!net)
goto error; goto error;
@ -11020,7 +11015,7 @@ virDomainDefParseXML(xmlDocPtr xml,
for (i = 0 ; i < n ; i++) { for (i = 0 ; i < n ; i++) {
virDomainHostdevDefPtr hostdev; virDomainHostdevDefPtr hostdev;
hostdev = virDomainHostdevDefParseXML(nodes[i], ctxt, bootMap, flags); hostdev = virDomainHostdevDefParseXML(nodes[i], ctxt, bootHash, flags);
if (!hostdev) if (!hostdev)
goto error; goto error;
@ -11136,7 +11131,7 @@ virDomainDefParseXML(xmlDocPtr xml,
goto no_memory; goto no_memory;
for (i = 0 ; i < n ; i++) { for (i = 0 ; i < n ; i++) {
virDomainRedirdevDefPtr redirdev = virDomainRedirdevDefParseXML(nodes[i], virDomainRedirdevDefPtr redirdev = virDomainRedirdevDefParseXML(nodes[i],
bootMap, bootHash,
flags); flags);
if (!redirdev) if (!redirdev)
goto error; goto error;
@ -11257,7 +11252,7 @@ virDomainDefParseXML(xmlDocPtr xml,
if (virDomainDefPostParse(def, caps, xmlopt) < 0) if (virDomainDefPostParse(def, caps, xmlopt) < 0)
goto error; goto error;
virBitmapFree(bootMap); virHashFree(bootHash);
return def; return def;
@ -11266,7 +11261,7 @@ no_memory:
error: error:
VIR_FREE(tmp); VIR_FREE(tmp);
VIR_FREE(nodes); VIR_FREE(nodes);
virBitmapFree(bootMap); virHashFree(bootHash);
virDomainDefFree(def); virDomainDefFree(def);
return NULL; return NULL;
} }