[PATCH v1 24/26] qemu: Refresh the actual size of virtio-mem on monitor reconnect

Michal Privoznik mprivozn at redhat.com
Fri Nov 27 15:03:10 UTC 2020


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 at redhat.com>
---
 src/qemu/qemu_domain.c       | 36 +++++++++++++++++++----
 src/qemu/qemu_monitor.h      |  3 ++
 src/qemu/qemu_monitor_json.c | 55 +++++++++++++++++++++---------------
 src/qemu/qemu_process.c      |  3 ++
 4 files changed, 69 insertions(+), 28 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index fc994ec282..3cd5708548 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -7845,9 +7845,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) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("qemu did not return info on vitio-mem device"));
+                return -1;
+            }
+        }
+
         return 0;
+    }
 
     if (rc < 0)
         return -1;
@@ -7862,9 +7874,23 @@ 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->actualsize = 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_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 63c52ce6e8..3a0bd6b79d 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1402,10 +1402,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;
 };
 
 int qemuMonitorGetMemoryDeviceInfo(qemuMonitorPtr mon,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 0c050b27b7..39089fe3e6 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -8409,7 +8409,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)))
@@ -8430,6 +8429,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"))) {
@@ -8439,26 +8441,23 @@ 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;
+        }
+
+        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);
+
         /* 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",
@@ -8489,17 +8488,27 @@ qemuMonitorJSONGetMemoryDeviceInfo(qemuMonitorPtr mon,
 
             }
 
-            if (virHashAddEntry(info, devalias, meminfo) < 0)
+        } else if (STREQ(type, "virtio-mem")) {
+            if (virJSONValueObjectGetNumberUlong(dimminfo, "size",
+                                                 &meminfo->size) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("malformed/missing slot in dimm memory info"));
                 goto cleanup;
-
-            meminfo = NULL;
+            }
+        } 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 64576377b8..fb77c6b9d9 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -8478,6 +8478,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




More information about the libvir-list mailing list