crash warns that ELF dump is incomplete like this: WARNING: vmcore: may be truncated or incomplete PT_LOAD p_offset: 218960740 p_filesz: 4194304 bytes required: 223155044 dumpfile size: 219960740 The warning saves a lot of time when figuring out what went wrong, but crash misses explicit dump detection for compressed kdumps. The change adds the warning for compressed kdumps: WARNING: vmcore: may be truncated or incomplete data_offset: 262144 block_size: 65536 total_valid_pages: 2438 first_empty_pd: 100 bytes required: 157467661 dumpfile size: 265982 bytes required is computed as: data_offset (kdump header + bitmaps) + total_valid_pages * page descriptor size (page descriptors) + zero page (that immediately follows page descriptors) + compressed size of every present page in the list of valid pages + block_size for every incomplete page (i.e page descriptor has zero offset) The warning is also printed for incomplete split dumps. Signed-off-by: Roman Bolshakov <r.bolshakov@xxxxxxxxx> --- diskdump.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/diskdump.c b/diskdump.c index de3eeb2..e802d04 100644 --- a/diskdump.c +++ b/diskdump.c @@ -23,6 +23,8 @@ * GNU General Public License for more details. */ +#define _LARGEFILE64_SOURCE 1 /* stat64() */ + #include "defs.h" #include "diskdump.h" #include "xen_dom0.h" @@ -548,6 +550,12 @@ read_dump_header(char *file) ulong pfn; int i, j, max_sect_len; int is_split = 0; + struct stat64 stat; + page_desc_t pd; + ulong page_idx; + ulong first_empty_pd = 0; + int zero_page_counted = 0; + size_t expected_size = 0; if (block_size < 0) return FALSE; @@ -898,13 +906,72 @@ restart: pfn = start; } + expected_size = dd->data_offset; dd->valid_pages = calloc(sizeof(ulong), max_sect_len + 1); dd->max_sect_len = max_sect_len; for (i = 1; i < max_sect_len + 1; i++) { dd->valid_pages[i] = dd->valid_pages[i - 1]; for (j = 0; j < BITMAP_SECT_LEN; j++, pfn++) - if (page_is_dumpable(pfn)) - dd->valid_pages[i]++; + if (page_is_dumpable(pfn)) { + page_idx = dd->valid_pages[i]++; + + offset = dd->data_offset + + page_idx * sizeof(pd); + + if (read_pd(dd->dfd, offset, &pd)) { + /* + * Truncated page descriptor at most + * references full page. + */ + expected_size += block_size; + goto next; + } + + if (pd.offset == 0) { + if (!first_empty_pd) + first_empty_pd = page_idx; + /* + * Incomplete pages at most use the + * whole page. + */ + expected_size += block_size; + } else if (!pd.flags) { + /* + * Zero page has no compression flags. + */ + if (!zero_page_counted) { + expected_size += block_size; + zero_page_counted = 1; + } + } else if (pd.flags) { + /* Regular compressed page */ + expected_size += pd.size; + } + +next: + expected_size += sizeof(pd); + } + } + + if (stat64(dd->filename, &stat) < 0) { + error(INFO, "%s: cannot stat %s\n", + DISKDUMP_VALID() ? "diskdump" : "compressed kdump", + dd->filename); + goto err; + } + + if (expected_size > stat.st_size) { + error(WARNING, + "%s: may be truncated or incomplete\n" + " data_offset: %zu\n" + " block_size: %d\n" + " total_valid_pages: %lu\n" + " first_empty_pd: %lu\n" + " bytes required: %zu\n" + " dumpfile size: %zu\n\n", + dd->filename, dd->data_offset, + dd->block_size, dd->valid_pages[dd->max_sect_len], + first_empty_pd, expected_size, stat.st_size); } return TRUE; -- 2.32.0 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility