diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index d78f846a52..04c10df0a9 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -15369,7 +15369,7 @@ virDomainHostdevMatchCaps(virDomainHostdevDef *a, } -static int +int virDomainHostdevMatch(virDomainHostdevDef *a, virDomainHostdevDef *b) { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f706c498ff..4d9d499b16 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3590,6 +3590,8 @@ virDomainHostdevDef * virDomainHostdevRemove(virDomainDef *def, size_t i); int virDomainHostdevFind(virDomainDef *def, virDomainHostdevDef *match, virDomainHostdevDef **found); +int virDomainHostdevMatch(virDomainHostdevDef *a, + virDomainHostdevDef *b); virDomainGraphicsListenDef * virDomainGraphicsGetListen(virDomainGraphicsDef *def, size_t i); diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 2124d25d16..df2ab47361 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -1068,7 +1068,25 @@ virDomainDefDuplicateDiskInfoValidate(const virDomainDef *def) return 0; } +static int +virDomainDefDuplicateHostdevInfoValidate(const virDomainDef *def) +{ + size_t i; + size_t j; + for (i = 0; i < def->nhostdevs; i++) { + for (j = i + 1; j < def->nhostdevs; j++) { + if (virDomainHostdevMatch(def->hostdevs[i], + def->hostdevs[j])) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Hostdev already exists in the domain configuration")); + return -1; + } + } + } + + return 0; +} /** * virDomainDefDuplicateDriveAddressesValidate: @@ -1529,6 +1547,9 @@ virDomainDefValidateInternal(const virDomainDef *def, if (virDomainDefDuplicateDiskInfoValidate(def) < 0) return -1; + if (virDomainDefDuplicateHostdevInfoValidate(def) < 0) + return -1; + if (virDomainDefDuplicateDriveAddressesValidate(def) < 0) return -1; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 68e4b6aab8..43e6398ae5 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -457,6 +457,7 @@ virDomainHostdevDefFree; virDomainHostdevDefNew; virDomainHostdevFind; virDomainHostdevInsert; +virDomainHostdevMatch; virDomainHostdevModeTypeToString; virDomainHostdevRemove; virDomainHostdevSubsysPCIBackendTypeToString; diff --git a/tests/qemuxml2argvdata/hostdev-mdev-duplicate.err b/tests/qemuxml2argvdata/hostdev-mdev-duplicate.err new file mode 100644 index 0000000000..590afd30f0 --- /dev/null +++ b/tests/qemuxml2argvdata/hostdev-mdev-duplicate.err @@ -0,0 +1 @@ +XML error: Hostdev already exists in the domain configuration diff --git a/tests/qemuxml2argvdata/hostdev-mdev-duplicate.xml b/tests/qemuxml2argvdata/hostdev-mdev-duplicate.xml new file mode 100644 index 0000000000..1c5e326381 --- /dev/null +++ b/tests/qemuxml2argvdata/hostdev-mdev-duplicate.xml @@ -0,0 +1,41 @@ + + QEMUGuest2 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-i386 + +
+ + + +
+ + + +