Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libkdumpfile for openSUSE:Factory checked in at 2023-11-06 21:14:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libkdumpfile (Old) and /work/SRC/openSUSE:Factory/.libkdumpfile.new.17445 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libkdumpfile" Mon Nov 6 21:14:40 2023 rev:23 rq:1123600 version:0.5.3 Changes: -------- --- /work/SRC/openSUSE:Factory/libkdumpfile/libkdumpfile.changes 2023-07-18 22:07:33.762800604 +0200 +++ /work/SRC/openSUSE:Factory/.libkdumpfile.new.17445/libkdumpfile.changes 2023-11-06 21:14:53.452617513 +0100 @@ -1,0 +2,6 @@ +Mon Nov 6 14:27:10 UTC 2023 - Petr TesaÅÃk <p...@tesarici.cz> + +- Upgrade to libkdumpfile version 0.5.3 + * Support flattened KDUMP format. + +------------------------------------------------------------------- Old: ---- libkdumpfile-0.5.2.tar.xz New: ---- libkdumpfile-0.5.3.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libkdumpfile.spec ++++++ --- /var/tmp/diff_new_pack.Zfg7W2/_old 2023-11-06 21:14:54.092641073 +0100 +++ /var/tmp/diff_new_pack.Zfg7W2/_new 2023-11-06 21:14:54.092641073 +0100 @@ -48,7 +48,7 @@ %define oldpython python Name: libkdumpfile -Version: 0.5.2 +Version: 0.5.3 Release: 0 %if "%name" == "libkdumpfile" Summary: Kernel dump file access library ++++++ libkdumpfile-0.5.2.tar.xz -> libkdumpfile-0.5.3.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/NEWS new/libkdumpfile-0.5.3/NEWS --- old/libkdumpfile-0.5.2/NEWS 2023-07-17 11:30:50.000000000 +0200 +++ new/libkdumpfile-0.5.3/NEWS 2023-11-06 14:59:42.000000000 +0100 @@ -1,3 +1,7 @@ +0.5.3 +----- + * Support flattened KDUMP format. + 0.5.2 ----- * Full support for 32-bit Arm. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/configure.ac new/libkdumpfile-0.5.3/configure.ac --- old/libkdumpfile-0.5.2/configure.ac 2023-07-17 11:30:50.000000000 +0200 +++ new/libkdumpfile-0.5.3/configure.ac 2023-11-06 14:59:42.000000000 +0100 @@ -20,7 +20,7 @@ dnl Package release versioning m4_define([pkg_major_version], [0]) m4_define([pkg_minor_version], [5]) -m4_define([pkg_micro_version], [2]) +m4_define([pkg_micro_version], [3]) m4_define([pkg_version], [pkg_major_version.pkg_minor_version.pkg_micro_version]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/src/kdumpfile/Makefile.am new/libkdumpfile-0.5.3/src/kdumpfile/Makefile.am --- old/libkdumpfile-0.5.2/src/kdumpfile/Makefile.am 2023-07-17 11:30:50.000000000 +0200 +++ new/libkdumpfile-0.5.3/src/kdumpfile/Makefile.am 2023-11-06 14:59:42.000000000 +0100 @@ -62,7 +62,7 @@ $(SNAPPY_LIBS) \ $(ZSTD_LIBS) -libkdumpfile_la_LDFLAGS = -version-info 10:1:0 +libkdumpfile_la_LDFLAGS = -version-info 10:2:0 if HAVE_LD_VERSION_SCRIPT libkdumpfile_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libkdumpfile.map diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/src/kdumpfile/diskdump.c new/libkdumpfile-0.5.3/src/kdumpfile/diskdump.c --- old/libkdumpfile-0.5.2/src/kdumpfile/diskdump.c 2023-07-17 11:30:50.000000000 +0200 +++ new/libkdumpfile-0.5.3/src/kdumpfile/diskdump.c 2023-11-06 14:59:42.000000000 +0100 @@ -50,6 +50,27 @@ /** @cond TARGET_ABI */ +#define MDF_SIGNATURE "makedumpfile" +#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 { + char signature[MDF_SIG_LEN]; + int64_t type; + 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" */ @@ -198,6 +219,12 @@ /** Memory region mapping. */ struct pfn_file_map mem_pagemap; + /** File offset mapping for flattened files. */ + addrxlat_map_t **flatmap; + + /** Differences between flattened and rearranged file offsets. */ + off_t **flatoffs; + /** Page descriptor mapping. */ struct pfn_file_map pdmap[]; }; @@ -226,6 +253,126 @@ static void diskdump_cleanup(struct kdump_shared *shared); +/** Read buffer from a flattened dump file. + * @param ctx Dump file object. + * @param buf Target I/O buffer. + * @param len Length of data. + * @param fidx Index of the file to read from. + * @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 +flattened_pread(kdump_ctx_t *ctx, void *buf, size_t len, + unsigned fidx, off_t pos) +{ + struct disk_dump_priv *ddp = ctx->shared->fmtdata; + const addrxlat_range_t *range, *end; + off_t off; + + range = addrxlat_map_ranges(ddp->flatmap[fidx]); + end = range + addrxlat_map_len(ddp->flatmap[fidx]); + 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 = ddp->flatoffs[fidx]; + kdump_status ret; + + ret = fcache_pread(ctx->shared->fcache, buf, seglen, + fidx, pos + flatoffs[range->meth]); + 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. + * @param len Length of data. + * @param fidx Index of the file to read from. + * @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, + unsigned fidx, off_t pos) +{ + struct disk_dump_priv *ddp = ctx->shared->fmtdata; + + return ddp->flatmap + ? flattened_pread(ctx, buf, len, fidx, pos) + : fcache_pread(ctx->shared->fcache, buf, len, fidx, pos); +} + +/** Get a contiguous data chunk from a flattened dump file. + * @param ctx Dump file object. + * @param fch File cache chunk, updated on success. + * @param len Length of data. + * @param fidx Index of the file to read from. + * @param pos File position. + * @returns Error status. + * + * Get a contiguous data chunk from a flattened dump file. Currently, this is + * implemented using a dynamically allocated buffer, even if the underlying + * file cache buffer might be used. + */ +static inline kdump_status +flattened_get_chunk(kdump_ctx_t *ctx, struct fcache_chunk *fch, + size_t len, unsigned fidx, off_t pos) +{ + fch->data = malloc(len); + if (!fch->data) + return KDUMP_ERR_SYSTEM; + fch->nent = 0; + return flattened_pread(ctx, fch->data, len, fidx, 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 fidx Index of the file to read from. + * @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, unsigned fidx, off_t pos) +{ + struct disk_dump_priv *ddp = ctx->shared->fmtdata; + + return ddp->flatmap + ? flattened_get_chunk(ctx, fch, len, fidx, pos) + : fcache_get_chunk(ctx->shared->fcache, fch, len, fidx, pos); +} + /** Convert a PFN to a page descriptor file offset. * @param pdmap Page descriptor mapping. * @param pfn Page frame number. @@ -382,8 +529,8 @@ } mutex_lock(&ctx->shared->cache_lock); - ret = fcache_pread(ctx->shared->fcache, &pd, sizeof pd, - pdmap->fidx, pd_pos); + ret = diskdump_pread(ctx, &pd, sizeof pd, + pdmap->fidx, pd_pos); mutex_unlock(&ctx->shared->cache_lock); if (ret != KDUMP_OK) return set_error(ctx, ret, @@ -411,8 +558,8 @@ /* read page data */ mutex_lock(&ctx->shared->cache_lock); - ret = fcache_pread(ctx->shared->fcache, buf, pd.size, - pdmap->fidx, pd.offset); + ret = diskdump_pread(ctx, buf, pd.size, + pdmap->fidx, pd.offset); mutex_unlock(&ctx->shared->cache_lock); if (ret != KDUMP_OK) return set_error(ctx, ret, @@ -548,7 +695,7 @@ struct fcache_chunk fch; kdump_status ret; - ret = fcache_get_chunk(ctx->shared->fcache, &fch, size, 0, off); + ret = diskdump_get_chunk(ctx, &fch, size, 0, off); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read %zu note bytes at %llu", @@ -609,8 +756,7 @@ if (get_max_pfn(ctx) > max_bitmap_pfn) set_max_pfn(ctx, max_bitmap_pfn); - ret = fcache_get_chunk(ctx->shared->fcache, - &fch, bitmapsize, pdmap->fidx, off); + ret = diskdump_get_chunk(ctx, &fch, bitmapsize, pdmap->fidx, off); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read %zu bytes of page bitmap" @@ -769,8 +915,8 @@ if (sdp->header_version < 1) return KDUMP_OK; - ret = fcache_pread(ctx->shared->fcache, &subhdr, sizeof subhdr, - pdmap->fidx, get_page_size(ctx)); + ret = diskdump_pread(ctx, &subhdr, sizeof subhdr, + pdmap->fidx, get_page_size(ctx)); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read subheader"); @@ -808,8 +954,8 @@ struct pfn_file_map *pdmap = &ddp->pdmap[fidx]; pdmap->fidx = fidx; - ret = fcache_pread(ctx->shared->fcache, dh, sizeof *dh, - fidx, 0); + ret = diskdump_pread(ctx, dh, sizeof *dh, + fidx, 0); if (ret != KDUMP_OK) { ret = set_error(ctx, ret, "Cannot read header"); break; @@ -875,8 +1021,8 @@ if (sdp->header_version < 1) return KDUMP_OK; - ret = fcache_pread(ctx->shared->fcache, &subhdr, sizeof subhdr, - pdmap->fidx, get_page_size(ctx)); + ret = diskdump_pread(ctx, &subhdr, sizeof subhdr, + pdmap->fidx, get_page_size(ctx)); if (ret != KDUMP_OK) return set_error(ctx, ret, "Cannot read subheader"); @@ -937,8 +1083,8 @@ struct pfn_file_map *pdmap = &ddp->pdmap[fidx]; pdmap->fidx = fidx; - ret = fcache_pread(ctx->shared->fcache, dh, sizeof *dh, - fidx, 0); + ret = diskdump_pread(ctx, dh, sizeof *dh, + fidx, 0); if (ret != KDUMP_OK) { ret = set_error(ctx, ret, "Cannot read header"); break; @@ -999,9 +1145,8 @@ kdump_pfn_t maxpfn; kdump_status status; - status = fcache_get_chunk(ctx->shared->fcache, &fch, - ddp->mem_pagemap_size, 0, - ddp->mem_pagemap_off); + status = diskdump_get_chunk(ctx, &fch, ddp->mem_pagemap_size, + 0, ddp->mem_pagemap_off); if (status != KDUMP_OK) return set_error(ctx, status, "Cannot read %zu bytes of page bitmap" @@ -1046,18 +1191,17 @@ return set_attr(ctx, attr, ATTR_INVALID, &val); } +/** Initialize diskdump private data. + * @param ctx Dump file object. + * @returns Error status. + * + * Allocate and initialize diskdump format private data. The private data + * should be eventually cleaned up by @ref diskdump_cleanup(). + */ static kdump_status -open_common(kdump_ctx_t *ctx, void *hdr) +init_private(kdump_ctx_t *ctx) { - struct disk_dump_header_32 *dh32 = hdr; - struct disk_dump_header_64 *dh64 = hdr; struct disk_dump_priv *ddp; - struct setup_data sd; - kdump_bmp_t *bmp; - kdump_status ret; - - memset(&sd, 0, sizeof sd); - sd.ctx = ctx; ddp = calloc(1, sizeof(*ddp) + get_num_files(ctx) * sizeof(ddp->pdmap[0])); @@ -1072,6 +1216,21 @@ ddp->cbuf_slot = -1; ctx->shared->fmtdata = ddp; + return KDUMP_OK; +} + +static kdump_status +open_common(kdump_ctx_t *ctx, void *hdr) +{ + struct disk_dump_priv *ddp = ctx->shared->fmtdata;; + struct disk_dump_header_32 *dh32 = hdr; + struct disk_dump_header_64 *dh64 = hdr; + struct setup_data sd; + kdump_bmp_t *bmp; + kdump_status ret; + + memset(&sd, 0, sizeof sd); + sd.ctx = ctx; set_addrspace_caps(ctx->xlat, ADDRXLAT_CAPS(ADDRXLAT_MACHPHYSADDR)); @@ -1122,29 +1281,179 @@ return ret; } +#define FLATOFFS_ALLOC_INC 32 + +/** Initialize flattened dump maps for one file. + * @param ctx Dump file object. + * @param fidx File index. + * @returns Error status. + * + * Read all flattened segment headers from file @p fidx and initialize + * @p flatmap and @p flatoffs. + */ +static kdump_status +init_flattened_file(kdump_ctx_t *ctx, unsigned fidx) +{ + struct disk_dump_priv *ddp = ctx->shared->fmtdata; + struct makedumpfile_data_header hdr; + addrxlat_map_t *flatmap; + off_t *flatoffs = NULL; + addrxlat_range_t range; + int64_t pos, size; + unsigned segidx; + off_t flatpos; + kdump_status status; + + flatmap = addrxlat_map_new(); + if (!flatmap) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate %s", "flattened map"); + ddp->flatmap[fidx] = flatmap; + + segidx = 0; + flatpos = MDF_HEADER_SIZE; + for (;;) { + status = fcache_pread(ctx->shared->fcache, &hdr, sizeof(hdr), + fidx, 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; + + flatoffs = realloc(flatoffs, + sizeof(*flatoffs) * newlen); + if (!flatoffs) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate %s", + "flattened offset array"); + ddp->flatoffs[fidx] = flatoffs; + } + flatpos += sizeof(hdr); + flatoffs[segidx] = flatpos - pos; + + range.endoff = size - 1; + range.meth = segidx; + if (addrxlat_map_set(flatmap, pos, &range) != ADDRXLAT_OK) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate %s", + "flattened map entry"); + + ++segidx; + flatpos += size; + } + return KDUMP_OK; +} + +/** Initialize flattened dump maps for all files. + * @param ctx Dump file object. + * @returns Error status. + * + * Initialize flattened dump maps for all files. + */ +static kdump_status +init_flattened_maps(kdump_ctx_t *ctx) +{ + struct disk_dump_priv *ddp = ctx->shared->fmtdata; + unsigned fidx; + kdump_status status; + + ddp->flatmap = calloc(ddp->num_files, sizeof(addrxlat_map_t *)); + if (!ddp->flatmap) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate %s", "flatmap array"); + ddp->flatoffs = calloc(ddp->num_files, sizeof(off_t *)); + if (!ddp->flatoffs) + return set_error(ctx, KDUMP_ERR_SYSTEM, + "Cannot allocate %s", "flatoffs array"); + + for (fidx = 0; fidx < get_num_files(ctx); ++fidx) { + status = init_flattened_file(ctx, fidx); + if (status != KDUMP_OK) + return set_error(ctx, status, + "Cannot rearrange file #%u", fidx); + } + + return KDUMP_OK; +} + static kdump_status diskdump_probe(kdump_ctx_t *ctx) { + static const char magic_flattened[MDF_SIG_LEN] = MDF_SIGNATURE; static const char magic_diskdump[] = { 'D', 'I', 'S', 'K', 'D', 'U', 'M', 'P' }; static const char magic_kdump[] = { 'K', 'D', 'U', 'M', 'P', ' ', ' ', ' ' }; char hdr[sizeof(struct disk_dump_header_64)]; + char desc[32]; kdump_status status; status = fcache_pread(ctx->shared->fcache, hdr, sizeof hdr, 0, 0); if (status != KDUMP_OK) return set_error(ctx, status, "Cannot read dump header"); + if (!memcmp(hdr, magic_flattened, sizeof magic_flattened)) { + struct makedumpfile_header *flathdr = + (struct makedumpfile_header*) hdr; + + if (be64toh(flathdr->type) != MDF_TYPE_FLAT_HEADER) + return set_error(ctx, KDUMP_ERR_NOTIMPL, + "Unknown flattened %s: %" PRId64 "\n", + "type", be64toh(flathdr->type)); + if (be64toh(flathdr->version) != MDF_VERSION_FLAT_HEADER) + return set_error(ctx, KDUMP_ERR_NOTIMPL, + "Unknown flattened %s: %" PRId64 "\n", + "version", be64toh(flathdr->version)); + + status = init_private(ctx); + if (status != KDUMP_OK) + return status; + + status = init_flattened_maps(ctx); + if (status != KDUMP_OK) + return status; + + status = flattened_pread(ctx, &hdr, sizeof hdr, 0, 0); + if (status != KDUMP_OK) + return set_error(ctx, status, "Cannot read dump header"); + strcpy(desc, "Flattened "); + } else + desc[0] = '\0'; + if (!memcmp(hdr, magic_diskdump, sizeof magic_diskdump)) - set_file_description(ctx, "Diskdump"); + strcat(desc, "Diskdump"); else if (!memcmp(hdr, magic_kdump, sizeof magic_kdump)) - set_file_description(ctx, "Compressed KDUMP"); + strcat(desc, "Compressed KDUMP"); else return set_error(ctx, KDUMP_NOPROBE, "Unrecognized diskdump signature"); + set_file_description(ctx, desc); + + if (!ctx->shared->fmtdata) { + status = init_private(ctx); + if (status != KDUMP_OK) + return status; + } + return open_common(ctx, hdr); } @@ -1173,6 +1482,22 @@ } if (ddp->cbuf_slot >= 0) per_ctx_free(shared, ddp->cbuf_slot); + if (ddp->flatmap) { + for (fidx = 0; fidx < ddp->num_files; ++fidx) { + addrxlat_map_t *flatmap = ddp->flatmap[fidx]; + if (flatmap) + addrxlat_map_decref(flatmap); + } + free(ddp->flatmap); + } + if (ddp->flatoffs) { + for (fidx = 0; fidx < ddp->num_files; ++fidx) { + off_t *flatoffs = ddp->flatoffs[fidx]; + if (flatoffs) + free(flatoffs); + } + free(ddp->flatoffs); + } free(ddp); shared->fmtdata = NULL; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/Makefile.am new/libkdumpfile-0.5.3/tests/Makefile.am --- old/libkdumpfile-0.5.2/tests/Makefile.am 2023-07-17 11:30:50.000000000 +0200 +++ new/libkdumpfile-0.5.3/tests/Makefile.am 2023-11-06 14:59:42.000000000 +0100 @@ -197,9 +197,11 @@ diskdump-basic-lzo \ diskdump-basic-snappy \ diskdump-basic-zstd \ + diskdump-flat-raw \ diskdump-multiread \ diskdump-excluded \ diskdump-split \ + diskdump-split-flat \ diskdump-v6-arm \ diskdump-v6-ia32 \ early-version-code \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump-basic new/libkdumpfile-0.5.3/tests/diskdump-basic --- old/libkdumpfile-0.5.2/tests/diskdump-basic 2023-07-17 11:30:50.000000000 +0200 +++ new/libkdumpfile-0.5.3/tests/diskdump-basic 2023-11-06 14:59:42.000000000 +0100 @@ -14,6 +14,7 @@ cat "$expectfile" >> "$datafile" ./mkdiskdump "$dumpfile" <<EOF +$extraparam version = 6 arch_name = x86_64 block_size = 4096 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump-flat-raw new/libkdumpfile-0.5.3/tests/diskdump-flat-raw --- old/libkdumpfile-0.5.2/tests/diskdump-flat-raw 1970-01-01 01:00:00.000000000 +0100 +++ new/libkdumpfile-0.5.3/tests/diskdump-flat-raw 2023-11-06 14:59:42.000000000 +0100 @@ -0,0 +1,5 @@ +#! /bin/sh +extraparam="flattened = yes" +pageflags=raw +. "$srcdir"/diskdump-basic +exit 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump-split new/libkdumpfile-0.5.3/tests/diskdump-split --- old/libkdumpfile-0.5.2/tests/diskdump-split 2023-07-17 11:30:50.000000000 +0200 +++ new/libkdumpfile-0.5.3/tests/diskdump-split 2023-11-06 14:59:42.000000000 +0100 @@ -1,3 +1,5 @@ +#! /bin/sh + # # Check reading data from a split dump file # @@ -142,7 +144,7 @@ echo "Check combined page map" ./checkattr "$dumpfile.1" "$dumpfile.2" "$dumpfile.3" <<EOF file.pagemap = bitmap: 0x1e -memory.pagemap = bitmap: 0x1f +memory.pagemap = bitmap: 0x3f EOF rc=$? if [ $rc -ne 0 ]; then @@ -153,7 +155,7 @@ echo "Check combined page map with files out of order" ./checkattr "$dumpfile.2" "$dumpfile.3" "$dumpfile.1" <<EOF file.pagemap = bitmap: 0x1e -memory.pagemap = bitmap: 0x1f +memory.pagemap = bitmap: 0x3f EOF rc=$? if [ $rc -ne 0 ]; then @@ -164,7 +166,7 @@ echo "Check combined page map with one file missing" ./checkattr "$dumpfile.3" "$dumpfile.1" <<EOF file.pagemap = bitmap: 0x1a -memory.pagemap = bitmap: 0x1f +memory.pagemap = bitmap: 0x3f EOF rc=$? if [ $rc -ne 0 ]; then diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump-split-flat new/libkdumpfile-0.5.3/tests/diskdump-split-flat --- old/libkdumpfile-0.5.2/tests/diskdump-split-flat 1970-01-01 01:00:00.000000000 +0100 +++ new/libkdumpfile-0.5.3/tests/diskdump-split-flat 2023-11-06 14:59:42.000000000 +0100 @@ -0,0 +1,177 @@ +#! /bin/sh + +# +# Check reading data from a flattened split dump file +# + +mkdir -p out || exit 99 + +name=$( basename "$0" ) +dumpfile="out/${name}.dump" +resultfile="out/${name}.result" +name=${name%-flat} +datafile="$srcdir/${name}.data" +expectfile="$srcdir/${name}.expect" + +desc=" +flattened = yes +version = 6 +arch_name = x86_64 +block_size = 4096 +phys_base = 0 +max_mapnr = 0x100 +sub_hdr_size = 1 + +uts.sysname = Linux +uts.nodename = test-node +uts.release = 3.4.5-test +uts.version = #1 SMP Fri Jan 22 14:02:42 UTC 2016 (1234567) +uts.machine = x86_64 +uts.domainname = (none) + +nr_cpus = 1 + +split = 1 + +DATA = $datafile +" + +# Create three split dump files + +./mkdiskdump "$dumpfile.1" <<EOF +$desc +start_pfn = 1 +end_pfn = 2 +DATA = $datafile +EOF +rc=$? +if [ $rc -ne 0 ]; then + echo "Cannot create diskdump file" >&2 + exit $rc +fi +echo "Created split diskdump dump: $dumpfile.1" + +./mkdiskdump "$dumpfile.2" <<EOF +$desc +start_pfn = 2 +end_pfn = 3 +DATA = $datafile +EOF +rc=$? +if [ $rc -ne 0 ]; then + echo "Cannot create diskdump file" >&2 + exit $rc +fi +echo "Created split diskdump dump: $dumpfile.2" + +./mkdiskdump "$dumpfile.3" <<EOF +$desc +start_pfn = 3 +end_pfn = 6 +DATA = $datafile +EOF +rc=$? +if [ $rc -ne 0 ]; then + echo "Cannot create diskdump file" >&2 + exit $rc +fi +echo "Created split diskdump dump: $dumpfile.3" + +echo "Check that file 1 only contains PFN 1" +./dumpdata "$dumpfile.1" 0x1000 8 > "$resultfile.1" +rc=$? +if [ $rc -ne 0 ]; then + echo "Cannot dump DISKDUMP data" >&2 + exit $rc +fi +if ! diff "$expectfile.1" "$resultfile.1"; then + echo "Results do not match" >&2 + exit 1 +fi +./dumpdata "$dumpfile.1" 0x2000 8 > "$resultfile.1.err" 2>/dev/null +rc=$? +if [ $rc -eq 0 ]; then + echo "Unexpected success!" >&2 + exit 1 +fi + +echo "Check that file 2 only contains PFN 2" +./dumpdata "$dumpfile.2" 0x2000 8 > "$resultfile.2" +rc=$? +if [ $rc -ne 0 ]; then + echo "Cannot dump DISKDUMP data" >&2 + exit $rc +fi +if ! diff "$expectfile.2" "$resultfile.2"; then + echo "Results do not match" >&2 + exit 1 +fi +./dumpdata "$dumpfile.2" 0x1000 8 > "$resultfile.2.err" 2>/dev/null +rc=$? +if [ $rc -eq 0 ]; then + echo "Unexpected success!" >&2 + exit 1 +fi + +echo "Check that file 3 contains PFN 3 and PFN 4" +./dumpdata "$dumpfile.3" 0x3ffc 8 > "$resultfile.3" +rc=$? +if [ $rc -ne 0 ]; then + echo "Cannot dump DISKDUMP data" >&2 + exit $rc +fi +if ! diff "$expectfile.3" "$resultfile.3"; then + echo "Results do not match" >&2 + exit 1 +fi +./dumpdata "$dumpfile.3" 0x2000 8 > "$resultfile.3.err" 2>/dev/null +rc=$? +if [ $rc -eq 0 ]; then + echo "Unexpected success!" >&2 + exit 1 +fi + +echo "Check that data from all three files is combined" +./dumpdata -n3 "$dumpfile.1" "$dumpfile.2" "$dumpfile.3" 0x1ffc 8 0x2ffc 8 0x3ffc 8 > "$resultfile" +rc=$? +if [ $rc -ne 0 ]; then + echo "Cannot dump DISKDUMP data" >&2 + exit $rc +fi +if ! diff "$expectfile" "$resultfile"; then + echo "Results do not match" >&2 + exit 1 +fi + +echo "Check combined page map" +./checkattr "$dumpfile.1" "$dumpfile.2" "$dumpfile.3" <<EOF +file.pagemap = bitmap: 0x3e +memory.pagemap = bitmap: 0x3f +EOF +rc=$? +if [ $rc -ne 0 ]; then + echo "Attribute check failed" >&2 + exit $rc +fi + +echo "Check combined page map with files out of order" +./checkattr "$dumpfile.2" "$dumpfile.3" "$dumpfile.1" <<EOF +file.pagemap = bitmap: 0x3e +memory.pagemap = bitmap: 0x3f +EOF +rc=$? +if [ $rc -ne 0 ]; then + echo "Attribute check failed" >&2 + exit $rc +fi + +echo "Check combined page map with one file missing" +./checkattr "$dumpfile.3" "$dumpfile.1" <<EOF +file.pagemap = bitmap: 0x3a +memory.pagemap = bitmap: 0x3f +EOF +rc=$? +if [ $rc -ne 0 ]; then + echo "Attribute check failed" >&2 + exit $rc +fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump-split.data new/libkdumpfile-0.5.3/tests/diskdump-split.data --- old/libkdumpfile-0.5.2/tests/diskdump-split.data 2023-07-17 11:30:50.000000000 +0200 +++ new/libkdumpfile-0.5.3/tests/diskdump-split.data 2023-11-06 14:59:42.000000000 +0100 @@ -1,3 +1,5 @@ +@0x5000 raw +dead*2048 @0x0000 raw ff*4096 @0x1000 raw diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/diskdump.h new/libkdumpfile-0.5.3/tests/diskdump.h --- old/libkdumpfile-0.5.2/tests/diskdump.h 2023-07-17 11:30:50.000000000 +0200 +++ new/libkdumpfile-0.5.3/tests/diskdump.h 2023-11-06 14:59:42.000000000 +0100 @@ -31,6 +31,27 @@ #include <stdint.h> +#define MDF_SIGNATURE "makedumpfile" +#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 { + char signature[MDF_SIG_LEN]; + int64_t type; + 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) + #define DISKDUMP_SIGNATURE "DISKDUMP" #define KDUMP_SIGNATURE "KDUMP " #define SIGNATURE_LEN 8 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libkdumpfile-0.5.2/tests/mkdiskdump.c new/libkdumpfile-0.5.3/tests/mkdiskdump.c --- old/libkdumpfile-0.5.2/tests/mkdiskdump.c 2023-07-17 11:30:50.000000000 +0200 +++ new/libkdumpfile-0.5.3/tests/mkdiskdump.c 2023-11-06 14:59:42.000000000 +0100 @@ -32,6 +32,7 @@ #include <stdio.h> #include <stdlib.h> #include <ctype.h> +#include <errno.h> #include "config.h" #include "testutil.h" @@ -68,8 +69,6 @@ #if USE_LZO lzo_bytep lzo_wrkmem; #endif - - unsigned long skip; }; static endian_t be; @@ -91,6 +90,9 @@ struct blob *blob; }; +static bool flattened; +static unsigned long long flattened_type = MDF_TYPE_FLAT_HEADER; +static unsigned long long flattened_version = MDF_VERSION_FLAT_HEADER; static char *arch_name; static unsigned long long compression; static char *signature; @@ -134,6 +136,9 @@ static const struct param param_array[] = { /* meta-data */ + PARAM_YESNO("flattened", flattened), + PARAM_NUMBER("flattened.type", flattened_type), + PARAM_NUMBER("flattened.version", flattened_version), PARAM_STRING("arch_name", arch_name), PARAM_NUMBER("compression", compression), @@ -218,6 +223,29 @@ } static int +write_chunk(FILE *f, off_t off, const void *ptr, size_t sz, const char *what) +{ + if (flattened) { + struct makedumpfile_data_header hdr = { + .offset = htobe64(off), + .buf_size = htobe64(sz), + }; + if (fwrite(&hdr, sizeof hdr, 1, f) != 1) { + perror("flattened segment header"); + return -1; + } + } else if (fseek(f, off, SEEK_SET) != 0) { + fprintf(stderr, "seek %s: %s\n", what, strerror(errno)); + return -1; + } + if (fwrite(ptr, sz, 1, f) != 1) { + fprintf(stderr, "write %s: %s\n", what, strerror(errno)); + return -1; + } + return 0; +} + +static int writeheader_32(FILE *f) { struct timeval tv; @@ -226,7 +254,7 @@ if (gettimeofday(&tv, NULL) != 0) { perror("gettimeofday"); - return -1; + return TEST_ERR; } /* initialize dump header to zero */ @@ -259,15 +287,8 @@ hdr.current_cpu = htodump32(be, current_cpu); hdr.nr_cpus = htodump32(be, nr_cpus); - if (fseek(f, 0, SEEK_SET) != 0) { - perror("seek header"); - return -1; - } - - if (fwrite(&hdr, sizeof hdr, 1, f) != 1) { - perror("write header"); - return -1; - } + if (write_chunk(f, 0, &hdr, sizeof hdr, "header")) + return TEST_ERR; subhdr.phys_base = htodump32(be, phys_base); subhdr.dump_level = htodump32(be, dump_level); @@ -290,17 +311,11 @@ subhdr.end_pfn_64 = htodump64(be, end_pfn); subhdr.max_mapnr_64 = htodump64(be, max_mapnr); - if (fseek(f, DISKDUMP_HEADER_BLOCKS * block_size, SEEK_SET) != 0) { - perror("seek subheader"); - return -1; - } - - if (fwrite(&subhdr, sizeof subhdr, 1, f) != 1) { - perror("write subheader"); - return -1; - } + if (write_chunk(f, DISKDUMP_HEADER_BLOCKS * block_size, + &subhdr, sizeof subhdr, "subheader")) + return TEST_ERR; - return 0; + return TEST_OK; } static int @@ -312,7 +327,7 @@ if (gettimeofday(&tv, NULL) != 0) { perror("gettimeofday"); - return -1; + return TEST_ERR; } /* initialize dump header to zero */ @@ -345,15 +360,8 @@ hdr.current_cpu = htodump32(be, current_cpu); hdr.nr_cpus = htodump32(be, nr_cpus); - if (fseek(f, 0, SEEK_SET) != 0) { - perror("seek header"); - return -1; - } - - if (fwrite(&hdr, sizeof hdr, 1, f) != 1) { - perror("write header"); - return -1; - } + if (write_chunk(f, 0, &hdr, sizeof hdr, "header")) + return TEST_ERR; subhdr.phys_base = htodump64(be, phys_base); subhdr.dump_level = htodump32(be, dump_level); @@ -376,17 +384,11 @@ subhdr.end_pfn_64 = htodump64(be, end_pfn); subhdr.max_mapnr_64 = htodump64(be, max_mapnr); - if (fseek(f, DISKDUMP_HEADER_BLOCKS * block_size, SEEK_SET) != 0) { - perror("seek subheader"); - return -1; - } - - if (fwrite(&subhdr, sizeof subhdr, 1, f) != 1) { - perror("write subheader"); - return -1; - } + if (write_chunk(f, DISKDUMP_HEADER_BLOCKS * block_size, + &subhdr, sizeof subhdr, "subheader")) + return TEST_ERR; - return 0; + return TEST_OK; } static int @@ -409,24 +411,11 @@ pgkdump->flags = 0; pgkdump->compress = compress_auto; - pgkdump->skip = 0; p = endp; while (*p && isspace(*p)) ++p; - if (!strncmp(p, "skip=", 5)) { - p += 5; - pgkdump->skip = strtoul(p, &endp, 0); - if (*endp && !isspace(*endp)) { - fprintf(stderr, "Invalid skip: %s\n", p); - return TEST_FAIL; - } - p = endp; - while (*p && isspace(*p)) - ++p; - } - if (!*p) return TEST_OK; @@ -682,36 +671,19 @@ buf = pg->buf; } pd.offset = htodump64(be, dataoff); - pd.size = htodump32(be, buflen + pgkdump->skip); + pd.size = htodump32(be, buflen); pd.flags = htodump32(be, flags); pd.page_flags = htodump64(be, 0); pdidx = bitmap_index(bitmap2, pfn) - start_pdidx; - if (fseek(pgkdump->f, pdoff + pdidx * sizeof pd, SEEK_SET) != 0) { - perror("seek page desc"); + if (write_chunk(pgkdump->f, pdoff + pdidx * sizeof pd, + &pd, sizeof pd, "page desc")) return TEST_ERR; - } - if (fwrite(&pd, sizeof pd, 1, pgkdump->f) != 1) { - perror("write page desc"); - return TEST_ERR; - } - if (fseek(pgkdump->f, dataoff, SEEK_SET) != 0) { - perror("seek page data"); + if (write_chunk(pgkdump->f, dataoff, buf, buflen, "page data")) return TEST_ERR; - } - if (fwrite(buf, 1, buflen, pgkdump->f) != buflen) { - perror("write page data"); - return TEST_ERR; - } dataoff += buflen; - if (pgkdump->skip && - fseek(pgkdump->f, pgkdump->skip, SEEK_CUR) != 0) { - perror("skip page data"); - return TEST_ERR; - } - return TEST_OK; } @@ -724,7 +696,7 @@ int rc; if (!data_file) - return TEST_OK; + return writeheader(f); pgkdump.f = f; pgkdump.addr = 0; @@ -779,18 +751,17 @@ if (rc != TEST_OK) goto out_bitmap2; - if (fseek(f, (1 + sub_hdr_size) * block_size, SEEK_SET) != 0) { - perror("seek bitmap"); - rc = TEST_ERR; + rc = writeheader(f); + if (rc != TEST_OK) goto out_bitmap2; - } - if (fwrite(bitmap1, block_size, bmp_blocks1, f) != bmp_blocks1) { - perror("write 1st bitmap"); + + if (write_chunk(f, (1 + sub_hdr_size) * block_size, + bitmap1, block_size * bmp_blocks1, "1st bitmap")) { rc = TEST_ERR; goto out_bitmap2; } - if (fwrite(bitmap2, block_size, bmp_blocks1, f) != bmp_blocks1) { - perror("write 2nd bitmap"); + if (write_chunk(f, (1 + sub_hdr_size + bmp_blocks1) * block_size, + bitmap2, block_size * bmp_blocks1, "2nd bitmap")) { rc = TEST_ERR; goto out_bitmap2; } @@ -827,13 +798,41 @@ { int rc; + if (flattened) { + struct makedumpfile_header hdr = { + .signature = MDF_SIGNATURE, + .type = htobe64(flattened_type), + .version = htobe64(flattened_version), + }; + size_t remain; + + if (fwrite(&hdr, sizeof hdr, 1, f) != 1) { + perror("flattened header"); + return TEST_ERR; + } + remain = MDF_HEADER_SIZE - sizeof hdr; + while (remain--) { + if (putc(0, f) != 0) { + perror("flattened header padding"); + return TEST_ERR; + } + } + } + rc = writedata(f); if (rc != 0) return rc; - rc = writeheader(f); - if (rc != 0) - return rc; + if (flattened) { + struct makedumpfile_data_header hdr = { + .offset = htobe64(MDF_OFFSET_END_FLAG), + .buf_size = htobe64(MDF_OFFSET_END_FLAG), + }; + if (fwrite(&hdr, sizeof hdr, 1, f) != 1) { + perror("end segment header"); + return TEST_ERR; + } + } return 0; }