From 4bd16ba8ead047212b18c99e9715f4759ea87cd0 Mon Sep 17 00:00:00 2001 From: Alexander Egorenkov Date: Thu, 11 Nov 2021 07:21:08 +0100 Subject: [PATCH] zdump: Extract dfo_mem_chunk interface from DFO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The primary goal is to separate DFO code into multiple smaller modules and make it unit testable. This refactoring only moved the code around w/o changing any functionality. Signed-off-by: Alexander Egorenkov Signed-off-by: Jan Höppner --- zdump/Makefile | 2 +- zdump/dfo.c | 119 ++++----------------------------------- zdump/dfo.h | 37 ++---------- zdump/dfo_elf.c | 1 + zdump/dfo_mem_chunk.c | 128 ++++++++++++++++++++++++++++++++++++++++++ zdump/dfo_mem_chunk.h | 42 ++++++++++++++ zdump/dfo_s390.c | 1 + 7 files changed, 190 insertions(+), 140 deletions(-) create mode 100644 zdump/dfo_mem_chunk.c create mode 100644 zdump/dfo_mem_chunk.h diff --git a/zdump/Makefile b/zdump/Makefile index db2f4ab8..ee7d7c12 100644 --- a/zdump/Makefile +++ b/zdump/Makefile @@ -47,7 +47,7 @@ OBJECTS = zgetdump.o opts.o zg.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 \ + dfi_devmem.o dfo.o dfo_mem_chunk.o \ dfo_elf.o dfo_s390.o \ df_s390.o \ dt.o dt_s390sv.o dt_s390sv_ext.o \ diff --git a/zdump/dfo.c b/zdump/dfo.c index fd85cc50..d92e222e 100644 --- a/zdump/dfo.c +++ b/zdump/dfo.c @@ -9,16 +9,13 @@ * it under the terms of the MIT license. See LICENSE for details. */ -#include +#include +#include -#include "lib/util_list.h" - -#include "dfi_mem_chunk.h" +#include "zg.h" +#include "dfo_mem_chunk.h" #include "dfo.h" -#define dfo_chunk_iterate(dfo_chunk) \ - util_list_iterate(&l.dump.chunk_list, dfo_chunk) - /* * DFO vector */ @@ -28,70 +25,14 @@ static struct dfo *dfo_vec[] = { NULL, }; -/* - * Dump (output) information - */ -struct dump { - u64 off; /* Current file offset in dump */ - u64 size; /* Size of dump in bytes */ - unsigned int chunk_cnt; /* Number of dump chunks */ - struct util_list chunk_list; /* DFO chunk list */ -}; - /* * File local static data */ static struct { - struct dump dump; + u64 off; /* Current file offset in dump */ struct dfo *dfo; } l; -/* - * Add dump chunk - */ -void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn) -{ - struct dfo_chunk *dfo_chunk; - - dfo_chunk = zg_alloc(sizeof(*dfo_chunk)); - dfo_chunk->start = start; - dfo_chunk->end = start + size - 1; - dfo_chunk->data = data; - dfo_chunk->read_fn = read_fn; - util_list_add_head(&l.dump.chunk_list, dfo_chunk); - l.dump.chunk_cnt++; - l.dump.size = MAX(l.dump.size, dfo_chunk->end + 1); -} - -/* - * Dump chunk function: Copy zero pages for chunk - */ -void dfo_chunk_zero_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt) -{ - (void) dfo_chunk; - (void) off; - - memset(buf, 0, cnt); -} - -/* - * Dump chunk function: Copy given buffer for chunk - */ -void dfo_chunk_buf_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt) -{ - memcpy(buf, dfo_chunk->data + off, cnt); -} - -/* - * Dump chunk function: Copy given memory range for chunk - */ -void dfo_chunk_mem_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt) -{ - struct dfi_mem_chunk *mem_chunk = dfo_chunk->data; - - mem_chunk->read_fn(mem_chunk, off, buf, cnt); -} - /* * Get DFO name */ @@ -125,55 +66,17 @@ void dfo_init(void) { if (!l.dfo) ABORT("DFO not set"); - util_list_init(&l.dump.chunk_list, struct dfo_chunk, list); + if (dfo_chunk_init()) + ABORT("DFO memory chunk init failed"); l.dfo->init(); } -/* - * Find dump chunk for offset "off" - * - * This function is a bit hacky. DFO chunks can overlap. If two DFO chunks - * overlap, the last registered chunk wins. The dfo_chunk_find() function - * reflects that by returning the first memory chunk that is found in - * the dfo chunk list. - * - * In addition to that it calculates the "virtual end" of that chunk. An - * overlapping chunk can limit the "virtual end" of an underlying chunk so - * that the "virtual end" of that chunk is lower than the "real end". - * - * Example: - * - * chunk 1.: |------| - * chunk 2.: |---------------------| - * off.....: ^ - * virt end: ^ - * real end: ^ - * - * In this case chunk 2 will be returned and "end" is set to the start of - * chunk 1. - */ -static struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end) -{ - struct dfo_chunk *dfo_chunk; - - *end = U64_MAX; - dfo_chunk_iterate(dfo_chunk) { - if (dfo_chunk->start <= off && dfo_chunk->end >= off) { - *end = MIN(*end, dfo_chunk->end); - return dfo_chunk; - } else if (dfo_chunk->start > off) { - *end = MIN(*end, dfo_chunk->start - 1); - } - } - return NULL; -} - /* * Seek to output dump offset "off" */ void dfo_seek(u64 off) { - l.dump.off = off; + l.off = off; } /* @@ -183,7 +86,7 @@ u64 dfo_read(void *buf, u64 cnt) { struct dfo_chunk *dfo_chunk; u64 copied = 0, end, size; - u64 off = l.dump.off; + u64 off = l.off; while (copied != cnt) { dfo_chunk = dfo_chunk_find(off, &end); @@ -196,7 +99,7 @@ u64 dfo_read(void *buf, u64 cnt) off += size; } out: - l.dump.off = off; + l.off = off; return copied; } @@ -205,5 +108,5 @@ out: */ u64 dfo_size(void) { - return l.dump.size; + return dfo_chunk_dump_size(); } diff --git a/zdump/dfo.h b/zdump/dfo.h index 3d30f132..212d6070 100644 --- a/zdump/dfo.h +++ b/zdump/dfo.h @@ -12,37 +12,12 @@ #ifndef DFO_H #define DFO_H -#include "lib/util_list.h" -#include "zg.h" - -struct dfo_chunk; - -typedef void (*dfo_chunk_read_fn)(struct dfo_chunk *chunk, u64 off, - void *buf, u64 cnt); - -struct dfo_chunk { - struct util_list_node list; - u64 start; - u64 end; - dfo_chunk_read_fn read_fn; - void *data; -}; - -extern void dfo_chunk_zero_fn(struct dfo_chunk *chunk, u64 off, void *buf, - u64 cnt); -extern void dfo_chunk_buf_fn(struct dfo_chunk *chunk, u64 off, void *buf, - u64 cnt); -extern void dfo_chunk_mem_fn(struct dfo_chunk *chunk, u64 off, void *buf, - u64 cnt); -extern void dfo_chunk_add(u64 start, u64 size, void *data, - dfo_chunk_read_fn read_fn); - -extern u64 dfo_read(void *buf, u64 cnt); -extern void dfo_seek(u64 addr); -extern u64 dfo_size(void); -extern const char *dfo_name(void); -extern void dfo_init(void); -extern int dfo_set(const char *dfo_name); +u64 dfo_read(void *buf, u64 cnt); +void dfo_seek(u64 addr); +u64 dfo_size(void); +const char *dfo_name(void); +void dfo_init(void); +int dfo_set(const char *dfo_name); /* * DFO operations diff --git a/zdump/dfo_elf.c b/zdump/dfo_elf.c index 3b824427..6191b8ad 100644 --- a/zdump/dfo_elf.c +++ b/zdump/dfo_elf.c @@ -19,6 +19,7 @@ #include "df_elf.h" #include "dfi.h" #include "dfi_mem_chunk.h" +#include "dfo_mem_chunk.h" #include "dfi_vmcoreinfo.h" #include "dfo.h" diff --git a/zdump/dfo_mem_chunk.c b/zdump/dfo_mem_chunk.c new file mode 100644 index 00000000..3b091f9b --- /dev/null +++ b/zdump/dfo_mem_chunk.c @@ -0,0 +1,128 @@ +/* + * Copyright IBM Corp. 2001, 2017, 2021 + * + * 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 + +#include "zg.h" +#include "dfi_mem_chunk.h" +#include "dfo_mem_chunk.h" + +/* + * File local static data + */ +static struct { + u64 size; /* Size of dump in bytes */ + unsigned int chunk_cnt; /* Number of dump chunks */ + struct util_list chunk_list; /* DFO chunk list */ +} l; + +/* + * Add dump chunk + */ +void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn) +{ + struct dfo_chunk *dfo_chunk; + + dfo_chunk = zg_alloc(sizeof(*dfo_chunk)); + dfo_chunk->start = start; + dfo_chunk->end = start + size - 1; + dfo_chunk->data = data; + dfo_chunk->read_fn = read_fn; + util_list_add_head(&l.chunk_list, dfo_chunk); + l.chunk_cnt++; + l.size = MAX(l.size, dfo_chunk->end + 1); +} + +/* + * Dump chunk function: Copy zero pages for chunk + */ +void dfo_chunk_zero_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt) +{ + (void) dfo_chunk; + (void) off; + + memset(buf, 0, cnt); +} + +/* + * Dump chunk function: Copy given buffer for chunk + */ +void dfo_chunk_buf_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt) +{ + memcpy(buf, dfo_chunk->data + off, cnt); +} + +/* + * Dump chunk function: Copy given memory range for chunk + */ +void dfo_chunk_mem_fn(struct dfo_chunk *dfo_chunk, u64 off, void *buf, u64 cnt) +{ + struct dfi_mem_chunk *mem_chunk = dfo_chunk->data; + + mem_chunk->read_fn(mem_chunk, off, buf, cnt); +} + +/* + * Find dump chunk for offset "off" + * + * This function is a bit hacky. DFO chunks can overlap. If two DFO chunks + * overlap, the last registered chunk wins. The dfo_chunk_find() function + * reflects that by returning the first memory chunk that is found in + * the dfo chunk list. + * + * In addition to that it calculates the "virtual end" of that chunk. An + * overlapping chunk can limit the "virtual end" of an underlying chunk so + * that the "virtual end" of that chunk is lower than the "real end". + * + * Example: + * + * chunk 1.: |------| + * chunk 2.: |---------------------| + * off.....: ^ + * virt end: ^ + * real end: ^ + * + * In this case chunk 2 will be returned and "end" is set to the start of + * chunk 1. + */ +struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end) +{ + struct dfo_chunk *dfo_chunk; + + *end = U64_MAX; + dfo_chunk_iterate(dfo_chunk) { + if (dfo_chunk->start <= off && dfo_chunk->end >= off) { + *end = MIN(*end, dfo_chunk->end); + return dfo_chunk; + } else if (dfo_chunk->start > off) { + *end = MIN(*end, dfo_chunk->start - 1); + } + } + return NULL; +} + +struct util_list *dfo_chunk_list(void) +{ + return &l.chunk_list; +} + +u64 dfo_chunk_dump_size(void) +{ + return l.size; +} + +int dfo_chunk_init(void) +{ + util_list_init(&l.chunk_list, struct dfo_chunk, list); + + return 0; +} + +void dfo_chunk_deinit(void) +{ + memset(&l, 0, sizeof(l)); +} diff --git a/zdump/dfo_mem_chunk.h b/zdump/dfo_mem_chunk.h new file mode 100644 index 00000000..c0f9c618 --- /dev/null +++ b/zdump/dfo_mem_chunk.h @@ -0,0 +1,42 @@ +/* + * Copyright IBM Corp. 2001, 2017, 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef DFO_MEM_CHUNK_H +#define DFO_MEM_CHUNK_H + +#include "lib/zt_common.h" +#include "lib/util_list.h" + +struct dfo_chunk; + +typedef void (*dfo_chunk_read_fn)(struct dfo_chunk *chunk, u64 off, + void *buf, u64 cnt); + +struct dfo_chunk { + struct util_list_node list; + u64 start; + u64 end; + dfo_chunk_read_fn read_fn; + void *data; +}; + +void dfo_chunk_zero_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt); +void dfo_chunk_buf_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt); +void dfo_chunk_mem_fn(struct dfo_chunk *chunk, u64 off, void *buf, u64 cnt); +void dfo_chunk_add(u64 start, u64 size, void *data, dfo_chunk_read_fn read_fn); +struct dfo_chunk *dfo_chunk_find(u64 off, u64 *end); + +struct util_list *dfo_chunk_list(void); +#define dfo_chunk_iterate(dfo_chunk) \ + util_list_iterate(dfo_chunk_list(), dfo_chunk) + +u64 dfo_chunk_dump_size(void); + +int dfo_chunk_init(void); +void dfo_chunk_deinit(void); + +#endif /* DFO_MEM_CHUNK_H */ diff --git a/zdump/dfo_s390.c b/zdump/dfo_s390.c index d1fefdb9..0bbfcef9 100644 --- a/zdump/dfo_s390.c +++ b/zdump/dfo_s390.c @@ -19,6 +19,7 @@ #include "df_s390.h" #include "dfi_mem_chunk.h" +#include "dfo_mem_chunk.h" #include "dfo.h" /*