zgetdump: Update zgetdump to process the new dump format

Update zgetdump tool to process dumps of the new s390 extended format.

Signed-off-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Mikhail Zaslonko
2018-04-17 21:06:00 +02:00
committed by Jan Höppner
parent 26d636f234
commit 4a223c70f2
9 changed files with 374 additions and 46 deletions

View File

@@ -42,8 +42,8 @@ all: check_dep_fuse check_dep_zlib zgetdump
OBJECTS = zgetdump.o opts.o zg.o \
dfi.o dfi_vmcoreinfo.o \
dfi_lkcd.o dfi_elf.o \
dfi_s390.o \
dfi_s390mv.o \
dfi_s390.o dfi_s390_ext.o\
dfi_s390mv.o dfi_s390mv_ext.o \
dfi_s390tape.o dfi_kdump.o \
dfi_devmem.o dfo.o \
dfo_elf.o dfo_s390.o \

View File

@@ -137,4 +137,8 @@ extern int dt_s390sv_init_gen(bool extended);
extern int dt_s390mv_init_gen(bool extended);
extern void dt_s390mv_info(void);
extern int dfi_s390_init_gen(bool extended);
extern int dfi_s390mv_init_gen(bool extended);
extern void dfi_s390mv_info(void);
#endif /* DF_S390_H */

View File

