[PATCH 0/3] Add a "percpu" command
by Petr Tesarik
Hi all,
a few people complained to me that the crash utility lacks a
user-friendly interface for percpu variables, especially if they are
dynamically allocated. I implemented a new command which should make
these people happy.
Tested on kernel 3.11, but I didn't really add anything
version-dependent (instead I used the existing infrastructure).
Comments welcome!
Petr Tesarik
11 years, 2 months
[PATCH v3] crash utility: fix max_mapnr issue on system has over 44-bit addressing
by Jingbai Ma
The patch will add support for new compressed dumpfile header_version 6.
This bug was posted here:
http://lists.infradead.org/pipermail/kexec/2013-September/009587.html
This patch will add 3 new fields in struct kdump_sub_header.
unsigned long long start_pfn_64; /* header_version 6 and later */
unsigned long long end_pfn_64; /* header_version 6 and later */
unsigned long long max_mapnr_64; /* header_version 6 and later */
And the old "unsigned int max_mapnr" in struct disk_dump_header will
not be used anymore. But still be there for compatibility purpose.
The corresponding patch for makedumpfile can be found here:
http://lists.infradead.org/pipermail/kexec/2013-October/009727.html
Changelog:
v3:
- Fix a bug that failed to work with old split format kdumps.
v2:
- Rename max_mapnr in struct kdump_sub_header to max_mapnr_64.
- Change type of max_mapnr_64 from unsigned long to unsigned long long.
In x86 PAE mode on x86_32 kernel, the address may exceeds 44bit limit.
- Add start_pfn_64, end_pfn_64 for struct kdump_sub_header.
- Add a 64bit max_mapnr in struct diskdump_data. The max_mapnr_64 in
the sub-header only exists in compressed kdump file format, so can't
be used in diskdump file format.
- Merge a patch from Dave Anderson that fixed bitmap_len issue.
v1:
- http://lists.infradead.org/pipermail/kexec/2013-September/009663.html
Signed-off-by: Jingbai Ma <jingbai.ma(a)hp.com>
Tested-by: Lisa Mitchell <lisa.mitchell(a)hp.com>
---
diskdump.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++------------
diskdump.h | 17 +++++++-
2 files changed, 112 insertions(+), 27 deletions(-)
diff --git a/diskdump.c b/diskdump.c
index 0819a3f..bb7a33e 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -40,11 +40,13 @@ struct diskdump_data {
struct disk_dump_sub_header *sub_header;
struct kdump_sub_header *sub_header_kdump;
+ unsigned long long max_mapnr; /* 64bit max_mapnr */
+
size_t data_offset;
int block_size;
int block_shift;
char *bitmap;
- int bitmap_len;
+ off_t bitmap_len;
char *dumpable_bitmap;
int byte, bit;
char *compressed_page; /* copy of compressed page data */
@@ -170,9 +172,9 @@ add_diskdump_data(char* name)
dd->filename = name;
if (CRASHDEBUG(1))
- fprintf(fp, "%s: start_pfn=%lu, end_pfn=%lu\n", name,
- dd->sub_header_kdump->start_pfn,
- dd->sub_header_kdump->end_pfn);
+ fprintf(fp, "%s: start_pfn=%llu, end_pfn=%llu\n", name,
+ dd->sub_header_kdump->start_pfn_64,
+ dd->sub_header_kdump->end_pfn_64);
}
static void
@@ -199,13 +201,13 @@ get_bit(char *map, int byte, int bit)
}
static inline int
-page_is_ram(unsigned int nr)
+page_is_ram(unsigned long nr)
{
return get_bit(dd->bitmap, nr >> 3, nr & 7);
}
static inline int
-page_is_dumpable(unsigned int nr)
+page_is_dumpable(unsigned long nr)
{
return dd->dumpable_bitmap[nr>>3] & (1 << (nr & 7));
}
@@ -214,7 +216,7 @@ static inline int
dump_is_partial(const struct disk_dump_header *header)
{
return header->bitmap_blocks >=
- divideup(divideup(header->max_mapnr, 8), dd->block_size) * 2;
+ divideup(divideup(dd->max_mapnr, 8), dd->block_size) * 2;
}
static int
@@ -321,6 +323,9 @@ x86_process_elf_notes(void *note_ptr, unsigned long size_note)
* [40] unsigned long size_note; / header_version 4 and later /
* [44] off_t offset_eraseinfo; / header_version 5 and later /
* [52] unsigned long size_eraseinfo; / header_version 5 and later /
+ * [56] unsigned long long start_pfn_64; / header_version 6 and later /
+ * [64] unsigned long long end_pfn_64; / header_version 6 and later /
+ * [72] unsigned long long max_mapnr_64; / header_version 6 and later /
* };
*
* But when compiled on an ARM processor, each 64-bit "off_t" would be pushed
@@ -337,7 +342,10 @@ x86_process_elf_notes(void *note_ptr, unsigned long size_note)
* [40] off_t offset_note; / header_version 4 and later /
* [48] unsigned long size_note; / header_version 4 and later /
* [56] off_t offset_eraseinfo; / header_version 5 and later /
- * [62] unsigned long size_eraseinfo; / header_version 5 and later /
+ * [64] unsigned long size_eraseinfo; / header_version 5 and later /
+ * [72] unsigned long long start_pfn_64; / header_version 6 and later /
+ * [80] unsigned long long end_pfn_64; / header_version 6 and later /
+ * [88] unsigned long long max_mapnr_64; / header_version 6 and later /
* };
*
*/
@@ -357,6 +365,10 @@ struct kdump_sub_header_ARM_target {
int pad3;
off_t offset_eraseinfo; /* header_version 5 and later */
unsigned long size_eraseinfo; /* header_version 5 and later */
+ int pad4;
+ unsigned long long start_pfn_64; /* header_version 6 and later */
+ unsigned long long end_pfn_64; /* header_version 6 and later */
+ unsigned long long max_mapnr_64; /* header_version 6 and later */
};
static void
@@ -380,6 +392,15 @@ arm_kdump_header_adjust(int header_version)
kdsh->offset_eraseinfo = kdsh_ARM_target->offset_eraseinfo;
kdsh->size_eraseinfo = kdsh_ARM_target->size_eraseinfo;
}
+ if (header_version >= 6) {
+ kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn_64;
+ kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn_64;
+ kdsh->max_mapnr_64 = kdsh_ARM_target->map_mapnr_64;
+ } else {
+ kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn;
+ kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn;
+ kdsh->max_mapnr_64 = dd->map_mapnr;
+ }
}
#endif /* __i386__ && ARM */
@@ -390,7 +411,10 @@ read_dump_header(char *file)
struct disk_dump_sub_header *sub_header = NULL;
struct kdump_sub_header *sub_header_kdump = NULL;
size_t size;
- int bitmap_len;
+ off_t bitmap_len;
+ char *bufptr;
+ size_t len;
+ size_t bytes_read;
int block_size = (int)sysconf(_SC_PAGESIZE);
off_t offset;
const off_t failed = (off_t)-1;
@@ -540,8 +564,27 @@ restart:
#if defined(__i386__) && defined(ARM)
arm_kdump_header_adjust(header->header_version);
#endif
+ /* use 64bit max_mapnr in compressed kdump file sub-header */
+ if (header->header_version >= 6)
+ dd->max_mapnr = dd->sub_header_kdump->max_mapnr_64;
+ else {
+ dd->sub_header_kdump->start_pfn_64
+ = dd->sub_header_kdump->start_pfn;
+ dd->sub_header_kdump->end_pfn_64
+ = dd->sub_header_kdump->end_pfn;
+ }
+ } else {
+ /* the 64bit max_mapnr only exists in sub-header of compressed
+ * kdump file, if it's not a compressed kdump file, we have to
+ * use the old 32bit max_mapnr in dumpfile header.
+ * max_mapnr may be truncated here.
+ */
+ dd->max_mapnr = header->max_mapnr;
}
+ if (header->header_version < 6)
+ dd->max_mapnr = header->max_mapnr;
+
/* read memory bitmap */
bitmap_len = block_size * header->bitmap_blocks;
dd->bitmap_len = bitmap_len;
@@ -571,11 +614,27 @@ restart:
DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
goto err;
}
+#ifdef OLDWAY
if (read(dd->dfd, dd->bitmap, bitmap_len) < bitmap_len) {
error(INFO, "%s: cannot read memory bitmap\n",
DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
goto err;
}
+#else
+ bufptr = dd->bitmap;
+ len = bitmap_len;
+ while (len) {
+ bytes_read = read(dd->dfd, bufptr, len);
+ if (bytes_read < 0) {
+ error(INFO, "%s: cannot read memory bitmap\n",
+ DISKDUMP_VALID() ? "diskdump"
+ : "compressed kdump");
+ goto err;
+ }
+ len -= bytes_read;
+ bufptr += bytes_read;
+ }
+#endif
}
if (dump_is_partial(header))
@@ -679,13 +738,13 @@ restart:
}
if (!is_split) {
- max_sect_len = divideup(header->max_mapnr, BITMAP_SECT_LEN);
+ max_sect_len = divideup(dd->max_mapnr, BITMAP_SECT_LEN);
pfn = 0;
dd->filename = file;
}
else {
- ulong start = sub_header_kdump->start_pfn;
- ulong end = sub_header_kdump->end_pfn;
+ unsigned long long start = sub_header_kdump->start_pfn_64;
+ unsigned long long end = sub_header_kdump->end_pfn_64;
max_sect_len = divideup(end - start + 1, BITMAP_SECT_LEN);
pfn = start;
}
@@ -727,8 +786,9 @@ pfn_to_pos(ulong pfn)
ulong p1, p2;
if (KDUMP_SPLIT()) {
- p1 = pfn - dd->sub_header_kdump->start_pfn;
- p2 = round(p1, BITMAP_SECT_LEN) + dd->sub_header_kdump->start_pfn;
+ p1 = pfn - dd->sub_header_kdump->start_pfn_64;
+ p2 = round(p1, BITMAP_SECT_LEN)
+ + dd->sub_header_kdump->start_pfn_64;
}
else {
p1 = pfn;
@@ -1034,12 +1094,12 @@ read_diskdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
if (KDUMP_SPLIT()) {
/* Find proper dd */
int i;
- unsigned long start_pfn;
- unsigned long end_pfn;
+ unsigned long long start_pfn;
+ unsigned long long end_pfn;
for (i=0; i<num_dumpfiles; i++) {
- start_pfn = dd_list[i]->sub_header_kdump->start_pfn;
- end_pfn = dd_list[i]->sub_header_kdump->end_pfn;
+ start_pfn = dd_list[i]->sub_header_kdump->start_pfn_64;
+ end_pfn = dd_list[i]->sub_header_kdump->end_pfn_64;
if ((pfn >= start_pfn) && (pfn <= end_pfn)) {
dd = dd_list[i];
break;
@@ -1058,14 +1118,14 @@ read_diskdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
curpaddr = paddr & ~((physaddr_t)(dd->block_size-1));
page_offset = paddr & ((physaddr_t)(dd->block_size-1));
- if ((pfn >= dd->header->max_mapnr) || !page_is_ram(pfn)) {
+ if ((pfn >= dd->max_mapnr) || !page_is_ram(pfn)) {
if (CRASHDEBUG(8)) {
fprintf(fp, "read_diskdump: SEEK_ERROR: "
"paddr/pfn: %llx/%lx ",
(ulonglong)paddr, pfn);
- if (pfn >= dd->header->max_mapnr)
- fprintf(fp, "max_mapnr: %x\n",
- dd->header->max_mapnr);
+ if (pfn >= dd->max_mapnr)
+ fprintf(fp, "max_mapnr: %llx\n",
+ dd->max_mapnr);
else
fprintf(fp, "!page_is_ram\n");
}
@@ -1517,7 +1577,7 @@ __diskdump_memory_dump(FILE *fp)
fprintf(fp, " block_size: %d\n", dh->block_size);
fprintf(fp, " sub_hdr_size: %d\n", dh->sub_hdr_size);
fprintf(fp, " bitmap_blocks: %u\n", dh->bitmap_blocks);
- fprintf(fp, " max_mapnr: %u\n", dh->max_mapnr);
+ fprintf(fp, " max_mapnr: %llu\n", dd->max_mapnr);
fprintf(fp, " total_ram_blocks: %u\n", dh->total_ram_blocks);
fprintf(fp, " device_blocks: %u\n", dh->device_blocks);
fprintf(fp, " written_blocks: %u\n", dh->written_blocks);
@@ -1662,6 +1722,20 @@ __diskdump_memory_dump(FILE *fp)
dump_eraseinfo(fp);
}
}
+ if (dh->header_version >= 6) {
+ fprintf(fp, " start_pfn_64: ");
+ if (KDUMP_SPLIT())
+ fprintf(fp, "%lld (0x%llx)\n",
+ kdsh->start_pfn_64, kdsh->start_pfn_64);
+ else
+ fprintf(fp, "(unused)\n");
+ fprintf(fp, " end_pfn_64: ");
+ if (KDUMP_SPLIT())
+ fprintf(fp, "%lld (0x%llx)\n",
+ kdsh->end_pfn_64, kdsh->end_pfn_64);
+ else
+ fprintf(fp, "(unused)\n");
+ }
fprintf(fp, "\n");
} else
fprintf(fp, "(n/a)\n\n");
@@ -1670,7 +1744,7 @@ __diskdump_memory_dump(FILE *fp)
fprintf(fp, " block_size: %d\n", dd->block_size);
fprintf(fp, " block_shift: %d\n", dd->block_shift);
fprintf(fp, " bitmap: %lx\n", (ulong)dd->bitmap);
- fprintf(fp, " bitmap_len: %d\n", dd->bitmap_len);
+ fprintf(fp, " bitmap_len: %ld\n", dd->bitmap_len);
fprintf(fp, " dumpable_bitmap: %lx\n", (ulong)dd->dumpable_bitmap);
fprintf(fp, " byte: %d\n", dd->byte);
fprintf(fp, " bit: %d\n", dd->bit);
diff --git a/diskdump.h b/diskdump.h
index 9ab10b6..0492351 100644
--- a/diskdump.h
+++ b/diskdump.h
@@ -42,7 +42,9 @@ struct disk_dump_header {
header in blocks */
unsigned int bitmap_blocks; /* Size of Memory bitmap in
block */
- unsigned int max_mapnr; /* = max_mapnr */
+ unsigned int max_mapnr; /* = max_mapnr, 32bit only,
+ full 64bit in sub header.
+ Do NOT use this anymore! */
unsigned int total_ram_blocks;/* Number of blocks should be
written */
unsigned int device_blocks; /* Number of total blocks in
@@ -61,14 +63,23 @@ struct kdump_sub_header {
unsigned long phys_base;
int dump_level; /* header_version 1 and later */
int split; /* header_version 2 and later */
- unsigned long start_pfn; /* header_version 2 and later */
- unsigned long end_pfn; /* header_version 2 and later */
+ unsigned long start_pfn; /* header_version 2 and later,
+ 32bit only, full 64bit in
+ start_pfn_64.
+ Do not use this anymore! */
+ unsigned long end_pfn; /* header_version 2 and later,
+ 32bit only, full 64bit in
+ end_pfn_64.
+ Do not use this anymore! */
off_t offset_vmcoreinfo; /* header_version 3 and later */
unsigned long size_vmcoreinfo; /* header_version 3 and later */
off_t offset_note; /* header_version 4 and later */
unsigned long size_note; /* header_version 4 and later */
off_t offset_eraseinfo; /* header_version 5 and later */
unsigned long size_eraseinfo; /* header_version 5 and later */
+ unsigned long long start_pfn_64; /* header_version 6 and later */
+ unsigned long long end_pfn_64; /* header_version 6 and later */
+ unsigned long long max_mapnr_64; /* header_version 6 and later */
};
/* page flags */
11 years, 2 months
[PATCH v3] makedumpfile: fix max_mapnr issue on system has over 44-bit addressing
by Jingbai Ma
This patch will fix a bug of makedumpfile doesn't work correctly on system
has over 44-bit addressing in compression dump mode.
This bug was posted here:
http://lists.infradead.org/pipermail/kexec/2013-September/009587.html
This patch will add 3 new fields in struct kdump_sub_header.
unsigned long long start_pfn_64; /* header_version 6 and later */
unsigned long long end_pfn_64; /* header_version 6 and later */
unsigned long long max_mapnr_64; /* header_version 6 and later */
And the old "unsigned int max_mapnr" in struct disk_dump_header will
not be used anymore, but still be there for compatibility purpose.
The max_mapnr_64 only exists in strcut kdump_sub_header, and that only
for compressed kdump format, so for ELF format kdump files (non-compressed),
only the max_mapnr is available, so it still may be truncated for addresses
exceed 44bit (above 16TB).
This patch will change the header_version to 6.
The corresponding patch for crash utility will be sent out separately.
This patch doesn't change sadump_header.
Changelog:
v3:
- Change notes for max_mapnr, start_pfn and end_pfn as obsolete.
- Remove "(32bit)" from debug messages of max_mapnr, start_pfn and end_pfn.
- Set the 32bit start_pfn and end_pfn to UINT_MAX.
- Remove bitmap writting enhancement to another seperate patch.
- Change type of len_bitmap in struct DumpInfo back to unsigned long.
v2:
- Rename max_mapnr in struct kdump_sub_header to max_mapnr_64.
- Change type of max_mapnr_64 from unsigned long to unsigned long long.
In x86 PAE mode on x86_32 kernel, the address may exceeds 44bit limit.
- Add start_pfn_64, end_pfn_64 for struct kdump_sub_header.
- Only print 64bit start_pfn_64, end_pfn_64 and max_mapnr_64
debug messages for disk dump header version >= 6.
- Change type of bitmap_len in struct DumpInfo, from unsigned long to
unsigned long long.
- Enhance bitmap writting function in reassemble_kdump_header().
Prevent bitmap writting failure if the size of bitmap is too large to
fit a sigle write.
v1:
- http://lists.infradead.org/pipermail/kexec/2013-September/009662.html
Signed-off-by: Jingbai Ma <jingbai.ma(a)hp.com>
Tested-by: Lisa Mitchell <lisa.mitchell(a)hp.com>
---
IMPLEMENTATION | 15 ++++++++++---
diskdump_mod.h | 15 ++++++++++---
makedumpfile.c | 66 ++++++++++++++++++++++++++++++++++++++++++++------------
3 files changed, 76 insertions(+), 20 deletions(-)
diff --git a/IMPLEMENTATION b/IMPLEMENTATION
index f0f3135..2f4cfd6 100644
--- a/IMPLEMENTATION
+++ b/IMPLEMENTATION
@@ -48,7 +48,9 @@
header in blocks */
unsigned int bitmap_blocks; /* Size of Memory bitmap in
block */
- unsigned int max_mapnr; /* = max_mapnr */
+ unsigned int max_mapnr; /* = max_mapnr, OBSOLETE!
+ 32bit only, full 64bit
+ in sub header. */
unsigned int total_ram_blocks;/* Number of blocks should be
written */
unsigned int device_blocks; /* Number of total blocks in
@@ -69,14 +71,21 @@
unsigned long phys_base;
int dump_level; /* header_version 1 and later */
int split; /* header_version 2 and later */
- unsigned long start_pfn; /* header_version 2 and later */
- unsigned long end_pfn; /* header_version 2 and later */
+ unsigned long start_pfn; /* header_version 2 and later,
+ OBSOLETE! 32bit only, full
+ 64bit in start_pfn_64. */
+ unsigned long end_pfn; /* header_version 2 and later,
+ OBSOLETE! 32bit only, full
+ 64bit in end_pfn_64. */
off_t offset_vmcoreinfo;/* header_version 3 and later */
unsigned long size_vmcoreinfo; /* header_version 3 and later */
off_t offset_note; /* header_version 4 and later */
unsigned long size_note; /* header_version 4 and later */
off_t offset_eraseinfo; /* header_version 5 and later */
unsigned long size_eraseinfo; /* header_version 5 and later */
+ unsigned long long start_pfn_64; /* header_version 6 and later */
+ unsigned long long end_pfn_64; /* header_version 6 and later */
+ unsigned long long max_mapnr_64; /* header_version 6 and later */
};
- 1st-bitmap
diff --git a/diskdump_mod.h b/diskdump_mod.h
index af060b6..7306867 100644
--- a/diskdump_mod.h
+++ b/diskdump_mod.h
@@ -48,7 +48,9 @@ struct disk_dump_header {
header in blocks */
unsigned int bitmap_blocks; /* Size of Memory bitmap in
block */
- unsigned int max_mapnr; /* = max_mapnr */
+ unsigned int max_mapnr; /* = max_mapnr, OBSOLETE!
+ 32bit only, full 64bit
+ in sub header. */
unsigned int total_ram_blocks;/* Number of blocks should be
written */
unsigned int device_blocks; /* Number of total blocks in
@@ -67,14 +69,21 @@ struct kdump_sub_header {
unsigned long phys_base;
int dump_level; /* header_version 1 and later */
int split; /* header_version 2 and later */
- unsigned long start_pfn; /* header_version 2 and later */
- unsigned long end_pfn; /* header_version 2 and later */
+ unsigned long start_pfn; /* header_version 2 and later,
+ OBSOLETE! 32bit only, full
+ 64bit in start_pfn_64. */
+ unsigned long end_pfn; /* header_version 2 and later,
+ OBSOLETE! 32bit only, full
+ 64bit in end_pfn_64. */
off_t offset_vmcoreinfo;/* header_version 3 and later */
unsigned long size_vmcoreinfo; /* header_version 3 and later */
off_t offset_note; /* header_version 4 and later */
unsigned long size_note; /* header_version 4 and later */
off_t offset_eraseinfo; /* header_version 5 and later */
unsigned long size_eraseinfo; /* header_version 5 and later */
+ unsigned long long start_pfn_64; /* header_version 6 and later */
+ unsigned long long end_pfn_64; /* header_version 6 and later */
+ unsigned long long max_mapnr_64; /* header_version 6 and later */
};
/* page flags */
diff --git a/makedumpfile.c b/makedumpfile.c
index b42565c..130cf9f 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -23,6 +23,7 @@
#include <stddef.h>
#include <ctype.h>
#include <sys/time.h>
+#include <limits.h>
struct symbol_table symbol_table;
struct size_table size_table;
@@ -125,7 +126,7 @@ get_max_mapnr(void)
unsigned long long max_paddr;
if (info->flag_refiltering) {
- info->max_mapnr = info->dh_memory->max_mapnr;
+ info->max_mapnr = info->kh_memory->max_mapnr_64;
return TRUE;
}
@@ -783,6 +784,10 @@ get_kdump_compressed_header_info(char *filename)
ERRMSG("header does not have dump_level member\n");
return FALSE;
}
+
+ if (dh.header_version < 6)
+ kh.max_mapnr_64 = dh.max_mapnr;
+
DEBUG_MSG("diskdump main header\n");
DEBUG_MSG(" signature : %s\n", dh.signature);
DEBUG_MSG(" header_version : %d\n", dh.header_version);
@@ -802,6 +807,12 @@ get_kdump_compressed_header_info(char *filename)
DEBUG_MSG(" split : %d\n", kh.split);
DEBUG_MSG(" start_pfn : 0x%lx\n", kh.start_pfn);
DEBUG_MSG(" end_pfn : 0x%lx\n", kh.end_pfn);
+ if (dh.header_version >= 6) {
+ /* A dumpfile contains full 64bit values. */
+ DEBUG_MSG(" start_pfn_64 : 0x%llx\n", kh.start_pfn_64);
+ DEBUG_MSG(" end_pfn_64 : 0x%llx\n", kh.end_pfn_64);
+ DEBUG_MSG(" max_mapnr_64 : 0x%llx\n", kh.max_mapnr_64);
+ }
info->dh_memory = malloc(sizeof(dh));
if (info->dh_memory == NULL) {
@@ -2766,14 +2777,16 @@ int
initialize_bitmap_memory(void)
{
struct disk_dump_header *dh;
+ struct kdump_sub_header *kh;
struct dump_bitmap *bmp;
off_t bitmap_offset;
- int bitmap_len, max_sect_len;
+ off_t bitmap_len, max_sect_len;
unsigned long pfn;
int i, j;
long block_size;
dh = info->dh_memory;
+ kh = info->kh_memory;
block_size = dh->block_size;
bitmap_offset
@@ -2793,7 +2806,7 @@ initialize_bitmap_memory(void)
bmp->offset = bitmap_offset + bitmap_len / 2;
info->bitmap_memory = bmp;
- max_sect_len = divideup(dh->max_mapnr, BITMAP_SECT_LEN);
+ max_sect_len = divideup(kh->max_mapnr_64, BITMAP_SECT_LEN);
info->valid_pages = calloc(sizeof(ulong), max_sect_len);
if (info->valid_pages == NULL) {
ERRMSG("Can't allocate memory for the valid_pages. %s\n",
@@ -4705,7 +4718,7 @@ create_2nd_bitmap(void)
int
prepare_bitmap_buffer(void)
{
- unsigned long tmp;
+ unsigned long long tmp;
/*
* Create 2 bitmaps (1st-bitmap & 2nd-bitmap) on block_size boundary.
@@ -4737,7 +4750,7 @@ prepare_bitmap_buffer(void)
int
prepare_bitmap_buffer_cyclic(void)
{
- unsigned long tmp;
+ unsigned long long tmp;
/*
* Create 2 bitmaps (1st-bitmap & 2nd-bitmap) on block_size boundary.
@@ -5153,11 +5166,12 @@ write_kdump_header(void)
* Write common header
*/
strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
- dh->header_version = 5;
+ dh->header_version = 6;
dh->block_size = info->page_size;
dh->sub_hdr_size = sizeof(kh) + size_note;
dh->sub_hdr_size = divideup(dh->sub_hdr_size, dh->block_size);
- dh->max_mapnr = info->max_mapnr;
+ /* dh->max_mapnr may be truncated, full 64bit in kh.max_mapnr_64 */
+ dh->max_mapnr = MIN(info->max_mapnr, UINT_MAX);
dh->nr_cpus = get_nr_cpus();
dh->bitmap_blocks = divideup(info->len_bitmap, dh->block_size);
memcpy(&dh->timestamp, &info->timestamp, sizeof(dh->timestamp));
@@ -5172,12 +5186,21 @@ write_kdump_header(void)
*/
size = sizeof(struct kdump_sub_header);
memset(&kh, 0, size);
+ /* 64bit max_mapnr_64 */
+ kh.max_mapnr_64 = info->max_mapnr;
kh.phys_base = info->phys_base;
kh.dump_level = info->dump_level;
if (info->flag_split) {
kh.split = 1;
- kh.start_pfn = info->split_start_pfn;
- kh.end_pfn = info->split_end_pfn;
+ /* start_pfn and end_pfn may be truncated,
+ * only for compatibility purpose
+ */
+ kh.start_pfn = MIN(info->split_start_pfn, UINT_MAX);
+ kh.end_pfn = MIN(info->split_end_pfn, UINT_MAX);
+
+ /* 64bit start_pfn_64 and end_pfn_64 */
+ kh.start_pfn_64 = info->split_start_pfn;
+ kh.end_pfn_64 = info->split_end_pfn;
}
if (has_pt_note()) {
/*
@@ -6421,7 +6444,7 @@ int
write_kdump_bitmap(void)
{
struct cache_data bm;
- long buf_size;
+ long long buf_size;
off_t offset;
int ret = FALSE;
@@ -7796,10 +7819,8 @@ store_splitting_info(void)
if (i == 0) {
memcpy(&dh, &tmp_dh, sizeof(tmp_dh));
- info->max_mapnr = dh.max_mapnr;
if (!set_page_size(dh.block_size))
return FALSE;
- DEBUG_MSG("max_mapnr : %llx\n", info->max_mapnr);
DEBUG_MSG("page_size : %ld\n", info->page_size);
}
@@ -7816,11 +7837,26 @@ store_splitting_info(void)
return FALSE;
if (i == 0) {
+ if (dh.header_version >= 6)
+ info->max_mapnr = kh.max_mapnr_64;
+ else
+ info->max_mapnr = dh.max_mapnr;
+
+ DEBUG_MSG("max_mapnr : %llx\n", info->max_mapnr);
+ }
+
+ if (i == 0) {
info->dump_level = kh.dump_level;
DEBUG_MSG("dump_level : %d\n", info->dump_level);
}
- SPLITTING_START_PFN(i) = kh.start_pfn;
- SPLITTING_END_PFN(i) = kh.end_pfn;
+
+ if (dh.header_version >= 6) {
+ SPLITTING_START_PFN(i) = kh.start_pfn_64;
+ SPLITTING_END_PFN(i) = kh.end_pfn_64;
+ } else {
+ SPLITTING_START_PFN(i) = kh.start_pfn;
+ SPLITTING_END_PFN(i) = kh.end_pfn;
+ }
SPLITTING_OFFSET_EI(i) = kh.offset_eraseinfo;
SPLITTING_SIZE_EI(i) = kh.size_eraseinfo;
}
@@ -7981,6 +8017,8 @@ reassemble_kdump_header(void)
kh.split = 0;
kh.start_pfn = 0;
kh.end_pfn = 0;
+ kh.start_pfn_64 = 0;
+ kh.end_pfn_64 = 0;
if (lseek(info->fd_dumpfile, info->page_size, SEEK_SET) < 0) {
ERRMSG("Can't seek a file(%s). %s\n",
11 years, 2 months
[PATCH v2] makedumpfile: fix max_mapnr issue on system has over 44-bit addressing
by Jingbai Ma
This patch will fix a bug of makedumpfile doesn't work correctly on system
has over 44-bit addressing in compression dump mode.
This bug was posted here:
http://lists.infradead.org/pipermail/kexec/2013-September/009587.html
This patch will add 3 new fields in struct kdump_sub_header.
unsigned long long start_pfn_64; /* header_version 6 and later */
unsigned long long end_pfn_64; /* header_version 6 and later */
unsigned long long max_mapnr_64; /* header_version 6 and later */
And the old "unsigned int max_mapnr" in struct disk_dump_header will
not be used anymore, but still be there for compatibility purpose.
The max_mapnr_64 only exists in strcut kdump_sub_header, and that only
for compressed kdump format, so for ELF format kdump files (non-compressed),
only the max_mapnr is available, so it still may be truncated for addresses
exceed 44bit (above 16TB).
This patch will change the header_version to 6.
The corresponding patch for crash utility will be sent out separately.
This patch doesn't change sadump_header.
Changelog:
v2:
- Rename max_mapnr in struct kdump_sub_header to max_mapnr_64.
- Change type of max_mapnr_64 from unsigned long to unsigned long long.
In x86 PAE mode on x86_32 kernel, the address may exceeds 44bit limit.
- Add start_pfn_64, end_pfn_64 for struct kdump_sub_header.
- Only print 64bit start_pfn_64, end_pfn_64 and max_mapnr_64
debug messages for disk dump header version >= 6.
- Change type of bitmap_len in struct DumpInfo, from unsigned long to
unsigned long long.
- Enhance bitmap writting function in reassemble_kdump_header().
Prevent bitmap writting failure if the size of bitmap is too large to
fit a sigle write.
v1:
- http://lists.infradead.org/pipermail/kexec/2013-September/009662.html
Signed-off-by: Jingbai Ma <jingbai.ma(a)hp.com>
Tested-by: Lisa Mitchell <lisa.mitchell(a)hp.com>
---
IMPLEMENTATION | 17 +++++++-
diskdump_mod.h | 17 +++++++-
makedumpfile.c | 116 +++++++++++++++++++++++++++++++++++++++++---------------
makedumpfile.h | 2 -
4 files changed, 113 insertions(+), 39 deletions(-)
diff --git a/IMPLEMENTATION b/IMPLEMENTATION
index f0f3135..4feda02 100644
--- a/IMPLEMENTATION
+++ b/IMPLEMENTATION
@@ -48,7 +48,9 @@
header in blocks */
unsigned int bitmap_blocks; /* Size of Memory bitmap in
block */
- unsigned int max_mapnr; /* = max_mapnr */
+ unsigned int max_mapnr; /* = max_mapnr, 32bit only,
+ full 64bit in sub header.
+ Do not use this anymore! */
unsigned int total_ram_blocks;/* Number of blocks should be
written */
unsigned int device_blocks; /* Number of total blocks in
@@ -69,14 +71,23 @@
unsigned long phys_base;
int dump_level; /* header_version 1 and later */
int split; /* header_version 2 and later */
- unsigned long start_pfn; /* header_version 2 and later */
- unsigned long end_pfn; /* header_version 2 and later */
+ unsigned long start_pfn; /* header_version 2 and later,
+ 32bit only, full 64bit in
+ start_pfn_64.
+ Do not use this anymore! */
+ unsigned long end_pfn; /* header_version 2 and later,
+ 32bit only, full 64bit in
+ end_pfn_64.
+ Do not use this anymore! */
off_t offset_vmcoreinfo;/* header_version 3 and later */
unsigned long size_vmcoreinfo; /* header_version 3 and later */
off_t offset_note; /* header_version 4 and later */
unsigned long size_note; /* header_version 4 and later */
off_t offset_eraseinfo; /* header_version 5 and later */
unsigned long size_eraseinfo; /* header_version 5 and later */
+ unsigned long long start_pfn_64; /* header_version 6 and later */
+ unsigned long long end_pfn_64; /* header_version 6 and later */
+ unsigned long long max_mapnr_64; /* header_version 6 and later */
};
- 1st-bitmap
diff --git a/diskdump_mod.h b/diskdump_mod.h
index af060b6..d907775 100644
--- a/diskdump_mod.h
+++ b/diskdump_mod.h
@@ -48,7 +48,9 @@ struct disk_dump_header {
header in blocks */
unsigned int bitmap_blocks; /* Size of Memory bitmap in
block */
- unsigned int max_mapnr; /* = max_mapnr */
+ unsigned int max_mapnr; /* = max_mapnr, 32bit only,
+ full 64bit in sub header.
+ Do not use this anymore! */
unsigned int total_ram_blocks;/* Number of blocks should be
written */
unsigned int device_blocks; /* Number of total blocks in
@@ -67,14 +69,23 @@ struct kdump_sub_header {
unsigned long phys_base;
int dump_level; /* header_version 1 and later */
int split; /* header_version 2 and later */
- unsigned long start_pfn; /* header_version 2 and later */
- unsigned long end_pfn; /* header_version 2 and later */
+ unsigned long start_pfn; /* header_version 2 and later,
+ 32bit only, full 64bit in
+ start_pfn_64.
+ Do not use this anymore! */
+ unsigned long end_pfn; /* header_version 2 and later,
+ 32bit only, full 64bit in
+ end_pfn_64.
+ Do not use this anymore! */
off_t offset_vmcoreinfo;/* header_version 3 and later */
unsigned long size_vmcoreinfo; /* header_version 3 and later */
off_t offset_note; /* header_version 4 and later */
unsigned long size_note; /* header_version 4 and later */
off_t offset_eraseinfo; /* header_version 5 and later */
unsigned long size_eraseinfo; /* header_version 5 and later */
+ unsigned long long start_pfn_64; /* header_version 6 and later */
+ unsigned long long end_pfn_64; /* header_version 6 and later */
+ unsigned long long max_mapnr_64; /* header_version 6 and later */
};
/* page flags */
diff --git a/makedumpfile.c b/makedumpfile.c
index b42565c..3ac3ad0 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -23,6 +23,7 @@
#include <stddef.h>
#include <ctype.h>
#include <sys/time.h>
+#include <limits.h>
struct symbol_table symbol_table;
struct size_table size_table;
@@ -125,7 +126,7 @@ get_max_mapnr(void)
unsigned long long max_paddr;
if (info->flag_refiltering) {
- info->max_mapnr = info->dh_memory->max_mapnr;
+ info->max_mapnr = info->kh_memory->max_mapnr_64;
return TRUE;
}
@@ -783,6 +784,10 @@ get_kdump_compressed_header_info(char *filename)
ERRMSG("header does not have dump_level member\n");
return FALSE;
}
+
+ if (dh.header_version < 6)
+ kh.max_mapnr_64 = dh.max_mapnr;
+
DEBUG_MSG("diskdump main header\n");
DEBUG_MSG(" signature : %s\n", dh.signature);
DEBUG_MSG(" header_version : %d\n", dh.header_version);
@@ -790,7 +795,7 @@ get_kdump_compressed_header_info(char *filename)
DEBUG_MSG(" block_size : %d\n", dh.block_size);
DEBUG_MSG(" sub_hdr_size : %d\n", dh.sub_hdr_size);
DEBUG_MSG(" bitmap_blocks : %d\n", dh.bitmap_blocks);
- DEBUG_MSG(" max_mapnr : 0x%x\n", dh.max_mapnr);
+ DEBUG_MSG(" max_mapnr(32bit) : 0x%x\n", dh.max_mapnr);
DEBUG_MSG(" total_ram_blocks : %d\n", dh.total_ram_blocks);
DEBUG_MSG(" device_blocks : %d\n", dh.device_blocks);
DEBUG_MSG(" written_blocks : %d\n", dh.written_blocks);
@@ -800,8 +805,14 @@ get_kdump_compressed_header_info(char *filename)
DEBUG_MSG(" phys_base : 0x%lx\n", kh.phys_base);
DEBUG_MSG(" dump_level : %d\n", kh.dump_level);
DEBUG_MSG(" split : %d\n", kh.split);
- DEBUG_MSG(" start_pfn : 0x%lx\n", kh.start_pfn);
- DEBUG_MSG(" end_pfn : 0x%lx\n", kh.end_pfn);
+ DEBUG_MSG(" start_pfn(32bit) : 0x%lx\n", kh.start_pfn);
+ DEBUG_MSG(" end_pfn(32bit) : 0x%lx\n", kh.end_pfn);
+ if (dh.header_version >= 6) {
+ /* A dumpfile contains full 64bit values. */
+ DEBUG_MSG(" start_pfn_64 : 0x%llx\n", kh.start_pfn_64);
+ DEBUG_MSG(" end_pfn_64 : 0x%llx\n", kh.end_pfn_64);
+ DEBUG_MSG(" max_mapnr_64 : 0x%llx\n", kh.max_mapnr_64);
+ }
info->dh_memory = malloc(sizeof(dh));
if (info->dh_memory == NULL) {
@@ -2766,14 +2777,16 @@ int
initialize_bitmap_memory(void)
{
struct disk_dump_header *dh;
+ struct kdump_sub_header *kh;
struct dump_bitmap *bmp;
off_t bitmap_offset;
- int bitmap_len, max_sect_len;
+ off_t bitmap_len, max_sect_len;
unsigned long pfn;
int i, j;
long block_size;
dh = info->dh_memory;
+ kh = info->kh_memory;
block_size = dh->block_size;
bitmap_offset
@@ -2793,7 +2806,7 @@ initialize_bitmap_memory(void)
bmp->offset = bitmap_offset + bitmap_len / 2;
info->bitmap_memory = bmp;
- max_sect_len = divideup(dh->max_mapnr, BITMAP_SECT_LEN);
+ max_sect_len = divideup(kh->max_mapnr_64, BITMAP_SECT_LEN);
info->valid_pages = calloc(sizeof(ulong), max_sect_len);
if (info->valid_pages == NULL) {
ERRMSG("Can't allocate memory for the valid_pages. %s\n",
@@ -4705,7 +4718,7 @@ create_2nd_bitmap(void)
int
prepare_bitmap_buffer(void)
{
- unsigned long tmp;
+ unsigned long long tmp;
/*
* Create 2 bitmaps (1st-bitmap & 2nd-bitmap) on block_size boundary.
@@ -4737,7 +4750,7 @@ prepare_bitmap_buffer(void)
int
prepare_bitmap_buffer_cyclic(void)
{
- unsigned long tmp;
+ unsigned long long tmp;
/*
* Create 2 bitmaps (1st-bitmap & 2nd-bitmap) on block_size boundary.
@@ -5153,11 +5166,12 @@ write_kdump_header(void)
* Write common header
*/
strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
- dh->header_version = 5;
+ dh->header_version = 6;
dh->block_size = info->page_size;
dh->sub_hdr_size = sizeof(kh) + size_note;
dh->sub_hdr_size = divideup(dh->sub_hdr_size, dh->block_size);
- dh->max_mapnr = info->max_mapnr;
+ /* dh->max_mapnr may be truncated, full 64bit in kh.max_mapnr_64 */
+ dh->max_mapnr = MIN(info->max_mapnr, UINT_MAX);
dh->nr_cpus = get_nr_cpus();
dh->bitmap_blocks = divideup(info->len_bitmap, dh->block_size);
memcpy(&dh->timestamp, &info->timestamp, sizeof(dh->timestamp));
@@ -5172,12 +5186,21 @@ write_kdump_header(void)
*/
size = sizeof(struct kdump_sub_header);
memset(&kh, 0, size);
+ /* 64bit max_mapnr_64 */
+ kh.max_mapnr_64 = info->max_mapnr;
kh.phys_base = info->phys_base;
kh.dump_level = info->dump_level;
if (info->flag_split) {
kh.split = 1;
+ /* start_pfn and end_pfn may be truncated,
+ * only for compatibility purpose
+ */
kh.start_pfn = info->split_start_pfn;
kh.end_pfn = info->split_end_pfn;
+
+ /* 64bit start_pfn_64 and end_pfn_64 */
+ kh.start_pfn_64 = info->split_start_pfn;
+ kh.end_pfn_64 = info->split_end_pfn;
}
if (has_pt_note()) {
/*
@@ -6421,7 +6444,7 @@ int
write_kdump_bitmap(void)
{
struct cache_data bm;
- long buf_size;
+ long long buf_size;
off_t offset;
int ret = FALSE;
@@ -7796,10 +7819,8 @@ store_splitting_info(void)
if (i == 0) {
memcpy(&dh, &tmp_dh, sizeof(tmp_dh));
- info->max_mapnr = dh.max_mapnr;
if (!set_page_size(dh.block_size))
return FALSE;
- DEBUG_MSG("max_mapnr : %llx\n", info->max_mapnr);
DEBUG_MSG("page_size : %ld\n", info->page_size);
}
@@ -7816,11 +7837,26 @@ store_splitting_info(void)
return FALSE;
if (i == 0) {
+ if (dh.header_version >= 6)
+ info->max_mapnr = kh.max_mapnr_64;
+ else
+ info->max_mapnr = dh.max_mapnr;
+
+ DEBUG_MSG("max_mapnr : %llx\n", info->max_mapnr);
+ }
+
+ if (i == 0) {
info->dump_level = kh.dump_level;
DEBUG_MSG("dump_level : %d\n", info->dump_level);
}
- SPLITTING_START_PFN(i) = kh.start_pfn;
- SPLITTING_END_PFN(i) = kh.end_pfn;
+
+ if (dh.header_version >= 6) {
+ SPLITTING_START_PFN(i) = kh.start_pfn_64;
+ SPLITTING_END_PFN(i) = kh.end_pfn_64;
+ } else {
+ SPLITTING_START_PFN(i) = kh.start_pfn;
+ SPLITTING_END_PFN(i) = kh.end_pfn;
+ }
SPLITTING_OFFSET_EI(i) = kh.offset_eraseinfo;
SPLITTING_SIZE_EI(i) = kh.size_eraseinfo;
}
@@ -7954,6 +7990,7 @@ reassemble_kdump_header(void)
struct disk_dump_header dh;
struct kdump_sub_header kh;
char *buf_bitmap = NULL;
+ ssize_t status, read_size, written_size;
/*
* Write common header.
@@ -7981,6 +8018,8 @@ reassemble_kdump_header(void)
kh.split = 0;
kh.start_pfn = 0;
kh.end_pfn = 0;
+ kh.start_pfn_64 = 0;
+ kh.end_pfn_64 = 0;
if (lseek(info->fd_dumpfile, info->page_size, SEEK_SET) < 0) {
ERRMSG("Can't seek a file(%s). %s\n",
@@ -8030,36 +8069,49 @@ reassemble_kdump_header(void)
SPLITTING_DUMPFILE(0), strerror(errno));
goto out;
}
- if (read(fd, buf_bitmap, info->len_bitmap) != info->len_bitmap) {
- ERRMSG("Can't read a file(%s). %s\n",
- SPLITTING_DUMPFILE(0), strerror(errno));
- goto out;
+ read_size = 0;
+ while (read_size < info->len_bitmap) {
+ status = read(fd, buf_bitmap + read_size, info->len_bitmap
+ - read_size);
+ if (status < 0) {
+ ERRMSG("Can't read a file(%s). %s\n",
+ SPLITTING_DUMPFILE(0), strerror(errno));
+ goto out;
+ }
+ read_size += status;
}
-
if (lseek(info->fd_dumpfile, offset, SEEK_SET) < 0) {
ERRMSG("Can't seek a file(%s). %s\n",
info->name_dumpfile, strerror(errno));
goto out;
}
- if (write(info->fd_dumpfile, buf_bitmap, info->len_bitmap)
- != info->len_bitmap) {
- ERRMSG("Can't write a file(%s). %s\n",
- info->name_dumpfile, strerror(errno));
- goto out;
+ written_size = 0;
+ while (written_size < info->len_bitmap) {
+ status = write(info->fd_dumpfile, buf_bitmap + written_size,
+ info->len_bitmap - written_size);
+ if (status < 0) {
+ ERRMSG("Can't write a file(%s). %s\n",
+ info->name_dumpfile, strerror(errno));
+ goto out;
+ }
+ written_size += status;
}
-
if (lseek(info->fd_bitmap, 0x0, SEEK_SET) < 0) {
ERRMSG("Can't seek a file(%s). %s\n",
info->name_bitmap, strerror(errno));
goto out;
}
- if (write(info->fd_bitmap, buf_bitmap, info->len_bitmap)
- != info->len_bitmap) {
- ERRMSG("Can't write a file(%s). %s\n",
- info->name_bitmap, strerror(errno));
- goto out;
+ written_size = 0;
+ while (written_size < info->len_bitmap) {
+ status = write(info->fd_bitmap, buf_bitmap + written_size,
+ info->len_bitmap - written_size);
+ if (status < 0) {
+ ERRMSG("Can't write a file(%s). %s\n",
+ info->name_bitmap, strerror(errno));
+ goto out;
+ }
+ written_size += status;
}
-
ret = TRUE;
out:
if (fd > 0)
diff --git a/makedumpfile.h b/makedumpfile.h
index a5826e0..4056fa0 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -927,7 +927,7 @@ struct DumpInfo {
*/
int block_order;
off_t offset_bitmap1;
- unsigned long len_bitmap; /* size of bitmap(1st and 2nd) */
+ unsigned long long len_bitmap; /* size of bitmap(1st and 2nd) */
struct dump_bitmap *bitmap1;
struct dump_bitmap *bitmap2;
struct disk_dump_header *dump_header;
11 years, 2 months
[PATCH v2] crash utility: fix max_mapnr issue on system has over 44-bit addressing
by Jingbai Ma
The patch will add support for new compressed dumpfile header_version 6.
This bug was posted here:
http://lists.infradead.org/pipermail/kexec/2013-September/009587.html
This patch will add a new field in struct kdump_sub_header.
unsigned long max_mapnr;
And the old "unsigned int max_mapnr" in struct disk_dump_header will
not be used anymore. But still be there for compatibility purpose.
Changelog:
v2:
- Rename max_mapnr in struct kdump_sub_header to max_mapnr_64.
- Change type of max_mapnr_64 from unsigned long to unsigned long long.
In x86 PAE mode on x86_32 kernel, the address may exceeds 44bit limit.
- Add start_pfn_64, end_pfn_64 for struct kdump_sub_header.
- Add a 64bit max_mapnr in struct diskdump_data. The max_mapnr_64 in
the sub-header only exists in compressed kdump file format, so can't
be used in diskdump file format.
- Merge a patch from Dave Anderson that fixed bitmap_len issue.
v1:
- http://lists.infradead.org/pipermail/kexec/2013-September/009663.html
Signed-off-by: Jingbai Ma <jingbai.ma(a)hp.com>
Tested-by: Lisa Mitchell <lisa.mitchell(a)hp.com>
---
diskdump.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++------------
diskdump.h | 17 +++++++--
2 files changed, 106 insertions(+), 27 deletions(-)
diff --git a/diskdump.c b/diskdump.c
index 0819a3f..cc01d5d 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -40,11 +40,13 @@ struct diskdump_data {
struct disk_dump_sub_header *sub_header;
struct kdump_sub_header *sub_header_kdump;
+ unsigned long long max_mapnr; /* 64bit max_mapnr */
+
size_t data_offset;
int block_size;
int block_shift;
char *bitmap;
- int bitmap_len;
+ off_t bitmap_len;
char *dumpable_bitmap;
int byte, bit;
char *compressed_page; /* copy of compressed page data */
@@ -170,9 +172,9 @@ add_diskdump_data(char* name)
dd->filename = name;
if (CRASHDEBUG(1))
- fprintf(fp, "%s: start_pfn=%lu, end_pfn=%lu\n", name,
- dd->sub_header_kdump->start_pfn,
- dd->sub_header_kdump->end_pfn);
+ fprintf(fp, "%s: start_pfn=%llu, end_pfn=%llu\n", name,
+ dd->sub_header_kdump->start_pfn_64,
+ dd->sub_header_kdump->end_pfn_64);
}
static void
@@ -199,13 +201,13 @@ get_bit(char *map, int byte, int bit)
}
static inline int
-page_is_ram(unsigned int nr)
+page_is_ram(unsigned long nr)
{
return get_bit(dd->bitmap, nr >> 3, nr & 7);
}
static inline int
-page_is_dumpable(unsigned int nr)
+page_is_dumpable(unsigned long nr)
{
return dd->dumpable_bitmap[nr>>3] & (1 << (nr & 7));
}
@@ -214,7 +216,7 @@ static inline int
dump_is_partial(const struct disk_dump_header *header)
{
return header->bitmap_blocks >=
- divideup(divideup(header->max_mapnr, 8), dd->block_size) * 2;
+ divideup(divideup(dd->max_mapnr, 8), dd->block_size) * 2;
}
static int
@@ -321,6 +323,9 @@ x86_process_elf_notes(void *note_ptr, unsigned long size_note)
* [40] unsigned long size_note; / header_version 4 and later /
* [44] off_t offset_eraseinfo; / header_version 5 and later /
* [52] unsigned long size_eraseinfo; / header_version 5 and later /
+ * [56] unsigned long long start_pfn_64; / header_version 6 and later /
+ * [64] unsigned long long end_pfn_64; / header_version 6 and later /
+ * [72] unsigned long long max_mapnr_64; / header_version 6 and later /
* };
*
* But when compiled on an ARM processor, each 64-bit "off_t" would be pushed
@@ -337,7 +342,10 @@ x86_process_elf_notes(void *note_ptr, unsigned long size_note)
* [40] off_t offset_note; / header_version 4 and later /
* [48] unsigned long size_note; / header_version 4 and later /
* [56] off_t offset_eraseinfo; / header_version 5 and later /
- * [62] unsigned long size_eraseinfo; / header_version 5 and later /
+ * [64] unsigned long size_eraseinfo; / header_version 5 and later /
+ * [72] unsigned long long start_pfn_64; / header_version 6 and later /
+ * [80] unsigned long long end_pfn_64; / header_version 6 and later /
+ * [88] unsigned long long max_mapnr_64; / header_version 6 and later /
* };
*
*/
@@ -357,6 +365,10 @@ struct kdump_sub_header_ARM_target {
int pad3;
off_t offset_eraseinfo; /* header_version 5 and later */
unsigned long size_eraseinfo; /* header_version 5 and later */
+ int pad4;
+ unsigned long long start_pfn_64; /* header_version 6 and later */
+ unsigned long long end_pfn_64; /* header_version 6 and later */
+ unsigned long long max_mapnr_64; /* header_version 6 and later */
};
static void
@@ -380,6 +392,15 @@ arm_kdump_header_adjust(int header_version)
kdsh->offset_eraseinfo = kdsh_ARM_target->offset_eraseinfo;
kdsh->size_eraseinfo = kdsh_ARM_target->size_eraseinfo;
}
+ if (header_version >= 6) {
+ kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn_64;
+ kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn_64;
+ kdsh->max_mapnr_64 = kdsh_ARM_target->map_mapnr_64;
+ } else {
+ kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn;
+ kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn;
+ kdsh->max_mapnr_64 = dd->map_mapnr;
+ }
}
#endif /* __i386__ && ARM */
@@ -390,7 +411,10 @@ read_dump_header(char *file)
struct disk_dump_sub_header *sub_header = NULL;
struct kdump_sub_header *sub_header_kdump = NULL;
size_t size;
- int bitmap_len;
+ off_t bitmap_len;
+ char *bufptr;
+ size_t len;
+ size_t bytes_read;
int block_size = (int)sysconf(_SC_PAGESIZE);
off_t offset;
const off_t failed = (off_t)-1;
@@ -540,8 +564,21 @@ restart:
#if defined(__i386__) && defined(ARM)
arm_kdump_header_adjust(header->header_version);
#endif
+ /* use 64bit max_mapnr in compressed kdump file sub-header */
+ if (header->header_version >= 6)
+ dd->max_mapnr = dd->sub_header_kdump->max_mapnr_64;
+ } else {
+ /* the 64bit max_mapnr only exists in sub-header of compressed
+ * kdump file, if it's not a compressed kdump file, we have to
+ * use the old 32bit max_mapnr in dumpfile header.
+ * max_mapnr may be truncated here.
+ */
+ dd->max_mapnr = header->max_mapnr;
}
+ if (header->header_version < 6)
+ dd->max_mapnr = header->max_mapnr;
+
/* read memory bitmap */
bitmap_len = block_size * header->bitmap_blocks;
dd->bitmap_len = bitmap_len;
@@ -571,11 +608,27 @@ restart:
DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
goto err;
}
+#ifdef OLDWAY
if (read(dd->dfd, dd->bitmap, bitmap_len) < bitmap_len) {
error(INFO, "%s: cannot read memory bitmap\n",
DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
goto err;
}
+#else
+ bufptr = dd->bitmap;
+ len = bitmap_len;
+ while (len) {
+ bytes_read = read(dd->dfd, bufptr, len);
+ if (bytes_read < 0) {
+ error(INFO, "%s: cannot read memory bitmap\n",
+ DISKDUMP_VALID() ? "diskdump"
+ : "compressed kdump");
+ goto err;
+ }
+ len -= bytes_read;
+ bufptr += bytes_read;
+ }
+#endif
}
if (dump_is_partial(header))
@@ -679,13 +732,13 @@ restart:
}
if (!is_split) {
- max_sect_len = divideup(header->max_mapnr, BITMAP_SECT_LEN);
+ max_sect_len = divideup(dd->max_mapnr, BITMAP_SECT_LEN);
pfn = 0;
dd->filename = file;
}
else {
- ulong start = sub_header_kdump->start_pfn;
- ulong end = sub_header_kdump->end_pfn;
+ unsigned long long start = sub_header_kdump->start_pfn_64;
+ unsigned long long end = sub_header_kdump->end_pfn_64;
max_sect_len = divideup(end - start + 1, BITMAP_SECT_LEN);
pfn = start;
}
@@ -727,8 +780,9 @@ pfn_to_pos(ulong pfn)
ulong p1, p2;
if (KDUMP_SPLIT()) {
- p1 = pfn - dd->sub_header_kdump->start_pfn;
- p2 = round(p1, BITMAP_SECT_LEN) + dd->sub_header_kdump->start_pfn;
+ p1 = pfn - dd->sub_header_kdump->start_pfn_64;
+ p2 = round(p1, BITMAP_SECT_LEN)
+ + dd->sub_header_kdump->start_pfn_64;
}
else {
p1 = pfn;
@@ -1034,12 +1088,12 @@ read_diskdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
if (KDUMP_SPLIT()) {
/* Find proper dd */
int i;
- unsigned long start_pfn;
- unsigned long end_pfn;
+ unsigned long long start_pfn;
+ unsigned long long end_pfn;
for (i=0; i<num_dumpfiles; i++) {
- start_pfn = dd_list[i]->sub_header_kdump->start_pfn;
- end_pfn = dd_list[i]->sub_header_kdump->end_pfn;
+ start_pfn = dd_list[i]->sub_header_kdump->start_pfn_64;
+ end_pfn = dd_list[i]->sub_header_kdump->end_pfn_64;
if ((pfn >= start_pfn) && (pfn <= end_pfn)) {
dd = dd_list[i];
break;
@@ -1058,14 +1112,14 @@ read_diskdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
curpaddr = paddr & ~((physaddr_t)(dd->block_size-1));
page_offset = paddr & ((physaddr_t)(dd->block_size-1));
- if ((pfn >= dd->header->max_mapnr) || !page_is_ram(pfn)) {
+ if ((pfn >= dd->max_mapnr) || !page_is_ram(pfn)) {
if (CRASHDEBUG(8)) {
fprintf(fp, "read_diskdump: SEEK_ERROR: "
"paddr/pfn: %llx/%lx ",
(ulonglong)paddr, pfn);
- if (pfn >= dd->header->max_mapnr)
- fprintf(fp, "max_mapnr: %x\n",
- dd->header->max_mapnr);
+ if (pfn >= dd->max_mapnr)
+ fprintf(fp, "max_mapnr: %llx\n",
+ dd->max_mapnr);
else
fprintf(fp, "!page_is_ram\n");
}
@@ -1517,7 +1571,7 @@ __diskdump_memory_dump(FILE *fp)
fprintf(fp, " block_size: %d\n", dh->block_size);
fprintf(fp, " sub_hdr_size: %d\n", dh->sub_hdr_size);
fprintf(fp, " bitmap_blocks: %u\n", dh->bitmap_blocks);
- fprintf(fp, " max_mapnr: %u\n", dh->max_mapnr);
+ fprintf(fp, " max_mapnr: %llu\n", dd->max_mapnr);
fprintf(fp, " total_ram_blocks: %u\n", dh->total_ram_blocks);
fprintf(fp, " device_blocks: %u\n", dh->device_blocks);
fprintf(fp, " written_blocks: %u\n", dh->written_blocks);
@@ -1662,6 +1716,20 @@ __diskdump_memory_dump(FILE *fp)
dump_eraseinfo(fp);
}
}
+ if (dh->header_version >= 6) {
+ fprintf(fp, " start_pfn_64: ");
+ if (KDUMP_SPLIT())
+ fprintf(fp, "%lld (0x%llx)\n",
+ kdsh->start_pfn_64, kdsh->start_pfn_64);
+ else
+ fprintf(fp, "(unused)\n");
+ fprintf(fp, " end_pfn_64: ");
+ if (KDUMP_SPLIT())
+ fprintf(fp, "%lld (0x%llx)\n",
+ kdsh->end_pfn_64, kdsh->end_pfn_64);
+ else
+ fprintf(fp, "(unused)\n");
+ }
fprintf(fp, "\n");
} else
fprintf(fp, "(n/a)\n\n");
@@ -1670,7 +1738,7 @@ __diskdump_memory_dump(FILE *fp)
fprintf(fp, " block_size: %d\n", dd->block_size);
fprintf(fp, " block_shift: %d\n", dd->block_shift);
fprintf(fp, " bitmap: %lx\n", (ulong)dd->bitmap);
- fprintf(fp, " bitmap_len: %d\n", dd->bitmap_len);
+ fprintf(fp, " bitmap_len: %ld\n", dd->bitmap_len);
fprintf(fp, " dumpable_bitmap: %lx\n", (ulong)dd->dumpable_bitmap);
fprintf(fp, " byte: %d\n", dd->byte);
fprintf(fp, " bit: %d\n", dd->bit);
diff --git a/diskdump.h b/diskdump.h
index 9ab10b6..0492351 100644
--- a/diskdump.h
+++ b/diskdump.h
@@ -42,7 +42,9 @@ struct disk_dump_header {
header in blocks */
unsigned int bitmap_blocks; /* Size of Memory bitmap in
block */
- unsigned int max_mapnr; /* = max_mapnr */
+ unsigned int max_mapnr; /* = max_mapnr, 32bit only,
+ full 64bit in sub header.
+ Do NOT use this anymore! */
unsigned int total_ram_blocks;/* Number of blocks should be
written */
unsigned int device_blocks; /* Number of total blocks in
@@ -61,14 +63,23 @@ struct kdump_sub_header {
unsigned long phys_base;
int dump_level; /* header_version 1 and later */
int split; /* header_version 2 and later */
- unsigned long start_pfn; /* header_version 2 and later */
- unsigned long end_pfn; /* header_version 2 and later */
+ unsigned long start_pfn; /* header_version 2 and later,
+ 32bit only, full 64bit in
+ start_pfn_64.
+ Do not use this anymore! */
+ unsigned long end_pfn; /* header_version 2 and later,
+ 32bit only, full 64bit in
+ end_pfn_64.
+ Do not use this anymore! */
off_t offset_vmcoreinfo; /* header_version 3 and later */
unsigned long size_vmcoreinfo; /* header_version 3 and later */
off_t offset_note; /* header_version 4 and later */
unsigned long size_note; /* header_version 4 and later */
off_t offset_eraseinfo; /* header_version 5 and later */
unsigned long size_eraseinfo; /* header_version 5 and later */
+ unsigned long long start_pfn_64; /* header_version 6 and later */
+ unsigned long long end_pfn_64; /* header_version 6 and later */
+ unsigned long long max_mapnr_64; /* header_version 6 and later */
};
/* page flags */
11 years, 2 months
[PATCH] s390x: Implement swap PTE for kernel 3.12
by Michael Holzheu
Hi Dave,
The following kernel git commit changes swap PTEs again
for Linux 3.12:
commit e509861105a3c1425f3f929bd631f88340b499bf
Author: Martin Schwidefsky <schwidefsky(a)de.ibm.com>
Date: Tue Jul 23 20:57:57 2013 +0200
s390/mm: cleanup page table definitions
So we have to do this also in crash.
Signed-off-by: Michael Holzheu <holzheu(a)linux.vnet.ibm.com>
---
s390x.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/s390x.c
+++ b/s390x.c
@@ -590,9 +590,12 @@ static int swap_entry(ulong entry)
if (THIS_KERNEL_VERSION < LINUX(2,6,19)) {
if ((entry & 0x601ULL) == 0x600ULL)
return 1;
- } else {
+ } if (THIS_KERNEL_VERSION < LINUX(3,12,0)) {
if ((entry & 0x403ULL) == 0x403ULL)
return 1;
+ } else {
+ if ((entry & 0x603ULL) == 0x402ULL)
+ return 1;
}
return 0;
}
11 years, 2 months
Re: [Crash-utility] [PATCH 6/7] x86, kaslr: report kernel offset on panic
by HATAYAMA Daisuke
(2013/10/03 22:47), Dave Anderson wrote:
>
>
> ----- Original Message -----
>> (2013/10/02 18:13), HATAYAMA Daisuke wrote:
>>> (2013/10/02 16:48), Kees Cook wrote:
>> <cut>
>>>>>> +
>>>>>> + return 0;
>>>>>> +}
>>>>>> +
>>>>>> +/*
>>>>>> * Determine if we were loaded by an EFI loader. If so, then we have also been
>>>>>> * passed the efi memmap, systab, etc., so we should use these data structures
>>>>>> * for initialization. Note, the efi init code path is determined by the
>>>>>> @@ -1242,3 +1256,15 @@ void __init i386_reserve_resources(void)
>>>>>> }
>>>>>>
>>>>>> #endif /* CONFIG_X86_32 */
>>>>>> +
>>>>>> +static struct notifier_block kernel_offset_notifier = {
>>>>>> + .notifier_call = dump_kernel_offset
>>>>>> +};
>>>>>> +
>>>>>> +static int __init register_kernel_offset_dumper(void)
>>>>>> +{
>>>>>> + atomic_notifier_chain_register(&panic_notifier_list,
>>>>>> + &kernel_offset_notifier);
>>>>>> + return 0;
>>>>>> +}
>>>>>> +__initcall(register_kernel_offset_dumper);
>>>>>>
>>>>>
>>>>> Panic notifier is not executed if kdump is enabled. Maybe, Chrome OS doesn't use
>>>>> kdump? Anyway, kdump related tools now calculate phys_base from memory map
>>>>> information passed as ELF PT_LOAD entries like below.
>>>>
>>>> Correct, we are not currently using kdump.
>>>>
>>>>> $ LANG=C readelf -l vmcore-rhel6up4
>>>>>
>>>>> Elf file type is CORE (Core file)
>>>>> Entry point 0x0
>>>>> There are 5 program headers, starting at offset 64
>>>>>
>>>>> Program Headers:
>>>>> Type Offset VirtAddr PhysAddr
>>>>> FileSiz MemSiz Flags Align
>>>>> NOTE 0x0000000000000158 0x0000000000000000 0x0000000000000000
>>>>> 0x0000000000000b08 0x0000000000000b08 0
>>>>> LOAD 0x0000000000000c60 0xffffffff81000000 0x0000000001000000
>>>>> 0x000000000103b000 0x000000000103b000 RWE 0
>>>>> LOAD 0x000000000103bc60 0xffff880000001000 0x0000000000001000
>>>>> 0x000000000009cc00 0x000000000009cc00 RWE 0
>>>>> LOAD 0x00000000010d8860 0xffff880000100000 0x0000000000100000
>>>>> 0x0000000002f00000 0x0000000002f00000 RWE 0
>>>>> LOAD 0x0000000003fd8860 0xffff880013000000 0x0000000013000000
>>>>> 0x000000002cffd000 0x000000002cffd000 RWE 0
>>>>>
>>>>> Each PT_LOAD entry is assigned to virtual and physical address. In this case,
>>>>> 1st PT_LOAD entry belongs to kernel text mapping region, from which we can
>>>>> calculate phys_base value.
>>>>
>>>> It seems like all the information you need would still be available?
>>>> The virtual address is there, so it should be trivial to see the
>>>> offset, IIUC.
>>>>
>>>
>>> Partially yes. I think OK to analyze crash dump by crash utility, a gdb-based
>>> symbolic debugger for kernel, since phys_base absorbs kernel offset caused by
>>> relocation and phys_base is available in the way I explained above.
>>>
>>> However, the gained phys_base is not correct one, exactly phys_base + offset_by_relocation.
>>> When analyzing crash dump by crash utility, we use debug information generated
>>> during kernel build, which we install as kernel-debuginfo on RHEL for example.
>>> Symbols in debuginfo have statically assigned addresses at build so we see
>>> the statically assigned addresses during debugging and we see
>>> phys_base + offset_by_relocation as phys_base. This would be problematic
>>> if failure on crash dump is relevant to the relocated addresses, though I don't
>>> immediately come up with crash senario where relocated symbol is defitely necessary.
>>>
>>> Still we can get relocated addresses if kallsyms is enabled on the kernel,
>>> but kallsyms and relocatable kernels are authogonal. I don't think it natural
>>> to rely on kallsyms. It seems natural to export relocation information newly
>>> as debugging information.
>>>
>>
>> I was confused yesterday. As I said above, kdump related tools now don't support
>> relocation on x86_64, phys_base only. kdump related tools think of present kernel
>> offset as phys_base. Then, they reflect kernel offset caused by relocation in
>> physical addresses only, not in virtual addresses. This obviously affects the
>> tools.
>>
>> BTW, relocation looks more sophisticated than phys_base one. Is it possible to
>> switch from phys_base one to relocation on x86_64? On x86, relocation is used so
>> I guess x86_64 can work in the same way. Is there something missing?
>> Is there what phys_base can but relocation cannot on x86_64?
>>
>> And, Dave, is there feature for crash utility to treat relocation now?
>
> Well sort of, there are couple guessing-game kludges that can be used.
>
> For 32-bit x86 systems configured with a CONFIG_PHYSICAL_START value
> that is larger than its CONFIG_PHYSICAL_ALIGN value, such that the
> vmlinux symbol values do not match their relocated virtual address
> values, there are two options for analyzing dumpfiles:
>
> (1) there is a "--reloc size" command line option, presuming that
> you know what it is.
> (2) take a snapshot of the /proc/kallsyms file from the crashing
> system into a file, and put it on the command line, similar
> to putting a System.map file on the command line in order to
> override the symbol values in the vmlinux file.
>
> In those cases, we have to alter all of the symbols seen in the
> vmlinux file, and go into a backdoor into the embedded gdb module
> to patch/modify the symbol values.
>
> On live x86 systems, the two options above are not necessary if
> /proc/kallsyms exists, because its contents can be checked against
> the vmlinux file symbol values, and the relocation calculated.
>
> For x86_64, the --reloc argument has never been needed. But if
> for whatever reason the "phys_base" value cannot be determined,
> it can be forced with the "--machdep phys_base=addr" option,
> again presuming you know what it is.
>
Thanks for detailed explanation. So, there's already a feature in crash utility
to address relocation!, though it's better for me to try them to check if it's
really applicable to this feature. My concern is whether --reloc works well
on x86_64 too, because relocation has never done on x86_64 ever, right?
Another concern is that in case of relocation, users need to additional information
regarding runtime symbol information to crash utility. I want to avoid additional
process, automation is preferable if possible.
I guess it's enough if there's runtime symbol addresses because we can get relocated
offset value by comparing it with the compile-time symbol address contained in
a given debuginfo file. Candidates for such symbols are the ones contained in
VMCOREINFO note containing some symbol values for makedumpfile to refer to mm-related
objects in kernel, which is always contained in vmcore generated by current kdump and
also vmcores converted by makedumpfile from it. How about this idea?
# I added CC to crash utility mailing list
--
Thanks.
HATAYAMA, Daisuke
11 years, 2 months
[ANNOUNCE] crash gcore command, version 1.2.2 is released
by HATAYAMA Daisuke
This is the release of crash gcore command, version 1.2.2.
ChangeLog:
- Now gcore collects and writes ELF note segments in O(1) memory
consumption with regard to the number of threads. The implementation
so far had created ELF note segments for all the threads as a list
at the same time, and so memory consumption had grown in proportion
to the number of threads. In contrast, new implementation writes
ELF note segments one by one. Without this change, gcore could fail
abnormally if specified process consists of threads more than tens of
thousands, with the message: "gcore: cannot allocate any more memory!".
(d.hatayama(a)jp.fujitsu.com)
- Fix the address of vdso virtual address in x86_64 compat mode by using
fixed VDSO_HIGH_BASE, not by vma->vm_mm->context.vdso. Without this
fix, access to vdso page fails in x86_64 compat mode and vdso page
fails to be collected in generated process core dump.
(d.hatayama(a)jp.fujitsu.com)
- Tested on RHEL5.10.
(d.hatayama(a)jp.fujitsu.com)
MD5 CheckSum:
$ md5sum crash-gcore-command-1.2.2.tar.gz
c343a47be9c9df64578777533c04e09a crash-gcore-command-1.2.2.tar.gz
--
Thanks.
HATAYAMA, Daisuke
11 years, 2 months
[PATCH] makedumpfile: fix max_mapnr issue on system has over 44-bit addressing
by Jingbai Ma
This patch will fix a bug of makedumpfile doesn't work correctly on system
has over 44-bit addressing in compression dump mode.
This bug was posted here:
http://lists.infradead.org/pipermail/kexec/2013-September/009587.html
This patch will add a new field in struct kdump_sub_header.
unsigned long max_mapnr;
And the old "unsigned int max_mapnr" in struct disk_dump_header will
not be used anymore. But still be there for compatibility purpose.
This patch will change the header_version to 6.
The corresponding patch for crash utility will be sent out separately.
This patch doesn't change sadump_header.
Because of in sadump file, there is no any sub-header, it has to change
the sadump_header itself.
And if do so, will cause backwards-compatibility issue.
So it could be a separate patch if needed.
Signed-off-by: Jingbai Ma <jingbai.ma(a)hp.com>
---
IMPLEMENTATION | 1 +
diskdump_mod.h | 5 ++++-
makedumpfile.c | 28 ++++++++++++++++++++++------
3 files changed, 27 insertions(+), 7 deletions(-)
diff --git a/IMPLEMENTATION b/IMPLEMENTATION
index f0f3135..d576811 100644
--- a/IMPLEMENTATION
+++ b/IMPLEMENTATION
@@ -77,6 +77,7 @@
unsigned long size_note; /* header_version 4 and later */
off_t offset_eraseinfo; /* header_version 5 and later */
unsigned long size_eraseinfo; /* header_version 5 and later */
+ unsigned long max_mapnr; /* header_version 6 and later */
};
- 1st-bitmap
diff --git a/diskdump_mod.h b/diskdump_mod.h
index af060b6..30306a5 100644
--- a/diskdump_mod.h
+++ b/diskdump_mod.h
@@ -48,7 +48,9 @@ struct disk_dump_header {
header in blocks */
unsigned int bitmap_blocks; /* Size of Memory bitmap in
block */
- unsigned int max_mapnr; /* = max_mapnr */
+ unsigned int max_mapnr; /* = max_mapnr, 32bit only,
+ full 64bit in sub header.
+ Do not use this anymore! */
unsigned int total_ram_blocks;/* Number of blocks should be
written */
unsigned int device_blocks; /* Number of total blocks in
@@ -75,6 +77,7 @@ struct kdump_sub_header {
unsigned long size_note; /* header_version 4 and later */
off_t offset_eraseinfo; /* header_version 5 and later */
unsigned long size_eraseinfo; /* header_version 5 and later */
+ unsigned long max_mapnr; /* header_version 6 and later */
};
/* page flags */
diff --git a/makedumpfile.c b/makedumpfile.c
index b42565c..a444adf 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -125,7 +125,7 @@ get_max_mapnr(void)
unsigned long long max_paddr;
if (info->flag_refiltering) {
- info->max_mapnr = info->dh_memory->max_mapnr;
+ info->max_mapnr = info->kh_memory->max_mapnr;
return TRUE;
}
@@ -783,6 +783,10 @@ get_kdump_compressed_header_info(char *filename)
ERRMSG("header does not have dump_level member\n");
return FALSE;
}
+
+ if (dh.header_version < 6)
+ kh.max_mapnr = dh.max_mapnr;
+
DEBUG_MSG("diskdump main header\n");
DEBUG_MSG(" signature : %s\n", dh.signature);
DEBUG_MSG(" header_version : %d\n", dh.header_version);
@@ -790,7 +794,7 @@ get_kdump_compressed_header_info(char *filename)
DEBUG_MSG(" block_size : %d\n", dh.block_size);
DEBUG_MSG(" sub_hdr_size : %d\n", dh.sub_hdr_size);
DEBUG_MSG(" bitmap_blocks : %d\n", dh.bitmap_blocks);
- DEBUG_MSG(" max_mapnr : 0x%x\n", dh.max_mapnr);
+ DEBUG_MSG(" max_mapnr(32bit) : 0x%x\n", dh.max_mapnr);
DEBUG_MSG(" total_ram_blocks : %d\n", dh.total_ram_blocks);
DEBUG_MSG(" device_blocks : %d\n", dh.device_blocks);
DEBUG_MSG(" written_blocks : %d\n", dh.written_blocks);
@@ -802,6 +806,7 @@ get_kdump_compressed_header_info(char *filename)
DEBUG_MSG(" split : %d\n", kh.split);
DEBUG_MSG(" start_pfn : 0x%lx\n", kh.start_pfn);
DEBUG_MSG(" end_pfn : 0x%lx\n", kh.end_pfn);
+ DEBUG_MSG(" max_mapnr(64bit) : 0x%lx\n", kh.max_mapnr);
info->dh_memory = malloc(sizeof(dh));
if (info->dh_memory == NULL) {
@@ -2766,6 +2771,7 @@ int
initialize_bitmap_memory(void)
{
struct disk_dump_header *dh;
+ struct kdump_sub_header *kh;
struct dump_bitmap *bmp;
off_t bitmap_offset;
int bitmap_len, max_sect_len;
@@ -2774,6 +2780,7 @@ initialize_bitmap_memory(void)
long block_size;
dh = info->dh_memory;
+ kh = info->kh_memory;
block_size = dh->block_size;
bitmap_offset
@@ -2793,7 +2800,7 @@ initialize_bitmap_memory(void)
bmp->offset = bitmap_offset + bitmap_len / 2;
info->bitmap_memory = bmp;
- max_sect_len = divideup(dh->max_mapnr, BITMAP_SECT_LEN);
+ max_sect_len = divideup(kh->max_mapnr, BITMAP_SECT_LEN);
info->valid_pages = calloc(sizeof(ulong), max_sect_len);
if (info->valid_pages == NULL) {
ERRMSG("Can't allocate memory for the valid_pages. %s\n",
@@ -5153,10 +5160,11 @@ write_kdump_header(void)
* Write common header
*/
strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE));
- dh->header_version = 5;
+ dh->header_version = 6;
dh->block_size = info->page_size;
dh->sub_hdr_size = sizeof(kh) + size_note;
dh->sub_hdr_size = divideup(dh->sub_hdr_size, dh->block_size);
+ /* dh->max_mapnr may be truncated here, full 64bit in kh.max_mapnr */
dh->max_mapnr = info->max_mapnr;
dh->nr_cpus = get_nr_cpus();
dh->bitmap_blocks = divideup(info->len_bitmap, dh->block_size);
@@ -5172,6 +5180,7 @@ write_kdump_header(void)
*/
size = sizeof(struct kdump_sub_header);
memset(&kh, 0, size);
+ kh.max_mapnr = info->max_mapnr;
kh.phys_base = info->phys_base;
kh.dump_level = info->dump_level;
if (info->flag_split) {
@@ -7796,10 +7805,8 @@ store_splitting_info(void)
if (i == 0) {
memcpy(&dh, &tmp_dh, sizeof(tmp_dh));
- info->max_mapnr = dh.max_mapnr;
if (!set_page_size(dh.block_size))
return FALSE;
- DEBUG_MSG("max_mapnr : %llx\n", info->max_mapnr);
DEBUG_MSG("page_size : %ld\n", info->page_size);
}
@@ -7816,6 +7823,15 @@ store_splitting_info(void)
return FALSE;
if (i == 0) {
+ if (dh.header_version >= 6)
+ info->max_mapnr = kh.max_mapnr;
+ else
+ info->max_mapnr = dh.max_mapnr;
+
+ DEBUG_MSG("max_mapnr : %llx\n", info->max_mapnr);
+ }
+
+ if (i == 0) {
info->dump_level = kh.dump_level;
DEBUG_MSG("dump_level : %d\n", info->dump_level);
}
11 years, 2 months
Re: [Crash-utility] question about kernel module dwarf unwinder support
by Jiong Wang
Hi Dave,
sorry for delayed reply, I was not on the mailing list, just subscribed
it :-)
please see inlined reply below.
> Hello Jiong,
>
> So should I presume that you are ultimately planning to post a complete
> patchset that introduces the TILE architecture? I'm not at all familiar
> with the processor type, but is there something that would differentiate
> TILE and TILEGX?
yes, we plan to return the whole backend to community after we finished
various tests.
TILEGX means TILE, it's already included in linux kernel tree.
> Anyway, I do try to avoid "#ifdef <ARCH>" if at all possible.
>
> A few questions:
>
> Your patch only makes the call if "mod -s <module>" is used -- but what
> if "mod -S" used?
>
> If your call fails, you force "mod -s <module>" to also fail -- do you
> really want to do that?
thanks for pointing this out. sure, my call fail should not stop the
normal "mod -s" procedure.
>
> 10042
> 10043 add_symbols:
> 10044 result = add_symbol_file(st->current);
> 10045
> 10046 if (CRASHDEBUG(2))
> 10047 check_for_dups(st->current);
> 10048
> 10049 st->current = NULL;
> 10050
> 10051 return result;
> 10052 }
>
> That would also cover the "mod -S" command as well.
looks like a good place to integrate my call as a post load module
target hook. I will re-arrange the code.
thanks.
---
Regards,
Jiong
Tilera Corporation.
>
> Dave Anderson
>
>
11 years, 2 months