File flatmap-Allow-to-use-the-flatmap-API-with-non-flatte.patch of Package libkdumpfile.36085
From: Petr Tesarik <petr@tesarici.cz>
Date: Sun, 29 Sep 2024 18:01:50 +0200
Subject: flatmap: Allow to use the flatmap API with non-flattened files
References: bsc#1223399
Upstream: merged
Git-commit: bc14a715bbcc7698b25064e4b3dbafaa1ea86bcf
The flatmap API now gets enough information to know if a file is flattened
and (where appropriate) read directly from a non-flattened file. In fact,
this is what elfdump_pread() and elfdump_get_chunk() already do.
Moreover, the check adds only little overhead (especially if the function
is inline), so rename the original functions (which can read only flattened
files) by adding a _flat suffix to them and make the API usable with
non-flattened files.
Remove the format-specific diskdump and elfdump functions, which do
essentially the same job as flatmap_pread() and flatmap_get_chunk()
after this change.
Signed-off-by: Petr Tesarik <ptesarik@suse.com>
---
src/kdumpfile/diskdump.c | 70 ++++++++++-------------------------------
src/kdumpfile/elfdump.c | 70 +++++++++--------------------------------
src/kdumpfile/flatmap.c | 8 ++--
src/kdumpfile/kdumpfile-priv.h | 43 ++++++++++++++++++++++++-
4 files changed, 79 insertions(+), 112 deletions(-)
--- a/src/kdumpfile/diskdump.c
+++ b/src/kdumpfile/diskdump.c
@@ -189,47 +189,6 @@ struct setup_data {
static void diskdump_cleanup(struct kdump_shared *shared);
-/** Read buffer from a diskdump file.
- * @param ctx Dump file object.
- * @param buf Target I/O buffer.
- * @param len Length of data.
- * @param pos File position.
- * @returns Error status.
- *
- * Read data from a diskdump file. If the file is flattened, interpret
- * @p pos as if it was already rearranged.
- */
-static inline kdump_status
-diskdump_pread(kdump_ctx_t *ctx, void *buf, size_t len, off_t pos)
-{
- struct disk_dump_priv *ddp = ctx->shared->fmtdata;
-
- return flatmap_isflattened(ddp->flatmap)
- ? flatmap_pread(ddp->flatmap, buf, len, pos)
- : fcache_pread(ctx->shared->fcache, buf, len, pos);
-}
-
-/** Get a contiguous data chunk from a diskdump file.
- * @param ctx Dump file object.
- * @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 diskdump file. If the file is
- * flattened, interpret @p pos as if it was already rearranged.
- */
-static inline kdump_status
-diskdump_get_chunk(kdump_ctx_t *ctx, struct fcache_chunk *fch,
- size_t len, off_t pos)
-{
- struct disk_dump_priv *ddp = ctx->shared->fmtdata;
-
- return flatmap_isflattened(ddp->flatmap)
- ? flatmap_get_chunk(ddp->flatmap, fch, len, pos)
- : fcache_get_chunk(ctx->shared->fcache, fch, len, pos);
-}
-
/** Add a new PFN region.
* @param ctx Dump file context.
* @param rgn PFN region.
@@ -422,7 +381,7 @@ diskdump_read_page(kdump_ctx_t *ctx, str
}
mutex_lock(&ctx->shared->cache_lock);
- ret = diskdump_pread(ctx, &pd, sizeof pd, pd_pos);
+ ret = flatmap_pread(ddp->flatmap, &pd, sizeof pd, pd_pos);
mutex_unlock(&ctx->shared->cache_lock);
if (ret != KDUMP_OK)
return set_error(ctx, ret,
@@ -441,7 +400,7 @@ diskdump_read_page(kdump_ctx_t *ctx, str
"Wrong compressed size: %lu",
(unsigned long)pd.size);
mutex_lock(&ctx->shared->cache_lock);
- ret = diskdump_get_chunk(ctx, &fch, pd.size, pd.offset);
+ ret = flatmap_get_chunk(ddp->flatmap, &fch, pd.size, pd.offset);
mutex_unlock(&ctx->shared->cache_lock);
} else {
if (pd.size != get_page_size(ctx))
@@ -449,7 +408,7 @@ diskdump_read_page(kdump_ctx_t *ctx, str
"Wrong page size: %lu",
(unsigned long)pd.size);
mutex_lock(&ctx->shared->cache_lock);
- ret = diskdump_pread(ctx, pio->chunk.data, pd.size, pd.offset);
+ ret = flatmap_pread(ddp->flatmap, pio->chunk.data, pd.size, pd.offset);
mutex_unlock(&ctx->shared->cache_lock);
}
@@ -518,11 +477,12 @@ diskdump_get_page(kdump_ctx_t *ctx, stru
static kdump_status
read_vmcoreinfo(kdump_ctx_t *ctx, off_t off, size_t size)
{
+ struct disk_dump_priv *ddp = ctx->shared->fmtdata;
struct fcache_chunk fch;
kdump_attr_value_t val;
kdump_status ret;
- ret = diskdump_get_chunk(ctx, &fch, size, off);
+ ret = flatmap_get_chunk(ddp->flatmap, &fch, size, off);
if (ret != KDUMP_OK)
return set_error(ctx, ret,
"Cannot read %zu VMCOREINFO bytes at %llu",
@@ -545,10 +505,11 @@ read_vmcoreinfo(kdump_ctx_t *ctx, off_t
static kdump_status
read_notes(kdump_ctx_t *ctx, off_t off, size_t size)
{
+ struct disk_dump_priv *ddp = ctx->shared->fmtdata;
struct fcache_chunk fch;
kdump_status ret;
- ret = diskdump_get_chunk(ctx, &fch, size, off);
+ ret = flatmap_get_chunk(ddp->flatmap, &fch, size, off);
if (ret != KDUMP_OK)
return set_error(ctx, ret,
"Cannot read %zu note bytes at %llu",
@@ -621,6 +582,7 @@ static kdump_status
read_bitmap(kdump_ctx_t *ctx, int32_t sub_hdr_size,
int32_t bitmap_blocks)
{
+ struct disk_dump_priv *ddp = ctx->shared->fmtdata;
off_t off = (1 + sub_hdr_size) * get_page_size(ctx);
off_t descoff;
size_t bitmapsize;
@@ -645,7 +607,7 @@ read_bitmap(kdump_ctx_t *ctx, int32_t su
if (get_max_pfn(ctx) > max_bitmap_pfn)
set_max_pfn(ctx, max_bitmap_pfn);
- ret = diskdump_get_chunk(ctx, &fch, bitmapsize, off);
+ ret = flatmap_get_chunk(ddp->flatmap, &fch, bitmapsize, off);
if (ret != KDUMP_OK)
return set_error(ctx, ret,
"Cannot read %zu bytes of page bitmap"
@@ -709,6 +671,7 @@ static kdump_status
read_sub_hdr_32(struct setup_data *sdp, int32_t header_version)
{
kdump_ctx_t *ctx = sdp->ctx;
+ struct disk_dump_priv *ddp = ctx->shared->fmtdata;
struct kdump_sub_header_32 subhdr;
kdump_status ret;
@@ -720,8 +683,8 @@ read_sub_hdr_32(struct setup_data *sdp,
if (header_version < 1)
return KDUMP_OK;
- ret = diskdump_pread(ctx, &subhdr, sizeof subhdr,
- get_page_size(ctx));
+ ret = flatmap_pread(ddp->flatmap, &subhdr, sizeof subhdr,
+ get_page_size(ctx));
if (ret != KDUMP_OK)
return set_error(ctx, ret,
"Cannot read subheader");
@@ -792,6 +755,7 @@ static kdump_status
read_sub_hdr_64(struct setup_data *sdp, int32_t header_version)
{
kdump_ctx_t *ctx = sdp->ctx;
+ struct disk_dump_priv *ddp = ctx->shared->fmtdata;
struct kdump_sub_header_64 subhdr;
kdump_status ret;
@@ -803,8 +767,8 @@ read_sub_hdr_64(struct setup_data *sdp,
if (header_version < 1)
return KDUMP_OK;
- ret = diskdump_pread(ctx, &subhdr, sizeof subhdr,
- get_page_size(ctx));
+ ret = flatmap_pread(ddp->flatmap, &subhdr, sizeof subhdr,
+ get_page_size(ctx));
if (ret != KDUMP_OK)
return set_error(ctx, ret,
"Cannot read subheader");
@@ -974,6 +938,7 @@ diskdump_probe(kdump_ctx_t *ctx)
{ 'K', 'D', 'U', 'M', 'P', ' ', ' ', ' ' };
char hdr[sizeof(struct disk_dump_header_64)];
+ struct disk_dump_priv *ddp;
char desc[32];
kdump_status status;
@@ -981,7 +946,8 @@ diskdump_probe(kdump_ctx_t *ctx)
if (status != KDUMP_OK)
return status;
- status = diskdump_pread(ctx, hdr, sizeof hdr, 0);
+ ddp = ctx->shared->fmtdata;
+ status = flatmap_pread(ddp->flatmap, hdr, sizeof hdr, 0);
if (status != KDUMP_OK)
return set_error(ctx, status, "Cannot read dump header");
--- a/src/kdumpfile/elfdump.c
+++ b/src/kdumpfile/elfdump.c
@@ -168,44 +168,6 @@ mach2arch(unsigned mach, int elfclass)
}
}
-/** Read buffer from an ELF dump file.
- * @param flatmap Flattened offset map.
- * @param buf Target I/O buffer.
- * @param len Length of data.
- * @param pos File position.
- * @returns Error status.
- *
- * Read data from an ELF dump file. If the file is flattened, interpret
- * @p pos as if it was already rearranged.
- */
-static inline kdump_status
-elfdump_pread(struct flattened_map *flatmap, void *buf, size_t len,
- off_t pos)
-{
- return flatmap_isflattened(flatmap)
- ? flatmap_pread(flatmap, buf, len, pos)
- : fcache_pread(flatmap->fcache, buf, len, pos);
-}
-
-/** Get a contiguous data chunk from an ELF dump file.
- * @param flatmap Flattened offset map.
- * @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 an ELF dump file. If the file is
- * flattened, interpret @p pos as if it was already rearranged.
- */
-static inline kdump_status
-elfdump_get_chunk(struct flattened_map *flatmap, struct fcache_chunk *fch,
- size_t len, off_t pos)
-{
- return flatmap_isflattened(flatmap)
- ? flatmap_get_chunk(flatmap, fch, len, pos)
- : fcache_get_chunk(flatmap->fcache, fch, len, pos);
-}
-
/** Find the LOAD segment that is closest to a physical address.
* @param edp ELF dump private data.
* @param paddr Requested physical address.
@@ -301,7 +263,7 @@ elf_read_page(kdump_ctx_t *ctx, struct p
if (size > loadaddr + pls->filesz - addr)
size = loadaddr + pls->filesz - addr;
- status = elfdump_pread(edp->flatmap, p, size, pos);
+ status = flatmap_pread(edp->flatmap, p, size, pos);
if (status != KDUMP_OK)
goto err_read;
p += size;
@@ -374,7 +336,7 @@ elf_get_page(kdump_ctx_t *ctx, struct pa
return cache_get_page(ctx, pio, elf_read_page);
mutex_lock(&ctx->shared->cache_lock);
- status = elfdump_get_chunk(edp->flatmap, &pio->chunk, sz,
+ status = flatmap_get_chunk(edp->flatmap, &pio->chunk, sz,
pls->file_offset + addr - loadaddr);
mutex_unlock(&ctx->shared->cache_lock);
return status;
@@ -785,7 +747,7 @@ xc_p2m_first_step(addrxlat_step_t *step,
pos = edp->xen_map_offset + idx * sizeof(struct xen_p2m);
mutex_lock(&shared->cache_lock);
- status = elfdump_pread(edp->flatmap, &p2m, sizeof p2m, pos);
+ status = flatmap_pread(edp->flatmap, &p2m, sizeof p2m, pos);
mutex_unlock(&shared->cache_lock);
if (status != KDUMP_OK)
return addrxlat_ctx_err(step->ctx, ADDRXLAT_ERR_NODATA,
@@ -823,7 +785,7 @@ xc_m2p_first_step(addrxlat_step_t *step,
pos = edp->xen_map_offset + idx * sizeof(struct xen_p2m);
mutex_lock(&shared->cache_lock);
- status = elfdump_pread(edp->flatmap, &p2m, sizeof p2m, pos);
+ status = flatmap_pread(edp->flatmap, &p2m, sizeof p2m, pos);
mutex_unlock(&shared->cache_lock);
if (status != KDUMP_OK)
return addrxlat_ctx_err(step->ctx, ADDRXLAT_ERR_NODATA,
@@ -927,7 +889,7 @@ xc_get_page(kdump_ctx_t *ctx, struct pag
offset = edp->xen_pages_offset + ((off_t)idx << get_page_shift(ctx));
mutex_lock(&ctx->shared->cache_lock);
- status = elfdump_get_chunk(edp->flatmap, &pio->chunk,
+ status = flatmap_get_chunk(edp->flatmap, &pio->chunk,
get_page_size(ctx), offset);
mutex_unlock(&ctx->shared->cache_lock);
return status;
@@ -1028,7 +990,7 @@ init_strtab(kdump_ctx_t *ctx, unsigned s
if (!edp->strtab)
return KDUMP_ERR_SYSTEM;
- status = elfdump_pread(edp->flatmap, edp->strtab, ps->size,
+ status = flatmap_pread(edp->flatmap, edp->strtab, ps->size,
ps->file_offset);
if (status != KDUMP_OK) {
free(edp->strtab);
@@ -1067,7 +1029,7 @@ init_elf32(kdump_ctx_t *ctx, Elf32_Ehdr
if (offset != 0 && (shnum == 0 || phnum == PN_XNUM)) {
Elf32_Shdr *sect;
- ret = elfdump_get_chunk(edp->flatmap, &fch,
+ ret = flatmap_get_chunk(edp->flatmap, &fch,
dump16toh(ctx, ehdr->e_shentsize),
offset);
if (ret != KDUMP_OK)
@@ -1099,7 +1061,7 @@ init_elf32(kdump_ctx_t *ctx, Elf32_Ehdr
Elf32_Phdr *prog;
struct load_segment *pls;
- ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset);
+ ret = flatmap_get_chunk(edp->flatmap, &fch, entsz, offset);
if (ret != KDUMP_OK)
return set_error(ctx, ret,
"Cannot read ELF %s #%" PRIu32 " at %llu",
@@ -1126,7 +1088,7 @@ init_elf32(kdump_ctx_t *ctx, Elf32_Ehdr
for (i = 0; i < shnum; ++i) {
Elf32_Shdr *sect;
- ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset);
+ ret = flatmap_get_chunk(edp->flatmap, &fch, entsz, offset);
if (ret != KDUMP_OK)
return set_error(ctx, ret,
"Cannot read ELF %s #%" PRIu32 " at %llu",
@@ -1167,7 +1129,7 @@ init_elf64(kdump_ctx_t *ctx, Elf64_Ehdr
if (offset != 0 && (shnum == 0 || phnum == PN_XNUM)) {
Elf64_Shdr *sect;
- ret = elfdump_get_chunk(edp->flatmap, &fch,
+ ret = flatmap_get_chunk(edp->flatmap, &fch,
dump16toh(ctx, ehdr->e_shentsize),
offset);
if (ret != KDUMP_OK)
@@ -1199,7 +1161,7 @@ init_elf64(kdump_ctx_t *ctx, Elf64_Ehdr
Elf64_Phdr *prog;
struct load_segment *pls;
- ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset);
+ ret = flatmap_get_chunk(edp->flatmap, &fch, entsz, offset);
if (ret != KDUMP_OK)
return set_error(ctx, ret,
"Cannot read ELF %s #%" PRIu64 " at %llu",
@@ -1226,7 +1188,7 @@ init_elf64(kdump_ctx_t *ctx, Elf64_Ehdr
for (i = 0; i < shnum; ++i) {
Elf64_Shdr *sect;
- ret = elfdump_get_chunk(edp->flatmap, &fch, entsz, offset);
+ ret = flatmap_get_chunk(edp->flatmap, &fch, entsz, offset);
if (ret != KDUMP_OK)
return set_error(ctx, ret,
"Cannot read ELF %s #%" PRIu64 " at %llu",
@@ -1262,7 +1224,7 @@ walk_elf_notes(kdump_ctx_t *ctx, walk_no
for (i = 0; i < edp->num_note_segments; ++i) {
struct load_segment *seg = edp->note_segments + i;
- ret = elfdump_get_chunk(edp->flatmap, &fch, seg->filesz,
+ ret = flatmap_get_chunk(edp->flatmap, &fch, seg->filesz,
seg->file_offset);
if (ret != KDUMP_OK)
return set_error(ctx, ret,
@@ -1405,7 +1367,7 @@ open_common(kdump_ctx_t *ctx)
return set_error(ctx, ret,
"Cannot create Xen PFN map");
} else if (!strcmp(name, ".note.Xen")) {
- ret = elfdump_get_chunk(edp->flatmap, &fch, sect->size,
+ ret = flatmap_get_chunk(edp->flatmap, &fch, sect->size,
sect->file_offset);
if (ret != KDUMP_OK)
return set_error(ctx, ret,
@@ -1416,7 +1378,7 @@ open_common(kdump_ctx_t *ctx)
return set_error(ctx, ret,
"Cannot process Xen notes");
} else if (!strcmp(name, ".xen_prstatus")) {
- ret = elfdump_get_chunk(edp->flatmap, &fch, sect->size,
+ ret = flatmap_get_chunk(edp->flatmap, &fch, sect->size,
sect->file_offset);
if (ret != KDUMP_OK)
return set_error(ctx, ret,
@@ -1512,7 +1474,7 @@ elf_probe(kdump_ctx_t *ctx)
if (ret != KDUMP_OK)
return ret;
- ret = elfdump_get_chunk(edp->flatmap, &fch, sizeof(Elf64_Ehdr), 0);
+ ret = flatmap_get_chunk(edp->flatmap, &fch, sizeof(Elf64_Ehdr), 0);
if (ret != KDUMP_OK)
return set_error(ctx, ret, "Cannot read dump header");
--- a/src/kdumpfile/flatmap.c
+++ b/src/kdumpfile/flatmap.c
@@ -231,8 +231,8 @@ flatmap_free(struct flattened_map *map)
* at position @p pos after rearrangement.
*/
kdump_status
-flatmap_pread(struct flattened_map *map, void *buf, size_t len,
- off_t pos)
+flatmap_pread_flat(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;
@@ -283,8 +283,8 @@ flatmap_pread(struct flattened_map *map,
* 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)
+flatmap_get_chunk_flat(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;
--- a/src/kdumpfile/kdumpfile-priv.h
+++ b/src/kdumpfile/kdumpfile-priv.h
@@ -1531,10 +1531,10 @@ 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,
+INTERNAL_DECL(kdump_status, flatmap_pread_flat,
(struct flattened_map *map, void *buf, size_t len,
off_t pos));
-INTERNAL_DECL(kdump_status, flatmap_get_chunk,
+INTERNAL_DECL(kdump_status, flatmap_get_chunk_flat,
(struct flattened_map *map, struct fcache_chunk *fch,
size_t len, off_t pos));
@@ -1548,6 +1548,45 @@ flatmap_isflattened(struct flattened_map
return map->fmap.map;
}
+/** Read buffer from a possibly flattened dump file.
+ * @param flatmap Flattened offset map.
+ * @param buf Target I/O buffer.
+ * @param len Length of data.
+ * @param pos File position.
+ * @returns Error status.
+ *
+ * Read data from an ELF dump file. If the file is flattened, interpret
+ * @p pos as if it was already rearranged.
+ */
+static inline kdump_status
+flatmap_pread(struct flattened_map *flatmap, void *buf, size_t len,
+ off_t pos)
+{
+ return flatmap_isflattened(flatmap)
+ ? flatmap_pread_flat(flatmap, buf, len, pos)
+ : fcache_pread(flatmap->fcache, buf, len, pos);
+}
+
+/** Get a contiguous data chunk from a possibly flattend dump file.
+ * @param flatmap Flattened offset map.
+ * @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 an ELF dump file. If the file is
+ * flattened, interpret @p pos as if it was already rearranged.
+ */
+static inline kdump_status
+flatmap_get_chunk(struct flattened_map *flatmap, struct fcache_chunk *fch,
+ size_t len, off_t pos)
+{
+ return flatmap_isflattened(flatmap)
+ ? flatmap_get_chunk_flat(flatmap, fch, len, pos)
+ : fcache_get_chunk(flatmap->fcache, fch, len, pos);
+}
+
+
/** Check if a character is a POSIX white space.
* @param c Character to check.
*