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;
void *parseOpaque)
{
int ret;
+ bool localParseOpaque = false;
struct virDomainDefPostParseDeviceIteratorData data = {
.caps = caps,
.xmlopt = xmlopt,
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
*/
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 */
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;
}
}
/* 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 */
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. */
struct _virDomainDefParserConfig {
/* driver domain definition callbacks */
virDomainDefPostParseBasicCallback domainPostParseBasicCallback;
+ virDomainDefPostParseDataAlloc domainPostParseDataAlloc;
virDomainDefPostParseCallback domainPostParseCallback;
virDomainDeviceDefPostParseCallback devicesPostParseCallback;
virDomainDefAssignAddressesCallback assignAddressesCallback;
+ virDomainDefPostParseDataFree domainPostParseDataFree;
/* validation callbacks */
virDomainDefValidateCallback domainValidateCallback;