When hot-plug a memory device, we don't check if there
is a memory device have the same address with the memory device
we want hot-pluged. Qemu forbid use/hot-plug 2 memory device
with same slot or the same base(qemu side this elemnt named addr).
Introduce a address check when build memory device qemu command line.
Signed-off-by: Luyao Huang <lhuang(a)redhat.com>
---
v2:
move the check to qemuBuildMemoryDeviceStr() to check the dimm address
when start/hot-plug a memory device.
src/qemu/qemu_command.c | 77 ++++++++++++++++++++++++++++++++++++-------------
1 file changed, 57 insertions(+), 20 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index d8ce511..0380a3b 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4955,6 +4955,61 @@ qemuBuildMemoryDimmBackendStr(virDomainMemoryDefPtr mem,
}
+static int
+qemuBuildMemoryDeviceAddr(virBuffer *buf,
+ virDomainDefPtr def,
+ virDomainMemoryDefPtr mem)
+{
+ ssize_t i;
+
+ if (mem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+ return 0;
+
+ if (mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("only 'dimm' addresses are supported for the
"
+ "pc-dimm device"));
+ return -1;
+ }
+
+ if (mem->info.addr.dimm.slot >= def->mem.memory_slots) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("memory device slot '%u' exceeds slots count
'%u'"),
+ mem->info.addr.dimm.slot, def->mem.memory_slots);
+ return -1;
+ }
+
+ for (i = 0; i < def->nmems; i++) {
+ virDomainMemoryDefPtr tmp = def->mems[i];
+
+ if (tmp == mem ||
+ tmp->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM)
+ continue;
+
+ if (mem->info.addr.dimm.slot == tmp->info.addr.dimm.slot) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("memory device slot '%u' already been"
+ " used by other memory device"),
+ mem->info.addr.dimm.slot);
+ return -1;
+ }
+
+ if (mem->info.addr.dimm.base != 0 && tmp->info.addr.dimm.base != 0
&&
+ mem->info.addr.dimm.base == tmp->info.addr.dimm.base) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("memory device base '0x%llx' already
been"
+ " used by other memory device"),
+ mem->info.addr.dimm.base);
+ return -1;
+ }
+ }
+
+ virBufferAsprintf(buf, ",slot=%d", mem->info.addr.dimm.slot);
+ virBufferAsprintf(buf, ",addr=%llu", mem->info.addr.dimm.base);
+
+ return 0;
+}
+
char *
qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem,
virDomainDefPtr def,
@@ -4976,29 +5031,11 @@ qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem,
return NULL;
}
- if (mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM &&
- mem->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("only 'dimm' addresses are supported for the
"
- "pc-dimm device"));
- return NULL;
- }
-
- if (mem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM &&
- mem->info.addr.dimm.slot >= def->mem.memory_slots) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("memory device slot '%u' exceeds slots count
'%u'"),
- mem->info.addr.dimm.slot, def->mem.memory_slots);
- return NULL;
- }
-
virBufferAsprintf(&buf, "pc-dimm,node=%d,memdev=mem%s,id=%s",
mem->targetNode, mem->info.alias, mem->info.alias);
- if (mem->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM) {
- virBufferAsprintf(&buf, ",slot=%d",
mem->info.addr.dimm.slot);
- virBufferAsprintf(&buf, ",addr=%llu",
mem->info.addr.dimm.base);
- }
+ if (qemuBuildMemoryDeviceAddr(&buf, def, mem) < 0)
+ return NULL;
break;
--
1.8.3.1