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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list