[libvirt] [PATCH 1/2] qemu: implement qemu's dump-guest-memory

Wen Congyang wency at cn.fujitsu.com
Mon Apr 2 04:07:58 UTC 2012


This patch introduces the API to use qemu's new monitor command dump-guest-memory

---
 src/qemu/qemu_monitor.c      |   32 ++++++++++++++++
 src/qemu/qemu_monitor.h      |   13 +++++++
 src/qemu/qemu_monitor_json.c |   42 +++++++++++++++++++++
 src/qemu/qemu_monitor_json.h |    7 ++++
 src/qemu/qemu_monitor_text.c |   83 ++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_text.h |    7 ++++
 6 files changed, 184 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index e1a8d4c..69e2502 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2018,6 +2018,38 @@ int qemuMonitorMigrateCancel(qemuMonitorPtr mon)
     return ret;
 }
 
+/* Return 0 on success, -1 on failure, or -2 if not supported. */
+int qemuMonitorDumpToFd(qemuMonitorPtr mon,
+                        unsigned int flags,
+                        int fd,
+                        unsigned long long begin,
+                        unsigned long long length)
+{
+    int ret;
+    VIR_DEBUG("mon=%p fd=%d flags=%x begin=%llx length=%llx",
+              mon, fd, flags, begin, length);
+
+    if (!mon) {
+        qemuReportError(VIR_ERR_INVALID_ARG, "%s",
+                        _("monitor must not be NULL"));
+        return -1;
+    }
+
+    if (qemuMonitorSendFileHandle(mon, "dump", fd) < 0)
+        return -1;
+
+    if (mon->json)
+        ret = qemuMonitorJSONDump(mon, flags, "fd:dump", begin, length);
+    else
+        ret = qemuMonitorTextDump(mon, flags, "fd:dump", begin, length);
+
+    if (ret < 0) {
+        if (qemuMonitorCloseFileHandle(mon, "dump") < 0)
+            VIR_WARN("failed to close dumping handle");
+    }
+
+    return ret;
+}
 
 int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
                                 int type,
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index b480966..315cb9e 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -379,6 +379,19 @@ int qemuMonitorMigrateToUnix(qemuMonitorPtr mon,
 
 int qemuMonitorMigrateCancel(qemuMonitorPtr mon);
 
+typedef enum {
+  QEMU_MONITOR_DUMP_HAVE_FILTER  = 1 << 0,
+  QEMU_MONITOR_DUMP_PAGING       = 1 << 1,
+  QEMU_MONITOR_DUMP_FLAGS_LAST
+} QEMU_MONITOR_DUMP;
+
+/* Return 0 on success, -1 on failure, or -2 if not supported. */
+int qemuMonitorDumpToFd(qemuMonitorPtr mon,
+                        unsigned int flags,
+                        int fd,
+                        unsigned long long begin,
+                        unsigned long long length);
+
 int qemuMonitorGraphicsRelocate(qemuMonitorPtr mon,
                                 int type,
                                 const char *hostname,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index eeeb6a6..57bc788 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2413,6 +2413,48 @@ int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon)
     return ret;
 }
 
+/* Return 0 on success, -1 on failure, or -2 if not supported. */
+int qemuMonitorJSONDump(qemuMonitorPtr mon,
+                        unsigned int flags,
+                        const char *protocol,
+                        unsigned long long begin,
+                        unsigned long long length)
+{
+    int ret;
+    virJSONValuePtr cmd = NULL;
+    virJSONValuePtr reply = NULL;
+
+    if (flags & QEMU_MONITOR_DUMP_HAVE_FILTER)
+        cmd = qemuMonitorJSONMakeCommand("dump-guest-memory",
+                                         "b:paging", flags & QEMU_MONITOR_DUMP_PAGING ? 1 : 0,
+                                         "s:protocol", protocol,
+                                         "U:begin", begin,
+                                         "U:length", length,
+                                         NULL);
+    else
+        cmd = qemuMonitorJSONMakeCommand("dump-guest-memory",
+                                         "b:paging", flags & QEMU_MONITOR_DUMP_PAGING ? 1 : 0,
+                                         "s:protocol", protocol,
+                                         NULL);
+    if (!cmd)
+        return -1;
+
+    ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+    if (ret == 0) {
+        if (qemuMonitorJSONHasError(reply, "CommandNotFound")) {
+            ret = -2;
+            goto cleanup;
+        }
+
+        ret = qemuMonitorJSONCheckError(cmd, reply);
+    }
+
+cleanup:
+    virJSONValueFree(cmd);
+    virJSONValueFree(reply);
+    return ret;
+}
 
 int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon,
                                     int type,
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index a0f67aa..a8b70d4 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -136,6 +136,13 @@ int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
 
 int qemuMonitorJSONMigrateCancel(qemuMonitorPtr mon);
 
