when zspage define 'huge', crash-utility zram decompress fail.
we need to be compatible with the previous kernel,
so we can't define 'huge' directly in zspage, just move to the right when calculating.
Before:
crash> mod -s zram zram.ko
MODULE NAME BASE SIZE OBJECT FILE
ffffffde224db800 zram ffffffde224d2000 57344 zram.ko
crash> mod -s zsmalloc zsmalloc.ko
MODULE NAME BASE SIZE OBJECT FILE
ffffffde224c5180 zsmalloc ffffffde224bf000 40960 zsmalloc.ko
crash> rd 0x13d89fb0
rd: zspage magic incorrect: b0
After:
crash> rd 0x13d89fb0
13d89fb0: c2b54f7170883b20 ;.pqO..
Link: https://lkml.kernel.org/r/20211115185909.3949505-6-minchan@xxxxxxxxxx
Signed-off-by: chenguanyou <chenguanyou@xxxxxxxxxx>
---
defs.h | 13 ++++++++++
diskdump.c | 70 ++++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 71 insertions(+), 12 deletions(-)
diff --git a/defs.h b/defs.h
index 96a7a2a..0af69cc 100644
--- a/defs.h
+++ b/defs.h
@@ -2225,6 +2225,7 @@ struct offset_table { /* stash of commonly-used offsets */
long module_memory_base;
long module_memory_size;
long irq_data_irq;
+ long zspage_huge;
};
struct size_table { /* stash of commonly-used sizes */
@@ -7221,6 +7222,18 @@ struct zspage {
unsigned int freeobj;
};
+struct zspage6 {
+ struct {
+ unsigned int huge : 1;
+ unsigned int fullness : 2;
+ unsigned int class : 9;
+ unsigned int isolated : 3;
+ unsigned int magic : 8;
+ };
+ unsigned int inuse;
+ unsigned int freeobj;
+};
+
/*
* makedumpfile.c
*/
diff --git a/diskdump.c b/diskdump.c
index 2c284ff..0307656 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -2754,6 +2754,9 @@ zram_init(void)
if (INVALID_MEMBER(zram_table_flag))
MEMBER_OFFSET_INIT(zram_table_flag, "zram_table_entry", "value");
STRUCT_SIZE_INIT(zram_table_entry, "zram_table_entry");
+ MEMBER_OFFSET_INIT(zspoll_size_class, "zs_pool", "size_class");
+ MEMBER_OFFSET_INIT(size_class_size, "size_class", "size");
+ MEMBER_OFFSET_INIT(zspage_huge, "zspage", "huge");
}
static unsigned char *
@@ -2761,9 +2764,11 @@ zram_object_addr(ulong pool, ulong handle, unsigned char *zram_buf)
{
ulong obj, off, class, page, zspage;
struct zspage zspage_s;
+ struct zspage6 zspage6_s;
physaddr_t paddr;
unsigned int obj_idx, class_idx, size;
ulong pages[2], sizes[2];
+ ulong zs_magic;
readmem(handle, KVADDR, &obj, sizeof(void *), "zram entry", FAULT_ON_ERROR);
obj >>= OBJ_TAG_BITS;
@@ -2772,11 +2777,19 @@ zram_object_addr(ulong pool, ulong handle, unsigned char *zram_buf)
readmem(page + OFFSET(page_private), KVADDR, &zspage,
sizeof(void *), "page_private", FAULT_ON_ERROR);
- readmem(zspage, KVADDR, &zspage_s, sizeof(struct zspage), "zspage", FAULT_ON_ERROR);
- class_idx = zspage_s.class;
- if (zspage_s.magic != ZSPAGE_MAGIC)
- error(FATAL, "zspage magic incorrect: %x\n", zspage_s.magic);
+ if (VALID_MEMBER(zspage_huge)) {
+ readmem(zspage, KVADDR, &zspage6_s, sizeof(struct zspage6), "zspage6", FAULT_ON_ERROR);
+ class_idx = zspage6_s.class;
+ zs_magic = zspage6_s.magic;
+ } else {
+ readmem(zspage, KVADDR, &zspage_s, sizeof(struct zspage), "zspage", FAULT_ON_ERROR);
+ class_idx = zspage_s.class;
+ zs_magic = zspage_s.magic;
+ }
+
+ if (zs_magic != ZSPAGE_MAGIC)
+ error(FATAL, "zspage magic incorrect: %x\n", zs_magic);
class = pool + OFFSET(zspoll_size_class);
class += (class_idx * sizeof(void *));
@@ -2794,8 +2807,13 @@ zram_object_addr(ulong pool, ulong handle, unsigned char *zram_buf)
}
pages[0] = page;
- readmem(page + OFFSET(page_freelist), KVADDR, &pages[1],
- sizeof(void *), "page_freelist", FAULT_ON_ERROR);
+ if (VALID_MEMBER(page_freelist)) {
+ readmem(page + OFFSET(page_freelist), KVADDR, &pages[1],
+ sizeof(void *), "page_freelist", FAULT_ON_ERROR);
+ } else {
+ readmem(page + OFFSET(page_index), KVADDR, &pages[1],
+ sizeof(void *), "page_index", FAULT_ON_ERROR);
+ }
sizes[0] = PAGESIZE() - off;
sizes[1] = size - sizes[0];
if (!is_page_ptr(pages[0], &paddr)) {
@@ -2812,9 +2830,15 @@ zram_object_addr(ulong pool, ulong handle, unsigned char *zram_buf)
readmem(paddr, PHYSADDR, zram_buf + sizes[0], sizes[1], "zram buffer[1]", FAULT_ON_ERROR);
out:
- readmem(page, KVADDR, &obj, sizeof(void *), "page flags", FAULT_ON_ERROR);
- if (!(obj & (1<<10))) { //PG_OwnerPriv1 flag
- return (zram_buf + ZS_HANDLE_SIZE);
+ if (!VALID_MEMBER(zspage_huge)) {
+ readmem(page, KVADDR, &obj, sizeof(void *), "page flags", FAULT_ON_ERROR);
+ if (!(obj & (1<<10))) { //PG_OwnerPriv1 flag
+ return (zram_buf + ZS_HANDLE_SIZE);
+ }
+ } else {
+ if (!zspage6_s.huge) {
+ return (zram_buf + ZS_HANDLE_SIZE);
+ }
}
return zram_buf;
@@ -2929,6 +2953,8 @@ try_zram_decompress(ulonglong pte_val, unsigned char *buf, ulong len, ulonglong
unsigned char *outbuf = NULL;
ulong zram, zram_table_entry, sector, index, entry, flags, size,
outsize, off;
+ unsigned long *same_buf = NULL;
+ bool is_same = false;
if (INVALID_MEMBER(zram_compressor)) {
zram_init();
@@ -2992,11 +3018,30 @@ try_zram_decompress(ulonglong pte_val, unsigned char *buf, ulong len, ulonglong
sizeof(void *), "entry of table", FAULT_ON_ERROR);
readmem(zram_table_entry + OFFSET(zram_table_flag), KVADDR, &flags,
sizeof(void *), "zram_table_flag", FAULT_ON_ERROR);
- if (!entry || (flags & ZRAM_FLAG_SAME_BIT)) {
- memset(buf, entry, len);
+
+ if (THIS_KERNEL_VERSION >= LINUX(5,1,0)) {
+ if (!entry || flags & (1 << (PAGESHIFT() + 1 + 1)))
+ is_same = true;
+ } else {
+ if (!entry || (flags & ZRAM_FLAG_SAME_BIT))
+ is_same = true;
+ }
+
+ if (is_same) {
+ same_buf = (unsigned long *)GETBUF(PAGESIZE());
+ for (int count = 0; count < PAGESIZE() / sizeof(unsigned long); count++) {
+ same_buf[count] = entry;
+ }
+ memcpy(buf, same_buf + off, PAGESIZE());
+ FREEBUF(same_buf);
goto out;
}
- size = flags & (ZRAM_FLAG_SHIFT -1);
+
+ if (THIS_KERNEL_VERSION >= LINUX(5,1,0)) {
+ size = flags & ((1 << (PAGESHIFT() + 1)) - 1);
+ } else {
+ size = flags & (ZRAM_FLAG_SHIFT -1);
+ }
if (size == 0) {
len = 0;
goto out;
--
2.39.0
|
From 59a3b4b4e797278921f82955d57811a732d84e7d Mon Sep 17 00:00:00 2001 From: chenguanyou <chenguanyou@xxxxxxxxxx> Date: Mon, 11 Sep 2023 20:59:39 +0800 Subject: [PATCH v3] Fix: move huge compressed obj from page to zspage when zspage define 'huge', crash-utility zram decompress fail. we need to be compatible with the previous kernel, so we can't define 'huge' directly in zspage, just move to the right when calculating. Before: crash> mod -s zram zram.ko MODULE NAME BASE SIZE OBJECT FILE ffffffde224db800 zram ffffffde224d2000 57344 zram.ko crash> mod -s zsmalloc zsmalloc.ko MODULE NAME BASE SIZE OBJECT FILE ffffffde224c5180 zsmalloc ffffffde224bf000 40960 zsmalloc.ko crash> rd 0x13d89fb0 rd: zspage magic incorrect: b0 After: crash> rd 0x13d89fb0 13d89fb0: c2b54f7170883b20 ;.pqO.. Link: https://lkml.kernel.org/r/20211115185909.3949505-6-minchan@xxxxxxxxxx Signed-off-by: chenguanyou <chenguanyou@xxxxxxxxxx> --- defs.h | 13 ++++++++++ diskdump.c | 69 ++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/defs.h b/defs.h index 96a7a2a..0af69cc 100644 --- a/defs.h +++ b/defs.h @@ -2225,6 +2225,7 @@ struct offset_table { /* stash of commonly-used offsets */ long module_memory_base; long module_memory_size; long irq_data_irq; + long zspage_huge; }; struct size_table { /* stash of commonly-used sizes */ @@ -7221,6 +7222,18 @@ struct zspage { unsigned int freeobj; }; +struct zspage6 { + struct { + unsigned int huge : 1; + unsigned int fullness : 2; + unsigned int class : 9; + unsigned int isolated : 3; + unsigned int magic : 8; + }; + unsigned int inuse; + unsigned int freeobj; +}; + /* * makedumpfile.c */ diff --git a/diskdump.c b/diskdump.c index 2c284ff..592667f 100644 --- a/diskdump.c +++ b/diskdump.c @@ -2754,6 +2754,9 @@ zram_init(void) if (INVALID_MEMBER(zram_table_flag)) MEMBER_OFFSET_INIT(zram_table_flag, "zram_table_entry", "value"); STRUCT_SIZE_INIT(zram_table_entry, "zram_table_entry"); + MEMBER_OFFSET_INIT(zspoll_size_class, "zs_pool", "size_class"); + MEMBER_OFFSET_INIT(size_class_size, "size_class", "size"); + MEMBER_OFFSET_INIT(zspage_huge, "zspage", "huge"); } static unsigned char * @@ -2761,9 +2764,11 @@ zram_object_addr(ulong pool, ulong handle, unsigned char *zram_buf) { ulong obj, off, class, page, zspage; struct zspage zspage_s; + struct zspage6 zspage6_s; physaddr_t paddr; unsigned int obj_idx, class_idx, size; ulong pages[2], sizes[2]; + ulong zs_magic; readmem(handle, KVADDR, &obj, sizeof(void *), "zram entry", FAULT_ON_ERROR); obj >>= OBJ_TAG_BITS; @@ -2772,11 +2777,19 @@ zram_object_addr(ulong pool, ulong handle, unsigned char *zram_buf) readmem(page + OFFSET(page_private), KVADDR, &zspage, sizeof(void *), "page_private", FAULT_ON_ERROR); - readmem(zspage, KVADDR, &zspage_s, sizeof(struct zspage), "zspage", FAULT_ON_ERROR); - class_idx = zspage_s.class; - if (zspage_s.magic != ZSPAGE_MAGIC) - error(FATAL, "zspage magic incorrect: %x\n", zspage_s.magic); + if (VALID_MEMBER(zspage_huge)) { + readmem(zspage, KVADDR, &zspage6_s, sizeof(struct zspage6), "zspage6", FAULT_ON_ERROR); + class_idx = zspage6_s.class; + zs_magic = zspage6_s.magic; + } else { + readmem(zspage, KVADDR, &zspage_s, sizeof(struct zspage), "zspage", FAULT_ON_ERROR); + class_idx = zspage_s.class; + zs_magic = zspage_s.magic; + } + + if (zs_magic != ZSPAGE_MAGIC) + error(FATAL, "zspage magic incorrect: %x\n", zs_magic); class = pool + OFFSET(zspoll_size_class); class += (class_idx * sizeof(void *)); @@ -2794,8 +2807,13 @@ zram_object_addr(ulong pool, ulong handle, unsigned char *zram_buf) } pages[0] = page; - readmem(page + OFFSET(page_freelist), KVADDR, &pages[1], - sizeof(void *), "page_freelist", FAULT_ON_ERROR); + if (VALID_MEMBER(page_freelist)) { + readmem(page + OFFSET(page_freelist), KVADDR, &pages[1], + sizeof(void *), "page_freelist", FAULT_ON_ERROR); + } else { + readmem(page + OFFSET(page_index), KVADDR, &pages[1], + sizeof(void *), "page_index", FAULT_ON_ERROR); + } sizes[0] = PAGESIZE() - off; sizes[1] = size - sizes[0]; if (!is_page_ptr(pages[0], &paddr)) { @@ -2812,9 +2830,15 @@ zram_object_addr(ulong pool, ulong handle, unsigned char *zram_buf) readmem(paddr, PHYSADDR, zram_buf + sizes[0], sizes[1], "zram buffer[1]", FAULT_ON_ERROR); out: - readmem(page, KVADDR, &obj, sizeof(void *), "page flags", FAULT_ON_ERROR); - if (!(obj & (1<<10))) { //PG_OwnerPriv1 flag - return (zram_buf + ZS_HANDLE_SIZE); + if (!VALID_MEMBER(zspage_huge)) { + readmem(page, KVADDR, &obj, sizeof(void *), "page flags", FAULT_ON_ERROR); + if (!(obj & (1<<10))) { //PG_OwnerPriv1 flag + return (zram_buf + ZS_HANDLE_SIZE); + } + } else { + if (!zspage6_s.huge) { + return (zram_buf + ZS_HANDLE_SIZE); + } } return zram_buf; @@ -2929,6 +2953,8 @@ try_zram_decompress(ulonglong pte_val, unsigned char *buf, ulong len, ulonglong unsigned char *outbuf = NULL; ulong zram, zram_table_entry, sector, index, entry, flags, size, outsize, off; + unsigned long *same_buf = NULL; + bool is_same = false; if (INVALID_MEMBER(zram_compressor)) { zram_init(); @@ -2992,11 +3018,30 @@ try_zram_decompress(ulonglong pte_val, unsigned char *buf, ulong len, ulonglong sizeof(void *), "entry of table", FAULT_ON_ERROR); readmem(zram_table_entry + OFFSET(zram_table_flag), KVADDR, &flags, sizeof(void *), "zram_table_flag", FAULT_ON_ERROR); - if (!entry || (flags & ZRAM_FLAG_SAME_BIT)) { - memset(buf, entry, len); + + if (THIS_KERNEL_VERSION >= LINUX(5,1,0)) { + if (!entry || flags & (1 << (PAGESHIFT() + 1 + 1))) + is_same = true; + } else { + if (!entry || (flags & ZRAM_FLAG_SAME_BIT)) + is_same = true; + } + + if (is_same) { + same_buf = (unsigned long *)GETBUF(PAGESIZE()); + for (int count = 0; count < PAGESIZE() / sizeof(unsigned long); count++) { + same_buf[count] = entry; + } + memcpy(buf, same_buf + off, PAGESIZE()); + FREEBUF(same_buf); goto out; } - size = flags & (ZRAM_FLAG_SHIFT -1); + + if (THIS_KERNEL_VERSION >= LINUX(5,1,0)) { + size = flags & ((1 << (PAGESHIFT() + 1)) - 1); + } else { + size = flags & (ZRAM_FLAG_SHIFT -1); + } if (size == 0) { len = 0; goto out; -- 2.39.0
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility Contribution Guidelines: https://github.com/crash-utility/crash/wiki