|
|
9119d9 |
From abecf1fdcf58796b048eeaa6ccecc39f19ffdbcd Mon Sep 17 00:00:00 2001
|
|
|
9119d9 |
Message-Id: <abecf1fdcf58796b048eeaa6ccecc39f19ffdbcd@dist-git>
|
|
|
9119d9 |
From: Pavel Hrdina <phrdina@redhat.com>
|
|
|
9119d9 |
Date: Wed, 14 Jan 2015 13:38:27 +0100
|
|
|
9119d9 |
Subject: [PATCH] qemu_process: detect updated video ram size values from QEMU
|
|
|
9119d9 |
|
|
|
9119d9 |
QEMU internally updates the size of video memory if the domain XML had
|
|
|
9119d9 |
provided too low memory size or there are some dependencies for a QXL
|
|
|
9119d9 |
devices 'vgamem' and 'ram' size. We need to know about the changes and
|
|
|
9119d9 |
store them into the status XML to not break migration or managedsave
|
|
|
9119d9 |
through different libvirt versions.
|
|
|
9119d9 |
|
|
|
9119d9 |
The values would be loaded only if the "vgamem_mb" property exists for
|
|
|
9119d9 |
the device. The presence of the "vgamem_mb" also tells that the
|
|
|
9119d9 |
"ram_size" and "vram_size" exists for QXL devices.
|
|
|
9119d9 |
|
|
|
9119d9 |
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
|
|
|
9119d9 |
(cherry picked from commit ce745914b33e3f9a136d91655600b931e7a4178f)
|
|
|
9119d9 |
|
|
|
9119d9 |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1180574
|
|
|
9119d9 |
|
|
|
9119d9 |
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
|
|
|
9119d9 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
9119d9 |
---
|
|
|
9119d9 |
src/qemu/qemu_monitor.c | 34 ++++++++++++++++++
|
|
|
9119d9 |
src/qemu/qemu_monitor.h | 4 +++
|
|
|
9119d9 |
src/qemu/qemu_monitor_json.c | 69 ++++++++++++++++++++++++++++++++++++
|
|
|
9119d9 |
src/qemu/qemu_monitor_json.h | 3 ++
|
|
|
9119d9 |
src/qemu/qemu_process.c | 83 ++++++++++++++++++++++++++++++++++++++++++++
|
|
|
9119d9 |
5 files changed, 193 insertions(+)
|
|
|
9119d9 |
|
|
|
9119d9 |
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
|
|
|
9119d9 |
index df7bb45..0b1b80e 100644
|
|
|
9119d9 |
--- a/src/qemu/qemu_monitor.c
|
|
|
9119d9 |
+++ b/src/qemu/qemu_monitor.c
|
|
|
9119d9 |
@@ -1158,6 +1158,40 @@ qemuMonitorFindBalloonObjectPath(qemuMonitorPtr mon,
|
|
|
9119d9 |
return ret;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+/**
|
|
|
9119d9 |
+ * To update video memory size in status XML we need to load correct values from
|
|
|
9119d9 |
+ * QEMU. This is supported only with JSON monitor.
|
|
|
9119d9 |
+ *
|
|
|
9119d9 |
+ * Returns 0 on success, -1 on failure and sets proper error message.
|
|
|
9119d9 |
+ */
|
|
|
9119d9 |
+int
|
|
|
9119d9 |
+qemuMonitorUpdateVideoMemorySize(qemuMonitorPtr mon,
|
|
|
9119d9 |
+ virDomainVideoDefPtr video,
|
|
|
9119d9 |
+ const char *videoName)
|
|
|
9119d9 |
+{
|
|
|
9119d9 |
+ int ret = -1;
|
|
|
9119d9 |
+ char *path = NULL;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ if (mon->json) {
|
|
|
9119d9 |
+ ret = qemuMonitorFindObjectPath(mon, "/", videoName, &path);
|
|
|
9119d9 |
+ if (ret < 0) {
|
|
|
9119d9 |
+ if (ret == -2)
|
|
|
9119d9 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
+ _("Failed to find QOM Object path for "
|
|
|
9119d9 |
+ "device '%s'"), videoName);
|
|
|
9119d9 |
+ return -1;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ ret = qemuMonitorJSONUpdateVideoMemorySize(mon, video, path);
|
|
|
9119d9 |
+ VIR_FREE(path);
|
|
|
9119d9 |
+ return ret;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ return 0;
|
|
|
9119d9 |
+}
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+
|
|
|
9119d9 |
int qemuMonitorHMPCommandWithFd(qemuMonitorPtr mon,
|
|
|
9119d9 |
const char *cmd,
|
|
|
9119d9 |
int scm_fd,
|
|
|
9119d9 |
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
|
|
|
9119d9 |
index b08d74d..8930744 100644
|
|
|
9119d9 |
--- a/src/qemu/qemu_monitor.h
|
|
|
9119d9 |
+++ b/src/qemu/qemu_monitor.h
|
|
|
9119d9 |
@@ -243,6 +243,10 @@ virJSONValuePtr qemuMonitorGetOptions(qemuMonitorPtr mon)
|
|
|
9119d9 |
ATTRIBUTE_NONNULL(1);
|
|
|
9119d9 |
void qemuMonitorSetOptions(qemuMonitorPtr mon, virJSONValuePtr options)
|
|
|
9119d9 |
ATTRIBUTE_NONNULL(1);
|
|
|
9119d9 |
+int qemuMonitorUpdateVideoMemorySize(qemuMonitorPtr mon,
|
|
|
9119d9 |
+ virDomainVideoDefPtr video,
|
|
|
9119d9 |
+ const char *videName)
|
|
|
9119d9 |
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
|
|
9119d9 |
int qemuMonitorHMPCommandWithFd(qemuMonitorPtr mon,
|
|
|
9119d9 |
const char *cmd,
|
|
|
9119d9 |
int scm_fd,
|
|
|
9119d9 |
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
|
|
|
9119d9 |
index 97151dc..9b3d17a 100644
|
|
|
9119d9 |
--- a/src/qemu/qemu_monitor_json.c
|
|
|
9119d9 |
+++ b/src/qemu/qemu_monitor_json.c
|
|
|
9119d9 |
@@ -1443,6 +1443,75 @@ int qemuMonitorJSONGetVirtType(qemuMonitorPtr mon,
|
|
|
9119d9 |
}
|
|
|
9119d9 |
|
|
|
9119d9 |
|
|
|
9119d9 |
+/**
|
|
|
9119d9 |
+ * Loads correct video memory size values from QEMU and update the video
|
|
|
9119d9 |
+ * definition.
|
|
|
9119d9 |
+ *
|
|
|
9119d9 |
+ * Return 0 on success, -1 on failure and set proper error message.
|
|
|
9119d9 |
+ */
|
|
|
9119d9 |
+int
|
|
|
9119d9 |
+qemuMonitorJSONUpdateVideoMemorySize(qemuMonitorPtr mon,
|
|
|
9119d9 |
+ virDomainVideoDefPtr video,
|
|
|
9119d9 |
+ char *path)
|
|
|
9119d9 |
+{
|
|
|
9119d9 |
+ qemuMonitorJSONObjectProperty prop = {
|
|
|
9119d9 |
+ QEMU_MONITOR_OBJECT_PROPERTY_ULONG,
|
|
|
9119d9 |
+ {0}
|
|
|
9119d9 |
+ };
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ switch (video->type) {
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_VGA:
|
|
|
9119d9 |
+ if (qemuMonitorJSONGetObjectProperty(mon, path, "vgamem_mb", &prop) < 0) {
|
|
|
9119d9 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
+ _("QOM Objext '%s' has no property 'vgamem_mb'"),
|
|
|
9119d9 |
+ path);
|
|
|
9119d9 |
+ return -1;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+ video->vram = prop.val.ul * 1024;
|
|
|
9119d9 |
+ break;
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_QXL:
|
|
|
9119d9 |
+ if (qemuMonitorJSONGetObjectProperty(mon, path, "vram_size", &prop) < 0) {
|
|
|
9119d9 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
+ _("QOM Objext '%s' has no property 'vram_size'"),
|
|
|
9119d9 |
+ path);
|
|
|
9119d9 |
+ return -1;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+ video->vram = prop.val.ul / 1024;
|
|
|
9119d9 |
+ if (qemuMonitorJSONGetObjectProperty(mon, path, "ram_size", &prop) < 0) {
|
|
|
9119d9 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
+ _("QOM Objext '%s' has no property 'ram_size'"),
|
|
|
9119d9 |
+ path);
|
|
|
9119d9 |
+ return -1;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+ video->ram = prop.val.ul / 1024;
|
|
|
9119d9 |
+ if (qemuMonitorJSONGetObjectProperty(mon, path, "vgamem_mb", &prop) < 0) {
|
|
|
9119d9 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
+ _("QOM Objext '%s' has no property 'vgamem_mb'"),
|
|
|
9119d9 |
+ path);
|
|
|
9119d9 |
+ return -1;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+ video->vgamem = prop.val.ul * 1024;
|
|
|
9119d9 |
+ break;
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
|
|
|
9119d9 |
+ if (qemuMonitorJSONGetObjectProperty(mon, path, "vgamem_mb", &prop) < 0) {
|
|
|
9119d9 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
+ _("QOM Objext '%s' has no property 'vgamem_mb'"),
|
|
|
9119d9 |
+ path);
|
|
|
9119d9 |
+ return -1;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+ video->vram = prop.val.ul * 1024;
|
|
|
9119d9 |
+ break;
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_XEN:
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_VBOX:
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_LAST:
|
|
|
9119d9 |
+ break;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ return 0;
|
|
|
9119d9 |
+}
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+
|
|
|
9119d9 |
/*
|
|
|
9119d9 |
* Returns: 0 if balloon not supported, +1 if balloon query worked
|
|
|
9119d9 |
* or -1 on failure
|
|
|
9119d9 |
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
|
|
|
9119d9 |
index d039991..ff20029 100644
|
|
|
9119d9 |
--- a/src/qemu/qemu_monitor_json.h
|
|
|
9119d9 |
+++ b/src/qemu/qemu_monitor_json.h
|
|
|
9119d9 |
@@ -57,6 +57,9 @@ int qemuMonitorJSONGetCPUInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
int **pids);
|
|
|
9119d9 |
int qemuMonitorJSONGetVirtType(qemuMonitorPtr mon,
|
|
|
9119d9 |
int *virtType);
|
|
|
9119d9 |
+int qemuMonitorJSONUpdateVideoMemorySize(qemuMonitorPtr mon,
|
|
|
9119d9 |
+ virDomainVideoDefPtr video,
|
|
|
9119d9 |
+ char *path);
|
|
|
9119d9 |
int qemuMonitorJSONGetBalloonInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
unsigned long long *currmem);
|
|
|
9119d9 |
int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon,
|
|
|
9119d9 |
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
|
|
|
9119d9 |
index d7b2688..d965938 100644
|
|
|
9119d9 |
--- a/src/qemu/qemu_process.c
|
|
|
9119d9 |
+++ b/src/qemu/qemu_process.c
|
|
|
9119d9 |
@@ -3032,6 +3032,85 @@ qemuProcessCleanupChardevDevice(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
|
|
9119d9 |
}
|
|
|
9119d9 |
|
|
|
9119d9 |
|
|
|
9119d9 |
+/**
|
|
|
9119d9 |
+ * Loads and update video memory size for video devices according to QEMU
|
|
|
9119d9 |
+ * process as the QEMU will silently update the values that we pass to QEMU
|
|
|
9119d9 |
+ * through command line. We need to load these updated values and store them
|
|
|
9119d9 |
+ * into the status XML.
|
|
|
9119d9 |
+ *
|
|
|
9119d9 |
+ * We will fail if for some reason the values cannot be loaded from QEMU because
|
|
|
9119d9 |
+ * its mandatory to get the correct video memory size to status XML to not break
|
|
|
9119d9 |
+ * migration.
|
|
|
9119d9 |
+ */
|
|
|
9119d9 |
+static int
|
|
|
9119d9 |
+qemuProcessUpdateVideoRamSize(virQEMUDriverPtr driver,
|
|
|
9119d9 |
+ virDomainObjPtr vm,
|
|
|
9119d9 |
+ int asyncJob)
|
|
|
9119d9 |
+{
|
|
|
9119d9 |
+ int ret = -1;
|
|
|
9119d9 |
+ ssize_t i;
|
|
|
9119d9 |
+ qemuDomainObjPrivatePtr priv = vm->privateData;
|
|
|
9119d9 |
+ virDomainVideoDefPtr video = NULL;
|
|
|
9119d9 |
+ virQEMUDriverConfigPtr cfg = NULL;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
|
|
|
9119d9 |
+ return -1;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ for (i = 0; i < vm->def->nvideos; i++) {
|
|
|
9119d9 |
+ video = vm->def->videos[i];
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ switch (video->type) {
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_VGA:
|
|
|
9119d9 |
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VGA_VGAMEM)) {
|
|
|
9119d9 |
+ if (qemuMonitorUpdateVideoMemorySize(priv->mon, video, "VGA") < 0)
|
|
|
9119d9 |
+ goto error;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+ break;
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_QXL:
|
|
|
9119d9 |
+ if (i == 0) {
|
|
|
9119d9 |
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QXL_VGA_VGAMEM)) {
|
|
|
9119d9 |
+ if (qemuMonitorUpdateVideoMemorySize(priv->mon, video,
|
|
|
9119d9 |
+ "qxl-vga") < 0)
|
|
|
9119d9 |
+ goto error;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+ } else {
|
|
|
9119d9 |
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QXL_VGAMEM)) {
|
|
|
9119d9 |
+ if (qemuMonitorUpdateVideoMemorySize(priv->mon, video,
|
|
|
9119d9 |
+ "qxl") < 0)
|
|
|
9119d9 |
+ goto error;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+ break;
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
|
|
|
9119d9 |
+ if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_VMWARE_SVGA_VGAMEM)) {
|
|
|
9119d9 |
+ if (qemuMonitorUpdateVideoMemorySize(priv->mon, video,
|
|
|
9119d9 |
+ "vmware-svga") < 0)
|
|
|
9119d9 |
+ goto error;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+ break;
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_XEN:
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_VBOX:
|
|
|
9119d9 |
+ case VIR_DOMAIN_VIDEO_TYPE_LAST:
|
|
|
9119d9 |
+ break;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ qemuDomainObjExitMonitor(driver, vm);
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ cfg = virQEMUDriverGetConfig(driver);
|
|
|
9119d9 |
+ ret = virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm);
|
|
|
9119d9 |
+ virObjectUnref(cfg);
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ return ret;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ error:
|
|
|
9119d9 |
+ qemuDomainObjExitMonitor(driver, vm);
|
|
|
9119d9 |
+ return -1;
|
|
|
9119d9 |
+}
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+
|
|
|
9119d9 |
struct qemuProcessHookData {
|
|
|
9119d9 |
virConnectPtr conn;
|
|
|
9119d9 |
virDomainObjPtr vm;
|
|
|
9119d9 |
@@ -4795,6 +4874,10 @@ int qemuProcessStart(virConnectPtr conn,
|
|
|
9119d9 |
}
|
|
|
9119d9 |
qemuDomainObjExitMonitor(driver, vm);
|
|
|
9119d9 |
|
|
|
9119d9 |
+ VIR_DEBUG("Detecting actual memory size for video device");
|
|
|
9119d9 |
+ if (qemuProcessUpdateVideoRamSize(driver, vm, asyncJob) < 0)
|
|
|
9119d9 |
+ goto cleanup;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
if (!(flags & VIR_QEMU_PROCESS_START_PAUSED)) {
|
|
|
9119d9 |
VIR_DEBUG("Starting domain CPUs");
|
|
|
9119d9 |
/* Allow the CPUS to start executing */
|
|
|
9119d9 |
--
|
|
|
9119d9 |
2.2.1
|
|
|
9119d9 |
|