If the QEMU driver restarts it loses the track of the actual size
of virtio-mem (because it's runtime type of information and thus
not stored in XML) and therefore, we have to refresh it when
reconnecting to the domain monitor.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_domain.c | 37 ++++++++++++++++++++----
src/qemu/qemu_monitor.h | 3 ++
src/qemu/qemu_monitor_json.c | 56 ++++++++++++++++++++++--------------
src/qemu/qemu_process.c | 3 ++
4 files changed, 72 insertions(+), 27 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 7de9f8c050..3275514908 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -8096,9 +8096,21 @@ qemuDomainUpdateMemoryDeviceInfo(virQEMUDriverPtr driver,
return -1;
}
- /* if qemu doesn't support the info request, just carry on */
- if (rc == -2)
+ /* If qemu doesn't support the info request, just carry on, unless we
+ * really need it. */
+ if (rc == -2) {
+ for (i = 0; i < vm->def->nmems; i++) {
+ virDomainMemoryDefPtr mem = vm->def->mems[i];
+
+ if (mem->model == VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qemu did not return info on vitio-mem
device"));
+ return -1;
+ }
+ }
+
return 0;
+ }
if (rc < 0)
return -1;
@@ -8113,9 +8125,24 @@ qemuDomainUpdateMemoryDeviceInfo(virQEMUDriverPtr driver,
if (!(dimm = virHashLookup(meminfo, mem->info.alias)))
continue;
- mem->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM;
- mem->info.addr.dimm.slot = dimm->slot;
- mem->info.addr.dimm.base = dimm->address;
+ switch (mem->model) {
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_MEM:
+ mem->actualsize = VIR_DIV_UP(dimm->size, 1024);
+ break;
+
+ case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+ case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
+ mem->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM;
+ mem->info.addr.dimm.slot = dimm->slot;
+ mem->info.addr.dimm.base = dimm->address;
+ break;
+
+ case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
+ case VIR_DOMAIN_MEMORY_MODEL_NONE:
+ case VIR_DOMAIN_MEMORY_MODEL_LAST:
+ /* nada */
+ break;
+ }
}
virHashFree(meminfo);
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 53f2aa9600..c369b8c6ef 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1393,10 +1393,13 @@ typedef struct _qemuMonitorMemoryDeviceInfo
qemuMonitorMemoryDeviceInfo;
typedef qemuMonitorMemoryDeviceInfo *qemuMonitorMemoryDeviceInfoPtr;
struct _qemuMonitorMemoryDeviceInfo {
+ /* For pc-dimm */
unsigned long long address;
unsigned int slot;
bool hotplugged;
bool hotpluggable;
+ /* For virtio-mem */
+ unsigned long long size; /* in bytes */
};
int qemuMonitorGetMemoryDeviceInfo(qemuMonitorPtr mon,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 9ce7ba52ba..09e898442d 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -8238,7 +8238,6 @@ qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
virJSONValuePtr data = NULL;
- qemuMonitorMemoryDeviceInfoPtr meminfo = NULL;
size_t i;
if (!(cmd = qemuMonitorJSONMakeCommand("query-memory-devices", NULL)))
@@ -8259,6 +8258,9 @@ qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
for (i = 0; i < virJSONValueArraySize(data); i++) {
virJSONValuePtr elem = virJSONValueArrayGet(data, i);
+ g_autofree qemuMonitorMemoryDeviceInfoPtr meminfo = NULL;
+ virJSONValuePtr dimminfo;
+ const char *devalias;
const char *type;
if (!(type = virJSONValueObjectGetString(elem, "type"))) {
@@ -8268,26 +8270,17 @@ qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
goto cleanup;
}
+ if (!(dimminfo = virJSONValueObjectGetObject(elem, "data"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("query-memory-devices reply data doesn't "
+ "contain enum data"));
+ goto cleanup;
+ }
+
+ meminfo = g_new0(qemuMonitorMemoryDeviceInfo, 1);
+
/* dimm memory devices */
if (STREQ(type, "dimm")) {
- virJSONValuePtr dimminfo;
- const char *devalias;
-
- if (!(dimminfo = virJSONValueObjectGetObject(elem, "data"))) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("query-memory-devices reply data doesn't
"
- "contain enum data"));
- goto cleanup;
- }
-
- if (!(devalias = virJSONValueObjectGetString(dimminfo, "id"))) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("dimm memory info data is missing
'id'"));
- goto cleanup;
- }
-
- meminfo = g_new0(qemuMonitorMemoryDeviceInfo, 1);
-
if (virJSONValueObjectGetNumberUlong(dimminfo, "addr",
&meminfo->address) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -8318,17 +8311,36 @@ qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
}
- if (virHashAddEntry(info, devalias, meminfo) < 0)
+ } else if (STREQ(type, "virtio-mem")) {
+ /* While 'id' attribute is marked as optional in QEMU's QAPI
+ * specification, Libvirt always sets it. Thus we can fail if not
+ * present. */
+ if (!(devalias = virJSONValueObjectGetString(dimminfo, "id"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("dimm memory info data is missing
'id'"));
goto cleanup;
+ }
- meminfo = NULL;
+ if (virJSONValueObjectGetNumberUlong(dimminfo, "size",
+ &meminfo->size) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed/missing slot in dimm memory
info"));
+ goto cleanup;
+ }
+ } else {
+ /* type not handled yet */
+ continue;
}
+
+ if (virHashAddEntry(info, devalias, meminfo) < 0)
+ goto cleanup;
+
+ meminfo = NULL;
}
ret = 0;
cleanup:
- VIR_FREE(meminfo);
virJSONValueFree(cmd);
virJSONValueFree(reply);
return ret;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4ab085841a..5881511218 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -8523,6 +8523,9 @@ qemuProcessReconnect(void *opaque)
qemuDomainVcpuPersistOrder(obj->def);
+ if (qemuDomainUpdateMemoryDeviceInfo(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
+ goto error;
+
if (qemuProcessDetectIOThreadPIDs(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
goto error;
--
2.26.2