File flatmap-Move-flatmap-routines-to-flatmap.c.patch of Package libkdumpfile.36085
From: Petr Tesarik <petr@tesarici.cz>
Date: Thu, 26 Sep 2024 11:32:30 +0200
Subject: flatmap: Move flatmap routines to flatmap.c
References: bsc#1223399
Upstream: merged
Git-commit: dacc72cc1d75adb31963894ca1e73271e1e28f33
Separate flattened format handling from diskdump and make the API available
to other users.
Signed-off-by: Petr Tesarik <ptesarik@suse.com>
---
src/kdumpfile/Makefile.am | 1
src/kdumpfile/Makefile.in | 7 -
src/kdumpfile/diskdump.c | 250 -------------------------------------
src/kdumpfile/flatmap.c | 271 +++++++++++++++++++++++++++++++++++++++++
src/kdumpfile/kdumpfile-priv.h | 33 ++++
5 files changed, 310 insertions(+), 252 deletions(-)
create mode 100644 src/kdumpfile/flatmap.c
--- a/src/kdumpfile/Makefile.am
+++ b/src/kdumpfile/Makefile.am
@@ -37,6 +37,7 @@ libkdumpfile_la_SOURCES = \
diskdump.c \
elfdump.c \
fcache.c \
+ flatmap.c \
ia32.c \
lkcd.c \
notes.c \
--- a/src/kdumpfile/diskdump.c
+++ b/src/kdumpfile/diskdump.c
@@ -51,7 +51,6 @@
#define MDF_SIG_LEN 16
#define MDF_TYPE_FLAT_HEADER 1
#define MDF_VERSION_FLAT_HEADER 1
-#define MDF_HEADER_SIZE 4096
/* Flattened format header. */
struct makedumpfile_header {
@@ -60,14 +59,6 @@ struct makedumpfile_header {
int64_t version;
} __attribute__((packed));
-/* Flattened segment header */
-struct makedumpfile_data_header {
- int64_t offset;
- int64_t buf_size;
-} __attribute__((packed));
-
-#define MDF_OFFSET_END_FLAG (-(int64_t)1)
-
/* The header is architecture-dependent, unfortunately */
struct disk_dump_header_32 {
char signature[SIG_LEN]; /* = "DISKDUMP" */
@@ -170,24 +161,6 @@ struct page_desc {
uint64_t page_flags; /**< Page flags. */
};
-/** Offset mapping for a file in the flattened format. */
-struct flattened_file_map {
- /** Map (rearranged) offset to an index in the offset arrray. */
- addrxlat_map_t *map;
-
- /** Differences between flattened and rearranged file offsets. */
- off_t *offs;
-};
-
-/** Offset mappings for a set of flattened files. */
-struct flattened_map {
- /** File cache. */
- struct fcache *fcache;
-
- /** Mappings for individual files. */
- struct flattened_file_map fmap;
-};
-
/** PFN region mapping. */
struct pfn_rgn {
kdump_pfn_t pfn; /**< Starting PFN. */
@@ -228,58 +201,6 @@ struct setup_data {
static void diskdump_cleanup(struct kdump_shared *shared);
-/** Read buffer from a flattened dump file.
- * @param map Flattened format mapping to be initialized.
- * @param buf Target I/O buffer.
- * @param len Length of data.
- * @param pos File position.
- * @returns Error status.
- *
- * Read data from the flattened segment(s) which contain(s) @p len bytes
- * at position @p pos after rearrangement.
- */
-static kdump_status
-flatmap_pread(struct flattened_map *map, void *buf, size_t len, off_t pos)
-{
- struct flattened_file_map *fmap = &map->fmap;
- const addrxlat_range_t *range, *end;
- off_t off;
-
- range = addrxlat_map_ranges(fmap->map);
- end = range + addrxlat_map_len(fmap->map);
- for (off = pos; range < end && off > range->endoff; ++range)
- off -= range->endoff + 1;
- while (range < end && len) {
- size_t seglen;
-
- seglen = range->endoff + 1 - off;
- if (seglen > len)
- seglen = len;
-
- if (range->meth != ADDRXLAT_SYS_METH_NONE) {
- off_t *flatoffs = fmap->offs;
- unsigned segidx = range->meth;
- kdump_status ret;
-
- ret = fcache_pread(map->fcache, buf, seglen,
- pos + flatoffs[segidx]);
- if (ret != KDUMP_OK)
- return ret;
- } else
- memset(buf, 0, seglen);
-
- buf += seglen;
- len -= seglen;
- pos += seglen;
- ++range;
- off = 0;
- }
-
- if (len)
- memset(buf, 0, len);
- return KDUMP_OK;
-}
-
/** Read buffer from a diskdump file.
* @param ctx Dump file object.
* @param buf Target I/O buffer.
@@ -300,39 +221,6 @@ diskdump_pread(kdump_ctx_t *ctx, void *b
: fcache_pread(ctx->shared->fcache, buf, len, pos);
}
-/** Get a contiguous data chunk from a flattened dump file.
- * @param map Flattened format mapping to be initialized.
- * @param fch File cache chunk, updated on success.
- * @param len Length of data.
- * @param pos File position.
- * @returns Error status.
- *
- * Get a contiguous data chunk from a flattened dump file.
- */
-static inline kdump_status
-flatmap_get_chunk(struct flattened_map *map, struct fcache_chunk *fch,
- size_t len, off_t pos)
-{
- struct flattened_file_map *fmap = &map->fmap;
- const addrxlat_range_t *range, *end;
- off_t off;
-
- range = addrxlat_map_ranges(fmap->map);
- end = range + addrxlat_map_len(fmap->map);
- for (off = pos; range < end && off > range->endoff; ++range)
- off -= range->endoff + 1;
- if (len <= range->endoff + 1 - off) {
- pos += fmap->offs[range->meth];
- return fcache_get_chunk(map->fcache, fch, len, pos);
- }
-
- fch->data = malloc(len);
- if (!fch->data)
- return KDUMP_ERR_SYSTEM;
- fch->nent = 0;
- return flatmap_pread(map, fch->data, len, pos);
-}
-
/** Get a contiguous data chunk from a diskdump file.
* @param ctx Dump file object.
* @param fch File cache chunk, updated on success.
@@ -1072,144 +960,6 @@ open_common(kdump_ctx_t *ctx, void *hdr)
return ret;
}
-#define FLATOFFS_ALLOC_INC 32
-
-/** Initialize flattened dump maps for one file.
- * @param fmap Flattened format mapping to be initialized.
- * @param ctx Dump file object.
- * @returns Error status.
- *
- * Read all flattened segment headers and initialize
- * @p fmap.
- *
- * Note that the mapping may be already partially initialized when this
- * function fails with an error status, so you should always release the
- * associated resources with @ref flatmap_file_cleanup(). As a consequence,
- * the mapping must be initialized to all zeroes prior to calling
- * flatmap_file_init().
- */
-static kdump_status
-flatmap_file_init(struct flattened_file_map *fmap, kdump_ctx_t *ctx)
-{
- struct makedumpfile_data_header hdr;
- addrxlat_range_t range;
- int64_t pos, size;
- unsigned segidx;
- off_t flatpos;
- kdump_status status;
-
- fmap->map = addrxlat_map_new();
- if (!fmap->map)
- return set_error(ctx, KDUMP_ERR_SYSTEM,
- "Cannot allocate %s", "flattened map");
-
- segidx = 0;
- flatpos = MDF_HEADER_SIZE;
- for (;;) {
- status = fcache_pread(ctx->shared->fcache, &hdr, sizeof(hdr),
- flatpos);
- if (status != KDUMP_OK)
- return set_error(ctx, status,
- "Cannot read flattened header at %llu",
- (unsigned long long) flatpos);
- pos = be64toh(hdr.offset);
- if (pos == MDF_OFFSET_END_FLAG)
- break;
- if (pos < 0)
- return set_error(ctx, KDUMP_ERR_CORRUPT,
- "Wrong flattened %s %"PRId64" at %llu",
- "offset", pos,
- (unsigned long long) flatpos);
- size = be64toh(hdr.buf_size);
- if (size <= 0)
- return set_error(ctx, KDUMP_ERR_CORRUPT,
- "Wrong flattened %s %"PRId64" at %llu",
- "segment size", size,
- (unsigned long long) flatpos);
-
- if ((segidx % FLATOFFS_ALLOC_INC) == 0) {
- unsigned newlen = segidx + FLATOFFS_ALLOC_INC;
- off_t *newbuf;
-
- newbuf = realloc(fmap->offs,
- sizeof(*fmap->offs) * newlen);
- if (!newbuf)
- return set_error(ctx, KDUMP_ERR_SYSTEM,
- "Cannot allocate %s",
- "flattened offset array");
- fmap->offs = newbuf;
- }
- flatpos += sizeof(hdr);
- fmap->offs[segidx] = flatpos - pos;
-
- range.endoff = size - 1;
- range.meth = segidx;
- if (addrxlat_map_set(fmap->map, pos, &range) != ADDRXLAT_OK)
- return set_error(ctx, KDUMP_ERR_SYSTEM,
- "Cannot allocate %s",
- "flattened map entry");
-
- ++segidx;
- flatpos += size;
- }
- return KDUMP_OK;
-}
-
-static void
-flatmap_file_cleanup(struct flattened_file_map *fmap)
-{
- if (fmap->map)
- addrxlat_map_decref(fmap->map);
- if (fmap->offs)
- free(fmap->offs);
-}
-
-/** Allocate a flattened dump map.
- * @returns Flattened offset map, or @c NULL on error.
- */
-static struct flattened_map*
-flatmap_alloc(void)
-{
- struct flattened_map *map;
-
- map = calloc(1, sizeof(*map));
- return map;
-}
-
-/** Initialize flattened dump maps for all files.
- * @param map Flattened offset map.
- * @param ctx Dump file object.
- * @returns Error status.
- *
- * Initialize flattened dump maps for all files.
- */
-static kdump_status
-flatmap_init(struct flattened_map *map, kdump_ctx_t *ctx)
-{
- kdump_status status;
-
- map->fcache = ctx->shared->fcache;
- fcache_incref(map->fcache);
-
- status = flatmap_file_init(&map->fmap, ctx);
- if (status != KDUMP_OK)
- return set_error(ctx, status,
- "Cannot rearrange file");
-
- return KDUMP_OK;
-}
-
-static void
-flatmap_free(struct flattened_map *map)
-{
- if (!map)
- return;
- flatmap_file_cleanup(&map->fmap);
- if (map->fcache)
- fcache_decref(map->fcache);
- free(map);
-}
-
static kdump_status
diskdump_probe(kdump_ctx_t *ctx)
{
--- /dev/null
+++ b/src/kdumpfile/flatmap.c
@@ -0,0 +1,271 @@
+/** @internal @file src/kdumpfile/flatmap.c
+ * @brief Routines to handle files in the flattened format.
+ */
+/* Copyright (C) 2024 Petr Tesarik <petr@tesarici.cz>
+
+ This file is free software; you can redistribute it and/or modify
+ it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at
+ your option) any later version
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at
+ your option) any later version
+
+ or both in parallel, as here.
+
+ libkdumpfile is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define _GNU_SOURCE
+
+#include "kdumpfile-priv.h"
+
+#include <stdlib.h>
+
+#define MDF_HEADER_SIZE 4096
+#define MDF_OFFSET_END_FLAG (-(int64_t)1)
+
+/* Flattened segment header */
+struct makedumpfile_data_header {
+ int64_t offset;
+ int64_t buf_size;
+} __attribute__((packed));
+
+#define ALLOC_INC 32
+
+/** Initialize flattened dump maps for one file.
+ * @param fmap Flattened format mapping to be initialized.
+ * @param ctx Dump file object.
+ * @returns Error status.
+ *
+ * Read all flattened segment headers and initialize
+ * @p fmap.
+ *
+ * Note that the mapping may be already partially initialized when this
+ * function fails with an error status, so you should always release the
+ * associated resources with @ref flatmap_file_cleanup(). As a consequence,
+ * the mapping must be initialized to all zeroes prior to calling
+ * flatmap_file_init().
+ */
+static kdump_status
+flatmap_file_init(struct flattened_file_map *fmap, kdump_ctx_t *ctx)
+{
+ struct makedumpfile_data_header hdr;
+ addrxlat_range_t range;
+ int64_t pos, size;
+ unsigned segidx;
+ off_t flatpos;
+ kdump_status status;
+
+ fmap->map = addrxlat_map_new();
+ if (!fmap->map)
+ return set_error(ctx, KDUMP_ERR_SYSTEM,
+ "Cannot allocate %s", "flattened map");
+
+ segidx = 0;
+ flatpos = MDF_HEADER_SIZE;
+ for (;;) {
+ status = fcache_pread(ctx->shared->fcache, &hdr, sizeof(hdr),
+ flatpos);
+ if (status != KDUMP_OK)
+ return set_error(ctx, status,
+ "Cannot read flattened header at %llu",
+ (unsigned long long) flatpos);
+ pos = be64toh(hdr.offset);
+ if (pos == MDF_OFFSET_END_FLAG)
+ break;
+ if (pos < 0)
+ return set_error(ctx, KDUMP_ERR_CORRUPT,
+ "Wrong flattened %s %"PRId64" at %llu",
+ "offset", pos,
+ (unsigned long long) flatpos);
+ size = be64toh(hdr.buf_size);
+ if (size <= 0)
+ return set_error(ctx, KDUMP_ERR_CORRUPT,
+ "Wrong flattened %s %"PRId64" at %llu",
+ "segment size", size,
+ (unsigned long long) flatpos);
+
+ if ((segidx % ALLOC_INC) == 0) {
+ unsigned newlen = segidx + ALLOC_INC;
+ off_t *newbuf;
+
+ newbuf = realloc(fmap->offs,
+ sizeof(*fmap->offs) * newlen);
+ if (!newbuf)
+ return set_error(ctx, KDUMP_ERR_SYSTEM,
+ "Cannot allocate %s",
+ "flattened offset array");
+ fmap->offs = newbuf;
+ }
+ flatpos += sizeof(hdr);
+ fmap->offs[segidx] = flatpos - pos;
+
+ range.endoff = size - 1;
+ range.meth = segidx;
+ if (addrxlat_map_set(fmap->map, pos, &range) != ADDRXLAT_OK)
+ return set_error(ctx, KDUMP_ERR_SYSTEM,
+ "Cannot allocate %s",
+ "flattened map entry");
+
+ ++segidx;
+ flatpos += size;
+ }
+ return KDUMP_OK;
+}
+
+static void
+flatmap_file_cleanup(struct flattened_file_map *fmap)
+{
+ if (fmap->map)
+ addrxlat_map_decref(fmap->map);
+ if (fmap->offs)
+ free(fmap->offs);
+}
+
+/** Allocate a flattened dump map.
+ * @returns Flattened offset map, or @c NULL on error.
+ */
+struct flattened_map*
+flatmap_alloc(void)
+{
+ struct flattened_map *map;
+
+ map = calloc(1, sizeof(*map));
+ return map;
+}
+
+/** Initialize flattened dump maps for all files.
+ * @param map Flattened offset map.
+ * @param ctx Dump file object.
+ * @returns Error status.
+ *
+ * Initialize flattened dump maps for all files.
+ */
+kdump_status
+flatmap_init(struct flattened_map *map, kdump_ctx_t *ctx)
+{
+ kdump_status status;
+
+ map->fcache = ctx->shared->fcache;
+ fcache_incref(map->fcache);
+
+ status = flatmap_file_init(&map->fmap, ctx);
+ if (status != KDUMP_OK)
+ return set_error(ctx, status,
+ "Cannot rearrange file");
+
+ return KDUMP_OK;
+}
+
+/** Release all resources used by a flattened dump map.
+ * @param map Flattened offset map.
+ */
+void
+flatmap_free(struct flattened_map *map)
+{
+ if (!map)
+ return;
+ flatmap_file_cleanup(&map->fmap);
+ if (map->fcache)
+ fcache_decref(map->fcache);
+ free(map);
+}
+
+/** Read buffer from a flattened dump file.
+ * @param map Flattened format mapping to be initialized.
+ * @param buf Target I/O buffer.
+ * @param len Length of data.
+ * @param pos File position.
+ * @returns Error status.
+ *
+ * Read data from the flattened segment(s) which contain(s) @p len bytes
+ * at position @p pos after rearrangement.
+ */
+kdump_status
+flatmap_pread(struct flattened_map *map, void *buf, size_t len,
+ off_t pos)
+{
+ struct flattened_file_map *fmap = &map->fmap;
+ const addrxlat_range_t *range, *end;
+ off_t off;
+
+ range = addrxlat_map_ranges(fmap->map);
+ end = range + addrxlat_map_len(fmap->map);
+ for (off = pos; range < end && off > range->endoff; ++range)
+ off -= range->endoff + 1;
+ while (range < end && len) {
+ size_t seglen;
+
+ seglen = range->endoff + 1 - off;
+ if (seglen > len)
+ seglen = len;
+
+ if (range->meth != ADDRXLAT_SYS_METH_NONE) {
+ off_t *flatoffs = fmap->offs;
+ unsigned segidx = range->meth;
+ kdump_status ret;
+
+ ret = fcache_pread(map->fcache, buf, seglen,
+ pos + flatoffs[segidx]);
+ if (ret != KDUMP_OK)
+ return ret;
+ } else
+ memset(buf, 0, seglen);
+
+ buf += seglen;
+ len -= seglen;
+ pos += seglen;
+ ++range;
+ off = 0;
+ }
+
+ if (len)
+ memset(buf, 0, len);
+ return KDUMP_OK;
+}
+
+/** Get a contiguous data chunk from a flattened dump file.
+ * @param map Flattened format mapping to be initialized.
+ * @param fch File cache chunk, updated on success.
+ * @param len Length of data.
+ * @param pos File position.
+ * @returns Error status.
+ *
+ * Get a contiguous data chunk from a flattened dump file.
+ */
+kdump_status
+flatmap_get_chunk(struct flattened_map *map, struct fcache_chunk *fch,
+ size_t len, off_t pos)
+{
+ struct flattened_file_map *fmap = &map->fmap;
+ const addrxlat_range_t *range, *end;
+ off_t off;
+
+ range = addrxlat_map_ranges(fmap->map);
+ end = range + addrxlat_map_len(fmap->map);
+ for (off = pos; range < end && off > range->endoff; ++range)
+ off -= range->endoff + 1;
+ if (len <= range->endoff + 1 - off) {
+ pos += fmap->offs[range->meth];
+ return fcache_get_chunk(map->fcache, fch, len, pos);
+ }
+
+ fch->data = malloc(len);
+ if (!fch->data)
+ return KDUMP_ERR_SYSTEM;
+ fch->nent = 0;
+ return flatmap_pread(map, fch->data, len, pos);
+}
--- a/src/kdumpfile/kdumpfile-priv.h
+++ b/src/kdumpfile/kdumpfile-priv.h
@@ -1505,6 +1505,39 @@ pfn_to_addr(struct kdump_shared *shared,
return pfn << sget_page_shift(shared);
}
+/* Flattened files. */
+
+/** Offset mapping for a file in the flattened format. */
+struct flattened_file_map {
+ /** Map (rearranged) offset to an index in the offset arrray. */
+ addrxlat_map_t *map;
+
+ /** Differences between flattened and rearranged file offsets. */
+ off_t *offs;
+};
+
+/** Offset mappings for a set of flattened files. */
+struct flattened_map {
+ /** File cache. */
+ struct fcache *fcache;
+
+ /** Mappings for individual files. */
+ struct flattened_file_map fmap;
+};
+
+INTERNAL_DECL(struct flattened_map *, flatmap_alloc,
+ (void));
+INTERNAL_DECL(kdump_status, flatmap_init,
+ (struct flattened_map *map, kdump_ctx_t *ctx));
+INTERNAL_DECL(void, flatmap_free,
+ (struct flattened_map *map));
+INTERNAL_DECL(kdump_status, flatmap_pread,
+ (struct flattened_map *map, void *buf, size_t len,
+ off_t pos));
+INTERNAL_DECL(kdump_status, flatmap_get_chunk,
+ (struct flattened_map *map, struct fcache_chunk *fch,
+ size_t len, off_t pos));
+
/** Check if a character is a POSIX white space.
* @param c Character to check.
*
--- a/src/kdumpfile/Makefile.in
+++ b/src/kdumpfile/Makefile.in
@@ -145,8 +145,9 @@ libkdumpfile_la_DEPENDENCIES = \
$(am__DEPENDENCIES_1)
am_libkdumpfile_la_OBJECTS = aarch64.lo attr.lo bitmap.lo blob.lo \
cache.lo context.lo devmem.lo diskdump.lo elfdump.lo fcache.lo \
- ia32.lo lkcd.lo notes.lo open.lo read.lo s390x.lo s390dump.lo \
- todo.lo util.lo vmcoreinfo.lo vtop.lo ppc64.lo x86_64.lo
+ flatmap.lo ia32.lo lkcd.lo notes.lo open.lo read.lo s390x.lo \
+ s390dump.lo todo.lo util.lo vmcoreinfo.lo vtop.lo ppc64.lo \
+ x86_64.lo
libkdumpfile_la_OBJECTS = $(am_libkdumpfile_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -595,6 +596,7 @@ libkdumpfile_la_SOURCES = \
diskdump.c \
elfdump.c \
fcache.c \
+ flatmap.c \
ia32.c \
lkcd.c \
notes.c \
@@ -734,6 +736,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diskdump.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfdump.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flatmap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ia32.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lkcd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notes.Plo@am__quote@