Now I can run qemu with the memory-backend-file option and use /usr/bin/crash
in "live" mode using the file(s) specified by mem-path argument as a RAM dump.
For example,
$ qemu-kmv ...other-options... \
-object memory-backend-file,id=MEM,size=128m,mem-path=/tmp/MEM,share=on \
-numa node,memdev=MEM -m 128
and
$ crash path-to-guests-vmlinux live:/tmp/MEM@0
NOTE: in this particular (and simple) case the offset is always zero. In more
complex situations the ram-to-file mapping used by qemu can be nontrivial, but
it is very simple to add the support for MEMORY-IMAGE@ADDRESS-LENGTH syntax.
Signed-off-by: Oleg Nesterov <oleg(a)redhat.com>
---
defs.h | 7 ++++---
main.c | 9 +++++++++
memory.c | 1 +
ramdump.c | 12 ++++++++++++
4 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/defs.h b/defs.h
index 1c78c38..61497a5 100644
--- a/defs.h
+++ b/defs.h
@@ -212,6 +212,7 @@ struct number_option {
#define DEVMEM (0x2000000ULL)
#define REM_LIVE_SYSTEM (0x4000000ULL)
#define NAMELIST_LOCAL (0x8000000ULL)
+#define LIVE_RAMDUMP (0x10000000ULL)
#define NAMELIST_SAVED (0x20000000ULL)
#define DUMPFILE_SAVED (0x40000000ULL)
#define UNLINK_NAMELIST (0x80000000ULL)
@@ -250,11 +251,11 @@ struct number_option {
#define PROC_KCORE (0x8000000000000000ULL)
#define ACTIVE() (pc->flags & LIVE_SYSTEM)
-#define LOCAL_ACTIVE() ACTIVE()
+#define LOCAL_ACTIVE() ((pc->flags & (LIVE_SYSTEM|LIVE_RAMDUMP)) ==
LIVE_SYSTEM)
#define DUMPFILE() (!(pc->flags & LIVE_SYSTEM))
#define LIVE() (pc->flags2 & LIVE_DUMP || pc->flags &
LIVE_SYSTEM)
-#define MEMORY_SOURCES
(NETDUMP|KDUMP|MCLXCD|LKCD|DEVMEM|S390D|MEMMOD|DISKDUMP|XENDUMP|CRASHBUILTIN|KVMDUMP|PROC_KCORE|SADUMP|VMWARE_VMSS)
-#define DUMPFILE_TYPES
(DISKDUMP|NETDUMP|KDUMP|MCLXCD|LKCD|S390D|XENDUMP|KVMDUMP|SADUMP|VMWARE_VMSS)
+#define MEMORY_SOURCES
(NETDUMP|KDUMP|MCLXCD|LKCD|DEVMEM|S390D|MEMMOD|DISKDUMP|XENDUMP|CRASHBUILTIN|KVMDUMP|PROC_KCORE|SADUMP|VMWARE_VMSS|LIVE_RAMDUMP)
+#define DUMPFILE_TYPES
(DISKDUMP|NETDUMP|KDUMP|MCLXCD|LKCD|S390D|XENDUMP|KVMDUMP|SADUMP|VMWARE_VMSS|LIVE_RAMDUMP)
#define REMOTE() (pc->flags2 & REMOTE_DAEMON)
#define REMOTE_ACTIVE() (pc->flags & REM_LIVE_SYSTEM)
#define REMOTE_DUMPFILE() \
diff --git a/main.c b/main.c
index a4db88d..075a1e8 100644
--- a/main.c
+++ b/main.c
@@ -428,6 +428,15 @@ main(int argc, char **argv)
"too many dumpfile arguments\n");
program_usage(SHORT_FORM);
}
+
+ if (ACTIVE()) {
+ pc->flags |= LIVE_RAMDUMP;
+ pc->readmem = read_ramdump;
+ pc->writemem = NULL;
+ optind++;
+ continue;
+ }
+
pc->dumpfile = ramdump_to_elf();
if (is_kdump(pc->dumpfile, KDUMP_LOCAL)) {
pc->flags |= KDUMP;
diff --git a/memory.c b/memory.c
index 693516e..aa8be87 100644
--- a/memory.c
+++ b/memory.c
@@ -16463,6 +16463,7 @@ memory_page_size(void)
case CRASHBUILTIN:
case KVMDUMP:
case PROC_KCORE:
+ case LIVE_RAMDUMP:
psz = (uint)getpagesize();
break;
diff --git a/ramdump.c b/ramdump.c
index 1922c1b..941851c 100644
--- a/ramdump.c
+++ b/ramdump.c
@@ -232,14 +232,21 @@ char *ramdump_to_elf(void)
return e_file;
}
+#define PREFIX(ptr, pat) \
+ (strncmp((ptr), (pat), sizeof(pat)-1) ? 0 : \
+ ((ptr) += sizeof(pat)-1, 1))
+
int is_ramdump(char *p)
{
char *x = NULL, *y = NULL, *pat;
size_t len;
char *pattern;
struct stat64 st;
+ int is_live;
int err = 0;
+ is_live = PREFIX(p, "live:");
+
if (nodes || !strchr(p, '@'))
return 0;
@@ -276,6 +283,11 @@ int is_ramdump(char *p)
pat = NULL;
}
+ if (nodes && is_live) {
+ pc->flags |= LIVE_SYSTEM;
+ pc->dumpfile = ramdump[0].path;
+ pc->live_memsrc = pc->dumpfile;
+ }
return nodes;
}
--
2.5.0