+/* Return 0 on success, -1 on failure, or -2 if not supported. */
+int qemuMonitorJSONDump(qemuMonitorPtr mon,
+                        unsigned int flags,
+                        const char *protocol,
+                        unsigned long long begin,
+                        unsigned long long length);
+
 int qemuMonitorJSONGraphicsRelocate(qemuMonitorPtr mon,
                                     int type,
                                     const char *hostname,
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index 30a0416..035d200 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -1745,6 +1745,89 @@ int qemuMonitorTextMigrateCancel(qemuMonitorPtr mon)
     return 0;
 }
 
+static int qemuMonitorTextCheckDumpingReply(const char *info)
+{
+    /* QERR_FD_NOT_FOUND */
+    if (strstr(info, "File descriptor named"))
+        return -1;
+
+    /* QERR_OPEN_FILE_FAILED */
+    if (strstr(info, "Could not open"))
+        return -1;
+
+    /* QERR_INVALID_PARAMETER */
+    if (strstr(info, "Invalid parameter"))
+        return -1;
+
+    /* QERR_IO_ERROR */
+    if (strstr(info, "An IO error has occurred"))
+        return -1;
+
+    /* QERR_PIPE_OR_SOCKET_FD */
+    if (strstr(info, "lseek() failed: the fd is associated with a pipe, socket"))
+        return -1;
+
+    return 0;
+}
+
+/* Return 0 on success, -1 on failure, or -2 if not supported. */
+int qemuMonitorTextDump(qemuMonitorPtr mon,
+                        unsigned int flags,
+                        const char *protocol,
+                        unsigned long long begin,
+                        unsigned long long length)
+{
+    char *cmd = NULL;
+    char *info = NULL;
+    int ret = -1;
+    char *safeprotocol = qemuMonitorEscapeArg(protocol);
+
+    if (!safeprotocol) {
+        virReportOOMError();
+        return -1;
+    }
+
+    if (flags & QEMU_MONITOR_DUMP_HAVE_FILTER) {
+        ret = virAsprintf(&cmd, "dump-guest-memory %s \"%s\" %llu %llu",
+                          flags & QEMU_MONITOR_DUMP_PAGING ? "-p" : "",
+                          safeprotocol, begin, length);
+    } else {
+        ret = virAsprintf(&cmd, "dump-guest-memory %s \"%s\"",
+                          flags & QEMU_MONITOR_DUMP_PAGING ? "-p" : "",
+                          safeprotocol);
+    }
+    if (ret < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (qemuMonitorHMPCommand(mon, cmd, &info) < 0) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("unable to start dumping to %s"), protocol);
+        goto cleanup;
+    }
+
+    /* If the command isn't supported then qemu prints:
+     * unknown command: dump" */
+    if (strstr(info, "unknown command:")) {
+        ret = -2;
+        goto cleanup;
+    }
+
+    if (qemuMonitorTextCheckDumpingReply(info) < 0) {
+        qemuReportError(VIR_ERR_OPERATION_FAILED,
+                        _("dumping to '%s' failed: %s"), protocol, info);
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    VIR_FREE(safeprotocol);
+    VIR_FREE(info);
+    VIR_FREE(cmd);
+    return ret;
+}
 
 int qemuMonitorTextGraphicsRelocate(qemuMonitorPtr mon,
                                     int type,
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index 4525864..ca330ac 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -128,6 +128,13 @@ int qemuMonitorTextMigrate(qemuMonitorPtr mon,
 
 int qemuMonitorTextMigrateCancel(qemuMonitorPtr mon);
 
+/* Return 0 on success, -1 on failure, or -2 if not supported. */
+int qemuMonitorTextDump(qemuMonitorPtr mon,
+                        unsigned int flags,
+                        const char *protocol,
+                        unsigned long long begin,
+                        unsigned long long length);
+
 int qemuMonitorTextGraphicsRelocate(qemuMonitorPtr mon,
                                     int type,
                                     const char *hostname,
-- 
1.7.1




More information about the libvir-list mailing list