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@
openSUSE Build Service is sponsored by