dump queue
Hi The "dump" queue, with: - [PATCH v3 qemu 0/3] Allow dump-guest-memory to output standard kdump format - [PATCH v2 0/5] dump: Minor fixes & improvements -----BEGIN PGP SIGNATURE----- iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmVEmsEcHG1hcmNhbmRy ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5YNkD/sFnz+I75mn6+DIdC3x aSVUU87JxAvWkt+G3KYGS+de2+g2YkRkPwwrIsIceiX7mlL4Es350AVcTl7+fXpu Jl9k9I32QI+U3pNXo9BStIqjKUMBxmmKs4aLCh9OHJ6oliTCG+aJTUmSl/dABIuw fAcW9vjhyR4ogAp8x7WhR6PKEAAb6OE/9k0w/z0GV2K09N/R0pPAvObQ36VQJ/Cl 6DN8tRRytl0IQmC/mZZ+MQPQ5cvamK78X3DmnYCGtyN9HTQERfUFMSSgD/sHLvNi rMKuwhXiGQfDs/xQ9Z6Vh2AL7JfAwbIQwUstepb78M/5GBLaZfwFYG4+eCohJE82 s0GOQ45Yks+AOTGj6lNyOfJ8PIf0SocCTbnLWZicpdHIfoEkSmmL0VZ5w+w0EpDO WOZJRpANJGTLhKNb//X3A3OJ05LoavN3/criokhC19DW/yE/VEGd3dXlP6yvFOku vGUINGivg1bw7yO0S/rzXNw4+cHCPgBCXbKCNuMI6B+dxL5pUR5Zr4OqcYgwejqE RWMdqsHA4ohpzc3AfbuHLFilXJNAgLR3jAEiVUXyrz9U1FiYEiq/8RNuupe9Uveq pO1PDZ9fher0Zda4y28bHl/e5M9hVeCFqElcVk0FQGt97T5olVvSaL/hFUPf65ls 8A3lN6WaAT9dvM33pkeswZvGxg== =eSbp -----END PGP SIGNATURE----- Merge tag 'dump-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging dump queue Hi The "dump" queue, with: - [PATCH v3 qemu 0/3] Allow dump-guest-memory to output standard kdump format - [PATCH v2 0/5] dump: Minor fixes & improvements # -----BEGIN PGP SIGNATURE----- # # iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmVEmsEcHG1hcmNhbmRy # ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5YNkD/sFnz+I75mn6+DIdC3x # aSVUU87JxAvWkt+G3KYGS+de2+g2YkRkPwwrIsIceiX7mlL4Es350AVcTl7+fXpu # Jl9k9I32QI+U3pNXo9BStIqjKUMBxmmKs4aLCh9OHJ6oliTCG+aJTUmSl/dABIuw # fAcW9vjhyR4ogAp8x7WhR6PKEAAb6OE/9k0w/z0GV2K09N/R0pPAvObQ36VQJ/Cl # 6DN8tRRytl0IQmC/mZZ+MQPQ5cvamK78X3DmnYCGtyN9HTQERfUFMSSgD/sHLvNi # rMKuwhXiGQfDs/xQ9Z6Vh2AL7JfAwbIQwUstepb78M/5GBLaZfwFYG4+eCohJE82 # s0GOQ45Yks+AOTGj6lNyOfJ8PIf0SocCTbnLWZicpdHIfoEkSmmL0VZ5w+w0EpDO # WOZJRpANJGTLhKNb//X3A3OJ05LoavN3/criokhC19DW/yE/VEGd3dXlP6yvFOku # vGUINGivg1bw7yO0S/rzXNw4+cHCPgBCXbKCNuMI6B+dxL5pUR5Zr4OqcYgwejqE # RWMdqsHA4ohpzc3AfbuHLFilXJNAgLR3jAEiVUXyrz9U1FiYEiq/8RNuupe9Uveq # pO1PDZ9fher0Zda4y28bHl/e5M9hVeCFqElcVk0FQGt97T5olVvSaL/hFUPf65ls # 8A3lN6WaAT9dvM33pkeswZvGxg== # =eSbp # -----END PGP SIGNATURE----- # gpg: Signature made Fri 03 Nov 2023 15:01:21 HKT # gpg: using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5 # gpg: issuer "marcandre.lureau@redhat.com" # gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full] # gpg: aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full] # Primary key fingerprint: 87A9 BD93 3F87 C606 D276 F62D DAE8 E109 7596 9CE5 * tag 'dump-pull-request' of https://gitlab.com/marcandre.lureau/qemu: dump: Drop redundant check for empty dump dump: Improve some dump-guest-memory error messages dump: Recognize "fd:" protocols on Windows hosts dump: Fix g_array_unref(NULL) in dump-guest-memory dump: Rename qmp_dump_guest_memory() parameter to match QAPI schema dump: Add command interface for kdump-raw formats dump: Allow directly outputting raw kdump format dump: Pass DumpState to write_ functions Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
1d6e13c1c7
@ -19,6 +19,7 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
|
||||
bool paging = qdict_get_try_bool(qdict, "paging", false);
|
||||
bool zlib = qdict_get_try_bool(qdict, "zlib", false);
|
||||
bool lzo = qdict_get_try_bool(qdict, "lzo", false);
|
||||
bool raw = qdict_get_try_bool(qdict, "raw", false);
|
||||
bool snappy = qdict_get_try_bool(qdict, "snappy", false);
|
||||
const char *file = qdict_get_str(qdict, "filename");
|
||||
bool has_begin = qdict_haskey(qdict, "begin");
|
||||
@ -40,16 +41,28 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
|
||||
dump_format = DUMP_GUEST_MEMORY_FORMAT_WIN_DMP;
|
||||
}
|
||||
|
||||
if (zlib) {
|
||||
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB;
|
||||
if (zlib && raw) {
|
||||
if (raw) {
|
||||
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_RAW_ZLIB;
|
||||
} else {
|
||||
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB;
|
||||
}
|
||||
}
|
||||
|
||||
if (lzo) {
|
||||
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO;
|
||||
if (raw) {
|
||||
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_RAW_LZO;
|
||||
} else {
|
||||
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO;
|
||||
}
|
||||
}
|
||||
|
||||
if (snappy) {
|
||||
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY;
|
||||
if (raw) {
|
||||
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_RAW_SNAPPY;
|
||||
} else {
|
||||
dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_begin) {
|
||||
|
158
dump/dump.c
158
dump/dump.c
@ -100,7 +100,7 @@ static int dump_cleanup(DumpState *s)
|
||||
memory_mapping_list_free(&s->list);
|
||||
close(s->fd);
|
||||
g_free(s->guest_note);
|
||||
g_array_unref(s->string_table_buf);
|
||||
g_clear_pointer(&s->string_table_buf, g_array_unref);
|
||||
s->guest_note = NULL;
|
||||
if (s->resume) {
|
||||
if (s->detached) {
|
||||
@ -809,11 +809,15 @@ static void create_vmcore(DumpState *s, Error **errp)
|
||||
dump_end(s, errp);
|
||||
}
|
||||
|
||||
static int write_start_flat_header(int fd)
|
||||
static int write_start_flat_header(DumpState *s)
|
||||
{
|
||||
MakedumpfileHeader *mh;
|
||||
int ret = 0;
|
||||
|
||||
if (s->kdump_raw) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
QEMU_BUILD_BUG_ON(sizeof *mh > MAX_SIZE_MDF_HEADER);
|
||||
mh = g_malloc0(MAX_SIZE_MDF_HEADER);
|
||||
|
||||
@ -824,7 +828,7 @@ static int write_start_flat_header(int fd)
|
||||
mh->version = cpu_to_be64(VERSION_FLAT_HEADER);
|
||||
|
||||
size_t written_size;
|
||||
written_size = qemu_write_full(fd, mh, MAX_SIZE_MDF_HEADER);
|
||||
written_size = qemu_write_full(s->fd, mh, MAX_SIZE_MDF_HEADER);
|
||||
if (written_size != MAX_SIZE_MDF_HEADER) {
|
||||
ret = -1;
|
||||
}
|
||||
@ -833,15 +837,19 @@ static int write_start_flat_header(int fd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int write_end_flat_header(int fd)
|
||||
static int write_end_flat_header(DumpState *s)
|
||||
{
|
||||
MakedumpfileDataHeader mdh;
|
||||
|
||||
if (s->kdump_raw) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mdh.offset = END_FLAG_FLAT_HEADER;
|
||||
mdh.buf_size = END_FLAG_FLAT_HEADER;
|
||||
|
||||
size_t written_size;
|
||||
written_size = qemu_write_full(fd, &mdh, sizeof(mdh));
|
||||
written_size = qemu_write_full(s->fd, &mdh, sizeof(mdh));
|
||||
if (written_size != sizeof(mdh)) {
|
||||
return -1;
|
||||
}
|
||||
@ -849,20 +857,28 @@ static int write_end_flat_header(int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_buffer(int fd, off_t offset, const void *buf, size_t size)
|
||||
static int write_buffer(DumpState *s, off_t offset, const void *buf, size_t size)
|
||||
{
|
||||
size_t written_size;
|
||||
MakedumpfileDataHeader mdh;
|
||||
off_t seek_loc;
|
||||
|
||||
mdh.offset = cpu_to_be64(offset);
|
||||
mdh.buf_size = cpu_to_be64(size);
|
||||
if (s->kdump_raw) {
|
||||
seek_loc = lseek(s->fd, offset, SEEK_SET);
|
||||
if (seek_loc == (off_t) -1) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
mdh.offset = cpu_to_be64(offset);
|
||||
mdh.buf_size = cpu_to_be64(size);
|
||||
|
||||
written_size = qemu_write_full(fd, &mdh, sizeof(mdh));
|
||||
if (written_size != sizeof(mdh)) {
|
||||
return -1;
|
||||
written_size = qemu_write_full(s->fd, &mdh, sizeof(mdh));
|
||||
if (written_size != sizeof(mdh)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
written_size = qemu_write_full(fd, buf, size);
|
||||
written_size = qemu_write_full(s->fd, buf, size);
|
||||
if (written_size != size) {
|
||||
return -1;
|
||||
}
|
||||
@ -982,7 +998,7 @@ static void create_header32(DumpState *s, Error **errp)
|
||||
#endif
|
||||
dh->status = cpu_to_dump32(s, status);
|
||||
|
||||
if (write_buffer(s->fd, 0, dh, size) < 0) {
|
||||
if (write_buffer(s, 0, dh, size) < 0) {
|
||||
error_setg(errp, "dump: failed to write disk dump header");
|
||||
goto out;
|
||||
}
|
||||
@ -1012,7 +1028,7 @@ static void create_header32(DumpState *s, Error **errp)
|
||||
kh->offset_note = cpu_to_dump64(s, offset_note);
|
||||
kh->note_size = cpu_to_dump32(s, s->note_size);
|
||||
|
||||
if (write_buffer(s->fd, DISKDUMP_HEADER_BLOCKS *
|
||||
if (write_buffer(s, DISKDUMP_HEADER_BLOCKS *
|
||||
block_size, kh, size) < 0) {
|
||||
error_setg(errp, "dump: failed to write kdump sub header");
|
||||
goto out;
|
||||
@ -1027,7 +1043,7 @@ static void create_header32(DumpState *s, Error **errp)
|
||||
if (*errp) {
|
||||
goto out;
|
||||
}
|
||||
if (write_buffer(s->fd, offset_note, s->note_buf,
|
||||
if (write_buffer(s, offset_note, s->note_buf,
|
||||
s->note_size) < 0) {
|
||||
error_setg(errp, "dump: failed to write notes");
|
||||
goto out;
|
||||
@ -1093,7 +1109,7 @@ static void create_header64(DumpState *s, Error **errp)
|
||||
#endif
|
||||
dh->status = cpu_to_dump32(s, status);
|
||||
|
||||
if (write_buffer(s->fd, 0, dh, size) < 0) {
|
||||
if (write_buffer(s, 0, dh, size) < 0) {
|
||||
error_setg(errp, "dump: failed to write disk dump header");
|
||||
goto out;
|
||||
}
|
||||
@ -1123,7 +1139,7 @@ static void create_header64(DumpState *s, Error **errp)
|
||||
kh->offset_note = cpu_to_dump64(s, offset_note);
|
||||
kh->note_size = cpu_to_dump64(s, s->note_size);
|
||||
|
||||
if (write_buffer(s->fd, DISKDUMP_HEADER_BLOCKS *
|
||||
if (write_buffer(s, DISKDUMP_HEADER_BLOCKS *
|
||||
block_size, kh, size) < 0) {
|
||||
error_setg(errp, "dump: failed to write kdump sub header");
|
||||
goto out;
|
||||
@ -1139,7 +1155,7 @@ static void create_header64(DumpState *s, Error **errp)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (write_buffer(s->fd, offset_note, s->note_buf,
|
||||
if (write_buffer(s, offset_note, s->note_buf,
|
||||
s->note_size) < 0) {
|
||||
error_setg(errp, "dump: failed to write notes");
|
||||
goto out;
|
||||
@ -1204,7 +1220,7 @@ static int set_dump_bitmap(uint64_t last_pfn, uint64_t pfn, bool value,
|
||||
while (old_offset < new_offset) {
|
||||
/* calculate the offset and write dump_bitmap */
|
||||
offset_bitmap1 = s->offset_dump_bitmap + old_offset;
|
||||
if (write_buffer(s->fd, offset_bitmap1, buf,
|
||||
if (write_buffer(s, offset_bitmap1, buf,
|
||||
bitmap_bufsize) < 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -1212,7 +1228,7 @@ static int set_dump_bitmap(uint64_t last_pfn, uint64_t pfn, bool value,
|
||||
/* dump level 1 is chosen, so 1st and 2nd bitmap are same */
|
||||
offset_bitmap2 = s->offset_dump_bitmap + s->len_dump_bitmap +
|
||||
old_offset;
|
||||
if (write_buffer(s->fd, offset_bitmap2, buf,
|
||||
if (write_buffer(s, offset_bitmap2, buf,
|
||||
bitmap_bufsize) < 0) {
|
||||
return -1;
|
||||
}
|
||||
@ -1380,7 +1396,7 @@ out:
|
||||
static void prepare_data_cache(DataCache *data_cache, DumpState *s,
|
||||
off_t offset)
|
||||
{
|
||||
data_cache->fd = s->fd;
|
||||
data_cache->state = s;
|
||||
data_cache->data_size = 0;
|
||||
data_cache->buf_size = 4 * dump_bitmap_get_bufsize(s);
|
||||
data_cache->buf = g_malloc0(data_cache->buf_size);
|
||||
@ -1399,11 +1415,11 @@ static int write_cache(DataCache *dc, const void *buf, size_t size,
|
||||
/*
|
||||
* if flag_sync is set, synchronize data in dc->buf into vmcore.
|
||||
* otherwise check if the space is enough for caching data in buf, if not,
|
||||
* write the data in dc->buf to dc->fd and reset dc->buf
|
||||
* write the data in dc->buf to dc->state->fd and reset dc->buf
|
||||
*/
|
||||
if ((!flag_sync && dc->data_size + size > dc->buf_size) ||
|
||||
(flag_sync && dc->data_size > 0)) {
|
||||
if (write_buffer(dc->fd, dc->offset, dc->buf, dc->data_size) < 0) {
|
||||
if (write_buffer(dc->state, dc->offset, dc->buf, dc->data_size) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1644,7 +1660,7 @@ static void create_kdump_vmcore(DumpState *s, Error **errp)
|
||||
* +------------------------------------------+
|
||||
*/
|
||||
|
||||
ret = write_start_flat_header(s->fd);
|
||||
ret = write_start_flat_header(s);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "dump: failed to write start flat header");
|
||||
return;
|
||||
@ -1665,33 +1681,13 @@ static void create_kdump_vmcore(DumpState *s, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = write_end_flat_header(s->fd);
|
||||
ret = write_end_flat_header(s);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "dump: failed to write end flat header");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static int validate_start_block(DumpState *s)
|
||||
{
|
||||
GuestPhysBlock *block;
|
||||
|
||||
if (!dump_has_filter(s)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) {
|
||||
/* This block is out of the range */
|
||||
if (block->target_start >= s->filter_area_begin + s->filter_area_length ||
|
||||
block->target_end <= s->filter_area_begin) {
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void get_max_mapnr(DumpState *s)
|
||||
{
|
||||
GuestPhysBlock *last_block;
|
||||
@ -1775,7 +1771,8 @@ static void vmcoreinfo_update_phys_base(DumpState *s)
|
||||
|
||||
static void dump_init(DumpState *s, int fd, bool has_format,
|
||||
DumpGuestMemoryFormat format, bool paging, bool has_filter,
|
||||
int64_t begin, int64_t length, Error **errp)
|
||||
int64_t begin, int64_t length, bool kdump_raw,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
VMCoreInfoState *vmci = vmcoreinfo_find();
|
||||
@ -1786,6 +1783,7 @@ static void dump_init(DumpState *s, int fd, bool has_format,
|
||||
s->has_format = has_format;
|
||||
s->format = format;
|
||||
s->written_size = 0;
|
||||
s->kdump_raw = kdump_raw;
|
||||
|
||||
/* kdump-compressed is conflict with paging and filter */
|
||||
if (has_format && format != DUMP_GUEST_MEMORY_FORMAT_ELF) {
|
||||
@ -1810,7 +1808,7 @@ static void dump_init(DumpState *s, int fd, bool has_format,
|
||||
|
||||
s->fd = fd;
|
||||
if (has_filter && !length) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, "length");
|
||||
error_setg(errp, "parameter 'length' expects a non-zero size");
|
||||
goto cleanup;
|
||||
}
|
||||
s->filter_area_begin = begin;
|
||||
@ -1839,12 +1837,6 @@ static void dump_init(DumpState *s, int fd, bool has_format,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Is the filter filtering everything? */
|
||||
if (validate_start_block(s) == -1) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, "begin");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* get dump info: endian, class and architecture.
|
||||
* If the target architecture is not supported, cpu_get_dump_info() will
|
||||
* return -1.
|
||||
@ -2061,17 +2053,19 @@ DumpQueryResult *qmp_query_dump(Error **errp)
|
||||
return result;
|
||||
}
|
||||
|
||||
void qmp_dump_guest_memory(bool paging, const char *file,
|
||||
void qmp_dump_guest_memory(bool paging, const char *protocol,
|
||||
bool has_detach, bool detach,
|
||||
bool has_begin, int64_t begin, bool has_length,
|
||||
int64_t length, bool has_format,
|
||||
DumpGuestMemoryFormat format, Error **errp)
|
||||
bool has_begin, int64_t begin,
|
||||
bool has_length, int64_t length,
|
||||
bool has_format, DumpGuestMemoryFormat format,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
const char *p;
|
||||
int fd = -1;
|
||||
int fd;
|
||||
DumpState *s;
|
||||
bool detach_p = false;
|
||||
bool kdump_raw = false;
|
||||
|
||||
if (runstate_check(RUN_STATE_INMIGRATE)) {
|
||||
error_setg(errp, "Dump not allowed during incoming migration.");
|
||||
@ -2085,6 +2079,29 @@ void qmp_dump_guest_memory(bool paging, const char *file,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* externally, we represent kdump-raw-* as separate formats, but internally
|
||||
* they are handled the same, except for the "raw" flag
|
||||
*/
|
||||
if (has_format) {
|
||||
switch (format) {
|
||||
case DUMP_GUEST_MEMORY_FORMAT_KDUMP_RAW_ZLIB:
|
||||
format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB;
|
||||
kdump_raw = true;
|
||||
break;
|
||||
case DUMP_GUEST_MEMORY_FORMAT_KDUMP_RAW_LZO:
|
||||
format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO;
|
||||
kdump_raw = true;
|
||||
break;
|
||||
case DUMP_GUEST_MEMORY_FORMAT_KDUMP_RAW_SNAPPY:
|
||||
format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY;
|
||||
kdump_raw = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* kdump-compressed format need the whole memory dumped, so paging or
|
||||
* filter is not supported here.
|
||||
@ -2127,25 +2144,23 @@ void qmp_dump_guest_memory(bool paging, const char *file,
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(WIN32)
|
||||
if (strstart(file, "fd:", &p)) {
|
||||
if (strstart(protocol, "fd:", &p)) {
|
||||
fd = monitor_get_fd(monitor_cur(), p, errp);
|
||||
if (fd == -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strstart(file, "file:", &p)) {
|
||||
fd = qemu_open_old(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR);
|
||||
} else if (strstart(protocol, "file:", &p)) {
|
||||
fd = qemu_create(p, O_WRONLY | O_TRUNC | O_BINARY, S_IRUSR, errp);
|
||||
if (fd < 0) {
|
||||
error_setg_file_open(errp, errno, p);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
error_setg(errp,
|
||||
"parameter 'protocol' must start with 'file:' or 'fd:'");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fd == -1) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
|
||||
if (kdump_raw && lseek(fd, 0, SEEK_CUR) == (off_t) -1) {
|
||||
error_setg(errp, "kdump-raw formats require a seekable file");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2168,7 +2183,7 @@ void qmp_dump_guest_memory(bool paging, const char *file,
|
||||
dump_state_prepare(s);
|
||||
|
||||
dump_init(s, fd, has_format, format, paging, has_begin,
|
||||
begin, length, errp);
|
||||
begin, length, kdump_raw, errp);
|
||||
if (*errp) {
|
||||
qatomic_set(&s->status, DUMP_STATUS_FAILED);
|
||||
return;
|
||||
@ -2196,15 +2211,18 @@ DumpGuestMemoryCapability *qmp_query_dump_guest_memory_capability(Error **errp)
|
||||
|
||||
/* kdump-zlib is always available */
|
||||
QAPI_LIST_APPEND(tail, DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB);
|
||||
QAPI_LIST_APPEND(tail, DUMP_GUEST_MEMORY_FORMAT_KDUMP_RAW_ZLIB);
|
||||
|
||||
/* add new item if kdump-lzo is available */
|
||||
#ifdef CONFIG_LZO
|
||||
QAPI_LIST_APPEND(tail, DUMP_GUEST_MEMORY_FORMAT_KDUMP_LZO);
|
||||
QAPI_LIST_APPEND(tail, DUMP_GUEST_MEMORY_FORMAT_KDUMP_RAW_LZO);
|
||||
#endif
|
||||
|
||||
/* add new item if kdump-snappy is available */
|
||||
#ifdef CONFIG_SNAPPY
|
||||
QAPI_LIST_APPEND(tail, DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY);
|
||||
QAPI_LIST_APPEND(tail, DUMP_GUEST_MEMORY_FORMAT_KDUMP_RAW_SNAPPY);
|
||||
#endif
|
||||
|
||||
if (win_dump_available(NULL)) {
|
||||
|
@ -1085,14 +1085,16 @@ ERST
|
||||
|
||||
{
|
||||
.name = "dump-guest-memory",
|
||||
.args_type = "paging:-p,detach:-d,windmp:-w,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:l?,length:l?",
|
||||
.params = "[-p] [-d] [-z|-l|-s|-w] filename [begin length]",
|
||||
.args_type = "paging:-p,detach:-d,windmp:-w,zlib:-z,lzo:-l,snappy:-s,raw:-R,filename:F,begin:l?,length:l?",
|
||||
.params = "[-p] [-d] [-z|-l|-s|-w] [-R] filename [begin length]",
|
||||
.help = "dump guest memory into file 'filename'.\n\t\t\t"
|
||||
"-p: do paging to get guest's memory mapping.\n\t\t\t"
|
||||
"-d: return immediately (do not wait for completion).\n\t\t\t"
|
||||
"-z: dump in kdump-compressed format, with zlib compression.\n\t\t\t"
|
||||
"-l: dump in kdump-compressed format, with lzo compression.\n\t\t\t"
|
||||
"-s: dump in kdump-compressed format, with snappy compression.\n\t\t\t"
|
||||
"-R: when using kdump (-z, -l, -s), use raw rather than makedumpfile-flattened\n\t\t\t"
|
||||
" format\n\t\t\t"
|
||||
"-w: dump in Windows crashdump format (can be used instead of ELF-dump converting),\n\t\t\t"
|
||||
" for Windows x86 and x64 guests with vmcoreinfo driver only.\n\t\t\t"
|
||||
"begin: the starting physical address.\n\t\t\t"
|
||||
@ -1115,6 +1117,9 @@ SRST
|
||||
dump in kdump-compressed format, with lzo compression.
|
||||
``-s``
|
||||
dump in kdump-compressed format, with snappy compression.
|
||||
``-R``
|
||||
when using kdump (-z, -l, -s), use raw rather than makedumpfile-flattened
|
||||
format
|
||||
``-w``
|
||||
dump in Windows crashdump format (can be used instead of ELF-dump converting),
|
||||
for Windows x64 guests with vmcoreinfo driver only
|
||||
|
@ -137,7 +137,7 @@ typedef struct QEMU_PACKED KdumpSubHeader64 {
|
||||
} KdumpSubHeader64;
|
||||
|
||||
typedef struct DataCache {
|
||||
int fd; /* fd of the file where to write the cached data */
|
||||
DumpState *state; /* dump state related to this data */
|
||||
uint8_t *buf; /* buffer for cached data */
|
||||
size_t buf_size; /* size of the buf */
|
||||
size_t data_size; /* size of cached data in buf */
|
||||
@ -157,6 +157,7 @@ typedef struct DumpState {
|
||||
MemoryMappingList list;
|
||||
bool resume;
|
||||
bool detached;
|
||||
bool kdump_raw;
|
||||
hwaddr memory_offset;
|
||||
int fd;
|
||||
|
||||
|
@ -15,11 +15,23 @@
|
||||
#
|
||||
# @elf: elf format
|
||||
#
|
||||
# @kdump-zlib: kdump-compressed format with zlib-compressed
|
||||
# @kdump-zlib: makedumpfile flattened, kdump-compressed format with zlib
|
||||
# compression
|
||||
#
|
||||
# @kdump-lzo: kdump-compressed format with lzo-compressed
|
||||
# @kdump-lzo: makedumpfile flattened, kdump-compressed format with lzo
|
||||
# compression
|
||||
#
|
||||
# @kdump-snappy: kdump-compressed format with snappy-compressed
|
||||
# @kdump-snappy: makedumpfile flattened, kdump-compressed format with snappy
|
||||
# compression
|
||||
#
|
||||
# @kdump-raw-zlib: raw assembled kdump-compressed format with zlib compression
|
||||
# (since 8.2)
|
||||
#
|
||||
# @kdump-raw-lzo: raw assembled kdump-compressed format with lzo compression
|
||||
# (since 8.2)
|
||||
#
|
||||
# @kdump-raw-snappy: raw assembled kdump-compressed format with snappy
|
||||
# compression (since 8.2)
|
||||
#
|
||||
# @win-dmp: Windows full crashdump format, can be used instead of ELF
|
||||
# converting (since 2.13)
|
||||
@ -27,7 +39,11 @@
|
||||
# Since: 2.0
|
||||
##
|
||||
{ 'enum': 'DumpGuestMemoryFormat',
|
||||
'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy', 'win-dmp' ] }
|
||||
'data': [
|
||||
'elf',
|
||||
'kdump-zlib', 'kdump-lzo', 'kdump-snappy',
|
||||
'kdump-raw-zlib', 'kdump-raw-lzo', 'kdump-raw-snappy',
|
||||
'win-dmp' ] }
|
||||
|
||||
##
|
||||
# @dump-guest-memory:
|
||||
|
Loading…
Reference in New Issue
Block a user