diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b7519c8b34..bd4e333953 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4675,6 +4675,31 @@ virDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, return 0; } +static int +virDomainDeviceDefPostParseOne(virDomainDeviceDefPtr dev, + const virDomainDef *def, + virCapsPtr caps, + unsigned int flags, + virDomainXMLOptionPtr xmlopt) +{ + void *parseOpaque = NULL; + int ret; + + if (xmlopt->config.domainPostParseDataAlloc) { + if (xmlopt->config.domainPostParseDataAlloc(def, caps, flags, + xmlopt->config.priv, + &parseOpaque) < 0) + return -1; + } + + ret = virDomainDeviceDefPostParse(dev, def, caps, flags, xmlopt, parseOpaque); + + if (parseOpaque && xmlopt->config.domainPostParseDataFree) + xmlopt->config.domainPostParseDataFree(parseOpaque); + + return ret; +} + struct virDomainDefPostParseDeviceIteratorData { virCapsPtr caps; @@ -4821,6 +4846,7 @@ virDomainDefPostParse(virDomainDefPtr def, void *parseOpaque) { int ret; + bool localParseOpaque = false; struct virDomainDefPostParseDeviceIteratorData data = { .caps = caps, .xmlopt = xmlopt, @@ -4837,6 +4863,17 @@ virDomainDefPostParse(virDomainDefPtr def, return ret; } + if (!data.parseOpaque && + xmlopt->config.domainPostParseDataAlloc) { + ret = xmlopt->config.domainPostParseDataAlloc(def, caps, parseFlags, + xmlopt->config.priv, + &data.parseOpaque); + + if (ret < 0) + return ret; + localParseOpaque = true; + } + /* this must be done before the hypervisor-specific callback, * in case presence of a controller at a specific index is checked */ @@ -4846,9 +4883,9 @@ virDomainDefPostParse(virDomainDefPtr def, if (xmlopt->config.domainPostParseCallback) { ret = xmlopt->config.domainPostParseCallback(def, caps, parseFlags, xmlopt->config.priv, - parseOpaque); + data.parseOpaque); if (ret < 0) - return ret; + goto cleanup; } /* iterate the devices */ @@ -4856,24 +4893,30 @@ virDomainDefPostParse(virDomainDefPtr def, virDomainDefPostParseDeviceIterator, true, &data)) < 0) - return ret; + goto cleanup; if ((ret = virDomainDefPostParseInternal(def, &data)) < 0) - return ret; + goto cleanup; if (xmlopt->config.assignAddressesCallback) { ret = xmlopt->config.assignAddressesCallback(def, caps, parseFlags, xmlopt->config.priv, - parseOpaque); + data.parseOpaque); if (ret < 0) - return ret; + goto cleanup; } - if (virDomainDefPostParseCheckFeatures(def, xmlopt) < 0) - return -1; + if ((ret = virDomainDefPostParseCheckFeatures(def, xmlopt)) < 0) + goto cleanup; - return 0; + ret = 0; + + cleanup: + if (localParseOpaque && xmlopt->config.domainPostParseDataFree) + xmlopt->config.domainPostParseDataFree(data.parseOpaque); + + return ret; } @@ -14679,7 +14722,7 @@ virDomainDeviceDefParse(const char *xmlStr, } /* callback to fill driver specific device aspects */ - if (virDomainDeviceDefPostParse(dev, def, caps, flags, xmlopt, NULL) < 0) + if (virDomainDeviceDefPostParseOne(dev, def, caps, flags, xmlopt) < 0) goto error; /* validate the configuration */ diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index bb5faa8b8e..956996fdd7 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -2538,6 +2538,13 @@ typedef int (*virDomainDefAssignAddressesCallback)(virDomainDef *def, void *opaque, void *parseOpaque); +typedef int (*virDomainDefPostParseDataAlloc)(const virDomainDef *def, + virCapsPtr caps, + unsigned int parseFlags, + void *opaque, + void **parseOpaque); +typedef void (*virDomainDefPostParseDataFree)(void *parseOpaque); + /* Called in appropriate places where the domain conf parser can return failure * for configurations that were previously accepted. This shall not modify the * config. */ @@ -2556,9 +2563,11 @@ typedef virDomainDefParserConfig *virDomainDefParserConfigPtr; struct _virDomainDefParserConfig { /* driver domain definition callbacks */ virDomainDefPostParseBasicCallback domainPostParseBasicCallback; + virDomainDefPostParseDataAlloc domainPostParseDataAlloc; virDomainDefPostParseCallback domainPostParseCallback; virDomainDeviceDefPostParseCallback devicesPostParseCallback; virDomainDefAssignAddressesCallback assignAddressesCallback; + virDomainDefPostParseDataFree domainPostParseDataFree; /* validation callbacks */ virDomainDefValidateCallback domainValidateCallback;