@@ -3,7 +3,7 @@
*
* Generic input dump format functions (DFI - Dump Format Input)
*
* Copyright IBM Corp. 2001, 2017
* Copyright IBM Corp. 2001, 2018
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -21,7 +21,9 @@
static struct dfi *dfi_vec[] = {
&dfi_s390tape,
&dfi_devmem,
&dfi_s390mv_ext,
&dfi_s390mv,
&dfi_s390_ext,
&dfi_s390,
&dfi_lkcd,
&dfi_elf,
@@ -149,12 +151,31 @@ static void mem_update(struct mem *mem)
static void mem_map_print(void)
{
struct dfi_mem_chunk *mem_chunk;
u64 print_start = 0, print_end = 0;
u32 volnr = 0;
STDERR("\nMemory map:\n");
/*
* Merge adjacent memory chunks from the same volume
*/
dfi_mem_chunk_iterate(mem_chunk) {
STDERR(" %016llx - %016llx (%llu MB)\n", mem_chunk->start,
mem_chunk->end, TO_MIB(mem_chunk->size));
if (print_end == 0) {
print_start = mem_chunk->start;
print_end = mem_chunk->end;
volnr = mem_chunk->volnr;
continue;
}
if (mem_chunk->start != print_end + 1 ||
mem_chunk->volnr != volnr) {
STDERR(" %016llx - %016llx (%llu MB)\n", print_start,
print_end, TO_MIB(print_end - print_start + 1));
print_start = mem_chunk->start;
volnr = mem_chunk->volnr;
}
print_end = mem_chunk->end;
}
STDERR(" %016llx - %016llx (%llu MB)\n", print_start,
print_end, TO_MIB(print_end - print_start + 1));
}
/*
@@ -351,9 +372,27 @@ void dfi_mem_chunk_virt_add(u64 start, u64 size, void *data,
dfi_mem_chunk_read_fn read_fn,
dfi_mem_chunk_free_fn free_fn)
{
if (size == 0)
return;
mem_chunk_create(&l.mem_virt, start, size, data, read_fn, free_fn);
}
/*
* Add memory chunk with volume index
*/
void dfi_mem_chunk_add_vol(u64 start, u64 size, void *data,
dfi_mem_chunk_read_fn read_fn,
dfi_mem_chunk_free_fn free_fn,
u32 volnr)
{
if (size == 0)
return;
mem_chunk_create(&l.mem_phys, start, size, data, read_fn, free_fn);
mem_chunk_create(&l.mem_virt, start, size, data, read_fn, free_fn);
l.mem_virt.chunk_cache->volnr = volnr;
}
/*
* Add memory chunk
*/
@@ -361,8 +400,16 @@ void dfi_mem_chunk_add(u64 start, u64 size, void *data,
dfi_mem_chunk_read_fn read_fn,
dfi_mem_chunk_free_fn free_fn)
{
mem_chunk_create(&l.mem_phys, start, size, data, read_fn, free_fn);
mem_chunk_create(&l.mem_virt, start, size, data, read_fn, free_fn);
dfi_mem_chunk_add_vol(start, size, data, read_fn, free_fn, 0);
}
/*
* Read zero pages
*/
void dfi_mem_chunk_read_zero(struct dfi_mem_chunk *UNUSED(mem_chunk),
u64 UNUSED(off), void *buf, u64 cnt)
{
memset(buf, 0, cnt);
}
/*
@@ -401,6 +448,16 @@ struct dfi_mem_chunk *dfi_mem_chunk_first(void)
return util_list_start(&l.mem_virt.chunk_list);
}
/*
* Return last memory chunk
*/
struct dfi_mem_chunk *dfi_mem_chunk_last(void)
{
if (util_list_is_empty(&l.mem_virt.chunk_list))
return NULL;
return util_list_end(&l.mem_virt.chunk_list);
}
/*
* Return next memory chunk
*/
@@ -678,7 +735,7 @@ struct new_utsname *dfi_attr_utsname(void)
}
/*
* Attribute: dump method
* Attribute: Dump method
*/
void dfi_attr_dump_method_set(char *dump_method)
{

View File

@@ -3,7 +3,7 @@
*
* Generic input dump format functions (DFI - Dump Format Input)
*
* Copyright IBM Corp. 2001, 2017
* Copyright IBM Corp. 2001, 2018
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
@@ -162,8 +162,15 @@ struct dfi_mem_chunk {
dfi_mem_chunk_read_fn read_fn; /* Chunk read callback */
dfi_mem_chunk_free_fn free_fn; /* Free data callback */
void *data; /* Data for callback */
u32 volnr; /* Volume id where chunk resides */
};
extern void dfi_mem_chunk_read_zero(struct dfi_mem_chunk *UNUSED(mem_chunk),
u64 UNUSED(off), void *buf, u64 cnt);
extern void dfi_mem_chunk_add_vol(u64 start, u64 size, void *data,
dfi_mem_chunk_read_fn read_fn,
dfi_mem_chunk_free_fn free_fn,
u32 volnr);
extern void dfi_mem_chunk_add(u64 start, u64 size, void *data,
dfi_mem_chunk_read_fn read_fn,
dfi_mem_chunk_free_fn free_fn);
@@ -174,6 +181,7 @@ extern u64 dfi_mem_range(void);
extern int dfi_mem_range_valid(u64 addr, u64 len);
extern unsigned int dfi_mem_chunk_cnt(void);
extern struct dfi_mem_chunk *dfi_mem_chunk_first(void);
extern struct dfi_mem_chunk *dfi_mem_chunk_last(void);
extern struct dfi_mem_chunk *dfi_mem_chunk_next(struct dfi_mem_chunk *chunk);
extern struct dfi_mem_chunk *dfi_mem_chunk_prev(struct dfi_mem_chunk *chunk);
extern struct dfi_mem_chunk *dfi_mem_chunk_find(u64 addr);

View File

@@ -26,10 +26,11 @@
static struct {
struct df_s390_hdr hdr; /* s390 dump header */
struct df_s390_em em; /* s390 end marker */
bool extended; /* Extended input dump format */
} l;
/*
* S390 mem chunk read callback
* s390 mem chunk read callback
*/
static void dfi_s390_mem_chunk_read(struct dfi_mem_chunk *mem_chunk, u64 off,
void *buf, u64 cnt)
@@ -40,16 +41,32 @@ static void dfi_s390_mem_chunk_read(struct dfi_mem_chunk *mem_chunk, u64 off,
zg_read(g.fh, buf, cnt, ZG_CHECK);
}
/*
* s390_ext mem chunk read callback
*/
static void dfi_s390_ext_mem_chunk_read(struct dfi_mem_chunk *mem_chunk,
u64 off, void *buf, u64 cnt)
{
u64 *mem_chunk_off = mem_chunk->data;
zg_seek(g.fh, *mem_chunk_off + off, ZG_CHECK);
zg_read(g.fh, buf, cnt, ZG_CHECK);
}
/*
* Read s390 dump header
*/
static int read_s390_hdr(void)
{
u64 magic_number;
magic_number = l.extended ? DF_S390_MAGIC_EXT : DF_S390_MAGIC;
if ((zg_type(g.fh) == ZG_TYPE_FILE) && (zg_size(g.fh) < sizeof(l.hdr)))
return -ENODEV;
if (zg_read(g.fh, &l.hdr, sizeof(l.hdr), ZG_CHECK_ERR) != sizeof(l.hdr))
return -ENODEV;
if (l.hdr.magic != DF_S390_MAGIC)
if (l.hdr.magic != magic_number)
return -ENODEV;
df_s390_hdr_add(&l.hdr);
return 0;
@@ -62,9 +79,6 @@ static int read_s390_em(void)
{
u64 rc;
rc = zg_seek(g.fh, l.hdr.mem_size + DF_S390_HDR_SIZE, ZG_CHECK_NONE);
if (rc != l.hdr.mem_size + DF_S390_HDR_SIZE)
return -EINVAL;
rc = zg_read(g.fh, &l.em, sizeof(l.em), ZG_CHECK_ERR);
if (rc != sizeof(l.em))
return -EINVAL;
@@ -75,23 +89,94 @@ static int read_s390_em(void)
}
/*
* Initialize s390 DFI
* Register memory chunks and verify the end marker
*/
static int dfi_s390_init(void)
static int mem_chunks_add(void)
{
u64 rc;
/* Single memory chunk for non-extended dump format */
dfi_mem_chunk_add(0, l.hdr.mem_size, NULL,
dfi_s390_mem_chunk_read,
NULL);
rc = zg_seek(g.fh, DF_S390_HDR_SIZE + l.hdr.mem_size,
ZG_CHECK_NONE);
if (rc != DF_S390_HDR_SIZE + l.hdr.mem_size)
return -EINVAL;
/* Read and verify the end marker */
return read_s390_em();
}
/*
* Register memory chunks (extended dump format) and verify the end marker
*/
static int mem_chunks_add_ext(void)
{
struct df_s390_dump_segm_hdr dump_segm;
u64 rc, *off_ptr, old = 0;
off_ptr = zg_alloc(sizeof(*off_ptr));
*off_ptr = zg_seek(g.fh, DF_S390_HDR_SIZE, ZG_CHECK_NONE);
if (*off_ptr != DF_S390_HDR_SIZE)
return -EINVAL;
while (*off_ptr < DF_S390_HDR_SIZE + l.hdr.mem_size - PAGE_SIZE) {
rc = zg_read(g.fh, &dump_segm, PAGE_SIZE, ZG_CHECK_ERR);
if (rc != PAGE_SIZE)
return -EINVAL;
*off_ptr += PAGE_SIZE;
/* Add zero memory chunk */
dfi_mem_chunk_add(old, dump_segm.start - old, NULL,
dfi_mem_chunk_read_zero, NULL);
/* Add memory chunk for a dump segment */
dfi_mem_chunk_add(dump_segm.start, dump_segm.len, off_ptr,
dfi_s390_ext_mem_chunk_read, zg_free);
old = dump_segm.start + dump_segm.len;
off_ptr = zg_alloc(sizeof(*off_ptr));
*off_ptr = zg_seek_cur(g.fh, dump_segm.len, ZG_CHECK_NONE);
if (dump_segm.stop_marker)
break;
}
/* Add zero memory chunk at the end */
dfi_mem_chunk_add(old, l.hdr.mem_size - old, NULL,
dfi_mem_chunk_read_zero, NULL);
/* Check if the last dump segment found */
if (!dump_segm.stop_marker)
return -EINVAL;
/* Read and verify the end marker */
return read_s390_em();
}
/*
* Initialize s390 single-volume DFI general function
*/
int dfi_s390_init_gen(bool extended)
{
int rc;
l.extended = extended;
if (read_s390_hdr() != 0)
return -ENODEV;
dfi_mem_chunk_add(0, l.hdr.mem_size, NULL, dfi_s390_mem_chunk_read,
NULL);
if (read_s390_em() != 0)
return -EINVAL;
if (!extended)
rc = mem_chunks_add();
else
rc = mem_chunks_add_ext();
if (rc)
return rc;
df_s390_cpu_info_add(&l.hdr, l.hdr.mem_size);
zg_seek(g.fh, sizeof(l.hdr), ZG_CHECK);
return 0;
}
/*
* S390 DFI operations
* Initialize s390 single-volume DFI (non-extended)
*/
static int dfi_s390_init(void)
{
return dfi_s390_init_gen(DUMP_NON_EXTENDED);
}
/*
* s390 single-volume DFI (non-extended) operations
*/
struct dfi dfi_s390 = {
.name = "s390",

29
zdump/dfi_s390_ext.c Normal file
View File

@@ -0,0 +1,29 @@
/*
* zgetdump - Tool for copying and converting System z dumps
*
* S390 extended dump input format
*
* Copyright IBM Corp. 2001, 2018
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "zgetdump.h"
/*
* Initialize s390 input dump format (extended)
*/
static int dfi_s390_ext_init(void)
{
return dfi_s390_init_gen(DUMP_EXTENDED);
}
/*
* s390 nput dump format (extedned) operations
*/
struct dfi dfi_s390_ext = {
.name = "s390_ext",
.init = dfi_s390_ext_init,
.feat_bits = DFI_FEAT_COPY | DFI_FEAT_SEEK,
};

View File

@@ -43,6 +43,14 @@ struct vol {
struct df_s390_hdr hdr;
};
/*
* Mem chunk helper structure for extended dump format
*/
struct vol_mem_chunk {
struct vol *vol;
u64 off; /* Offset to the memory chunk from the start of the volume */
};
/*
* File local static data
*/
@@ -55,6 +63,7 @@ static struct {
struct df_s390_dumper dumper;
int dump_incomplete;
bool extended;
u64 magic_number; /* Reference value to compare with */
char dumper_magic[7]; /* Reference value to compare with */
} l;
@@ -86,6 +95,7 @@ static void em_init(struct vol *vol)
l.dump_incomplete = 1;
}
/*
* Check sysfs, whether a device specified by its bus ID is defined and online.
* Find out the corresponding dev_t
@@ -177,9 +187,9 @@ static void vol_read(struct vol *vol)
}
/*
* Read memory
* Read memory chunk
*/
static void df_s390mv_mem_read(struct dfi_mem_chunk *mem_chunk, u64 off,
static void dfi_s390mv_mem_read(struct dfi_mem_chunk *mem_chunk, u64 off,
void *buf, u64 cnt)
{
struct vol *vol = mem_chunk->data;
@@ -188,6 +198,19 @@ static void df_s390mv_mem_read(struct dfi_mem_chunk *mem_chunk, u64 off,
zg_read(vol->fh, buf, cnt, ZG_CHECK);
}
/*
* Read memory chunk (extended)
*/
static void dfi_s390mv_ext_mem_read(struct dfi_mem_chunk *mem_chunk, u64 off,
void *buf, u64 cnt)
{
struct vol_mem_chunk *vol_mem_chunk = mem_chunk->data;
struct vol *vol = vol_mem_chunk->vol;
zg_seek(vol->fh, vol_mem_chunk->off + off, ZG_CHECK);
zg_read(vol->fh, buf, cnt, ZG_CHECK);
}
/*
* Initialize DASD volume
*/
@@ -214,7 +237,7 @@ static void vol_init(struct vol *vol, struct vol_parm *vol_parm, int ssid,
if ((vol->hdr.volnr == vol->nr) && (vol->hdr.mem_size != 0))
vol->sign = SIGN_ACTIVE;
if (vol->hdr.mvdump_sign != DF_S390_MAGIC) {
if (vol->hdr.mvdump_sign != l.magic_number) {
vol->sign = SIGN_INVALID;
l.dump_incomplete = 1;
}
@@ -277,16 +300,83 @@ static void vol_print_all(void)
*/
static void mem_chunks_add(void)
{
struct vol *vol;
unsigned int i;
for (i = 0; i < l.table.vol_cnt; i++) {
vol = &l.vol_vec[i];
if (vol->sign != SIGN_ACTIVE)
continue;
dfi_mem_chunk_add_vol(vol->mem_start,
vol->mem_end - vol->mem_start + 1,
vol, dfi_s390mv_mem_read, NULL, vol->nr);
}
}
/*
* Add memory chunks (extended dump format) and verify the end marker
*/
static int mem_chunks_add_ext(void)
{
u64 off, rc, part_end, old = 0;
struct df_s390_dump_segm_hdr dump_segm;
struct vol_mem_chunk *vol_mem_chunk;
unsigned int i;
for (i = 0; i < l.table.vol_cnt; i++) {
struct vol *vol = &l.vol_vec[i];
if (vol->sign != SIGN_ACTIVE)
continue;
dfi_mem_chunk_add(vol->mem_start,
vol->mem_end - vol->mem_start + 1,
vol, df_s390mv_mem_read, NULL);
off = vol->part_off + DF_S390_HDR_SIZE;
part_end = vol->part_off + vol->part_size;
rc = zg_seek(vol->fh, off, ZG_CHECK_NONE);
if (rc != off)
return -EINVAL;
/*
* Reading dump segments from the start of partition (skipping
* the dump header) till the end of partition (considering that
* minimum dump segment size is one megabyte + one page and one
* more page is reserved for the end marker)
*/
while (off < part_end - MIB - PAGE_SIZE) {
rc = zg_read(vol->fh, &dump_segm, sizeof(dump_segm),
ZG_CHECK_ERR);
if (rc != PAGE_SIZE)
return -EINVAL;
off += PAGE_SIZE;
vol_mem_chunk = zg_alloc(sizeof(*vol_mem_chunk));
vol_mem_chunk->vol = vol;
vol_mem_chunk->off = off;
/* Add zero memory chunk */
dfi_mem_chunk_add_vol(old, dump_segm.start - old, NULL,
dfi_mem_chunk_read_zero, NULL,
vol->nr);
/* Add memory chunk for a dump segment */
dfi_mem_chunk_add_vol(dump_segm.start, dump_segm.len,
vol_mem_chunk,
dfi_s390mv_ext_mem_read, NULL,
vol->nr);
old = dump_segm.start + dump_segm.len;
off = zg_seek_cur(vol->fh, dump_segm.len,
ZG_CHECK_NONE);
if (dump_segm.stop_marker)
break;
}
if (dump_segm.stop_marker) {
/* Add zero memory chunk at the end*/
dfi_mem_chunk_add_vol(old, l.hdr.mem_size - old, NULL,
dfi_mem_chunk_read_zero, NULL,
vol->nr);
/* Read and verify the end marker */
rc = zg_read(vol->fh, &l.em, sizeof(l.em), ZG_CHECK);
if (rc != sizeof(l.em) ||
df_s390_em_verify(&l.em, &l.hdr) != 0)
return -EINVAL;
return 0;
}
}
/* No dump segment with the stop marker found */
return -EINVAL;
}
/*
@@ -364,9 +454,9 @@ static int mvdump_hdr_check(const char *file)
fh = zg_open(file, O_RDONLY, ZG_CHECK);
if (zg_read(fh, &hdr, sizeof(hdr), ZG_CHECK_ERR) != sizeof(hdr))
goto fail;
if (hdr.magic != DF_S390_MAGIC)
if (hdr.magic != l.magic_number)
goto fail;
if (hdr.mvdump_sign != DF_S390_MAGIC)
if (hdr.mvdump_sign != l.magic_number)
goto fail;
rc = 0;
fail:
@@ -387,14 +477,6 @@ static void check_sysfs(void)
closedir(fh_dir);
}
/*
* Print dump information (dfi operation)
*/
static void dfi_s390mvfo_dump(void)
{
vol_print_all();
}
/*
* Read dump tool from DASD and check if we have a multi-volume dump tool
*/
@@ -461,10 +543,26 @@ static int open_dump(void)
}
/*
* Initialize s390 multi-volume input dump format
* Specify reference values for dumper magic and dump magic numbers
*/
static int dfi_s390mv_init(void)
static void set_magic_numbers(void)
{
if (l.extended) {
l.magic_number = DF_S390_MAGIC_EXT;
strncpy(l.dumper_magic, DF_S390_DUMPER_MAGIC_MV_EXT, 7);
} else {
l.magic_number = DF_S390_MAGIC;
strncpy(l.dumper_magic, DF_S390_DUMPER_MAGIC_MV, 7);
}
}
/*
* Initialize s390 multi-volume input dump format generic function
*/
int dfi_s390mv_init_gen(bool extended)
{
l.extended = extended;
set_magic_numbers();
if (open_dump() != 0)
return -ENODEV;
volumes_init();
@@ -473,7 +571,10 @@ static int dfi_s390mv_init(void)
if (l.hdr.mem_size == 0)
return -ENODEV;
df_s390_hdr_add(&l.hdr);
mem_chunks_add();
if (!extended)
mem_chunks_add();
else if (mem_chunks_add_ext() != 0)
return -EINVAL;
if (l.dump_incomplete)
return -EINVAL;
df_s390_cpu_info_add(&l.hdr, l.hdr.mem_end);
@@ -481,17 +582,29 @@ static int dfi_s390mv_init(void)
return 0;
}
/*
* Initializt s390 multi-volume input dump
*/
static int dfi_s390mv_init(void)
{
return dfi_s390mv_init_gen(DUMP_NON_EXTENDED);
}
/*
* Print dump information (dfi operation)
*/
void dfi_s390mv_info(void)
{
vol_print_all();
}
/*
* Initialize s390 multi-volume dump tool generic function
*/
int dt_s390mv_init_gen(bool extended)
{
l.extended = extended;
/* Specify dumper magic value for further validation */
if (extended)
strncpy(l.dumper_magic, DF_S390_DUMPER_MAGIC_MV_EXT, 7);
else
strncpy(l.dumper_magic, DF_S390_DUMPER_MAGIC_MV, 7);
set_magic_numbers();
if (open_dump() != 0)
return -ENODEV;
volumes_init();
@@ -516,6 +629,6 @@ void dt_s390mv_info(void)
struct dfi dfi_s390mv = {
.name = "s390mv",
.init = dfi_s390mv_init,
.info_dump = dfi_s390mvfo_dump,
.info_dump = dfi_s390mv_info,
.feat_bits = DFI_FEAT_COPY | DFI_FEAT_SEEK,
};

30
zdump/dfi_s390mv_ext.c Normal file
View File

@@ -0,0 +1,30 @@
/*
* zgetdump - Tool for copying and converting System z dumps
*
* S390x multi-volume dump input format
*
* Copyright IBM Corp. 2001, 2018
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include "zgetdump.h"
/*
* Initialize s390 multi-volume input dump format (extedend)
*/
static int dfi_s390mv_ext_init(void)
{
return dfi_s390mv_init_gen(DUMP_EXTENDED);
}
/*
* s390 multi-volume DFI (extedned) operations
*/
struct dfi dfi_s390mv_ext = {
.name = "s390mv_ext",
.init = dfi_s390mv_ext_init,
.info_dump = dfi_s390mv_info,
.feat_bits = DFI_FEAT_COPY | DFI_FEAT_SEEK,
};

View File

@@ -75,7 +75,9 @@ void zfuse_umount(void);
*/
extern struct dfi dfi_s390tape;
extern struct dfi dfi_s390mv;
extern struct dfi dfi_s390mv_ext;
extern struct dfi dfi_s390;
extern struct dfi dfi_s390_ext;
extern struct dfi dfi_lkcd;
extern struct dfi dfi_elf;
extern struct dfi dfi_kdump;