22c47c372b
Release: crash-8.0.2-3 Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
150 lines
5.3 KiB
Diff
150 lines
5.3 KiB
Diff
From d83df2fb66cd77877d365fda32cd45c531796599 Mon Sep 17 00:00:00 2001
|
|
From: Kazuhito Hagio <k-hagio-ab@nec.com>
|
|
Date: Fri, 16 Dec 2022 14:03:46 +0900
|
|
Subject: [PATCH 17/28] SLUB: Fix for offset change of struct slab members on
|
|
Linux 6.2-rc1
|
|
|
|
The following kernel commits split slab info from struct page into
|
|
struct slab in Linux 5.17.
|
|
|
|
d122019bf061 ("mm: Split slab into its own type")
|
|
07f910f9b729 ("mm: Remove slab from struct page")
|
|
|
|
Crash commit 5f390ed811b0 followed the change for SLUB, but crash still
|
|
uses the offset of page.lru inappropriately. Luckily, it could work
|
|
because it was the same value as the offset of slab.slab_list until
|
|
Linux 6.1.
|
|
|
|
However, kernel commit 130d4df57390 ("mm/sl[au]b: rearrange struct slab
|
|
fields to allow larger rcu_head") in Linux 6.2-rc1 changed the offset of
|
|
slab.slab_list. As a result, without the patch, "kmem -s|-S" options
|
|
print the following errors and fail to print values correctly for
|
|
kernels configured with CONFIG_SLUB.
|
|
|
|
crash> kmem -S filp
|
|
CACHE OBJSIZE ALLOCATED TOTAL SLABS SSIZE NAME
|
|
kmem: filp: partial list slab: ffffcc650405ab88 invalid page.inuse: -1
|
|
ffff8fa0401eca00 232 1267 1792 56 8k filp
|
|
...
|
|
KMEM_CACHE_NODE NODE SLABS PARTIAL PER-CPU
|
|
ffff8fa0401cb8c0 0 56 24 8
|
|
NODE 0 PARTIAL:
|
|
SLAB MEMORY NODE TOTAL ALLOCATED FREE
|
|
kmem: filp: invalid partial list slab pointer: ffffcc650405ab88
|
|
|
|
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
|
|
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
|
---
|
|
defs.h | 1 +
|
|
memory.c | 16 ++++++++++------
|
|
symbols.c | 1 +
|
|
3 files changed, 12 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/defs.h b/defs.h
|
|
index 0cff47e30ae9..d3d837631632 100644
|
|
--- a/defs.h
|
|
+++ b/defs.h
|
|
@@ -2188,6 +2188,7 @@ struct offset_table { /* stash of commonly-used offsets */
|
|
long blk_mq_tags_rqs;
|
|
long request_queue_hctx_table;
|
|
long percpu_counter_counters;
|
|
+ long slab_slab_list;
|
|
};
|
|
|
|
struct size_table { /* stash of commonly-used sizes */
|
|
diff --git a/memory.c b/memory.c
|
|
index 9d003713534b..d05737cc1429 100644
|
|
--- a/memory.c
|
|
+++ b/memory.c
|
|
@@ -781,6 +781,8 @@ vm_init(void)
|
|
if (INVALID_MEMBER(page_slab))
|
|
MEMBER_OFFSET_INIT(page_slab, "slab", "slab_cache");
|
|
|
|
+ MEMBER_OFFSET_INIT(slab_slab_list, "slab", "slab_list");
|
|
+
|
|
MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page");
|
|
if (INVALID_MEMBER(page_slab_page))
|
|
ANON_MEMBER_OFFSET_INIT(page_slab_page, "page", "slab_page");
|
|
@@ -19474,6 +19476,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node)
|
|
{
|
|
ulong next, last, list_head, flags;
|
|
int first;
|
|
+ long list_off = VALID_MEMBER(slab_slab_list) ? OFFSET(slab_slab_list) : OFFSET(page_lru);
|
|
|
|
if (!node_ptr)
|
|
return;
|
|
@@ -19487,7 +19490,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node)
|
|
next == list_head ? " (empty)\n" : "");
|
|
first = 0;
|
|
while (next != list_head) {
|
|
- si->slab = last = next - OFFSET(page_lru);
|
|
+ si->slab = last = next - list_off;
|
|
if (first++ == 0)
|
|
fprintf(fp, " %s", slab_hdr);
|
|
|
|
@@ -19510,7 +19513,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node)
|
|
|
|
if (!IS_KVADDR(next) ||
|
|
((next != list_head) &&
|
|
- !is_page_ptr(next - OFFSET(page_lru), NULL))) {
|
|
+ !is_page_ptr(next - list_off, NULL))) {
|
|
error(INFO,
|
|
"%s: partial list slab: %lx invalid page.lru.next: %lx\n",
|
|
si->curname, last, next);
|
|
@@ -19537,7 +19540,7 @@ do_node_lists_slub(struct meminfo *si, ulong node_ptr, int node)
|
|
next == list_head ? " (empty)\n" : "");
|
|
first = 0;
|
|
while (next != list_head) {
|
|
- si->slab = next - OFFSET(page_lru);
|
|
+ si->slab = next - list_off;
|
|
if (first++ == 0)
|
|
fprintf(fp, " %s", slab_hdr);
|
|
|
|
@@ -19754,6 +19757,7 @@ count_partial(ulong node, struct meminfo *si, ulong *free)
|
|
short inuse, objects;
|
|
ulong total_inuse;
|
|
ulong count = 0;
|
|
+ long list_off = VALID_MEMBER(slab_slab_list) ? OFFSET(slab_slab_list) : OFFSET(page_lru);
|
|
|
|
count = 0;
|
|
total_inuse = 0;
|
|
@@ -19765,12 +19769,12 @@ count_partial(ulong node, struct meminfo *si, ulong *free)
|
|
hq_open();
|
|
|
|
while (next != list_head) {
|
|
- if (!readmem(next - OFFSET(page_lru) + OFFSET(page_inuse),
|
|
+ if (!readmem(next - list_off + OFFSET(page_inuse),
|
|
KVADDR, &inuse, sizeof(ushort), "page.inuse", RETURN_ON_ERROR)) {
|
|
hq_close();
|
|
return -1;
|
|
}
|
|
- last = next - OFFSET(page_lru);
|
|
+ last = next - list_off;
|
|
|
|
if (inuse == -1) {
|
|
error(INFO,
|
|
@@ -19796,7 +19800,7 @@ count_partial(ulong node, struct meminfo *si, ulong *free)
|
|
}
|
|
if (!IS_KVADDR(next) ||
|
|
((next != list_head) &&
|
|
- !is_page_ptr(next - OFFSET(page_lru), NULL))) {
|
|
+ !is_page_ptr(next - list_off, NULL))) {
|
|
error(INFO, "%s: partial list slab: %lx invalid page.lru.next: %lx\n",
|
|
si->curname, last, next);
|
|
break;
|
|
diff --git a/symbols.c b/symbols.c
|
|
index cb5b508dcc50..33e68d520a72 100644
|
|
--- a/symbols.c
|
|
+++ b/symbols.c
|
|
@@ -9710,6 +9710,7 @@ dump_offset_table(char *spec, ulong makestruct)
|
|
OFFSET(slab_inuse));
|
|
fprintf(fp, " slab_free: %ld\n",
|
|
OFFSET(slab_free));
|
|
+ fprintf(fp, " slab_slab_list: %ld\n", OFFSET(slab_slab_list));
|
|
|
|
fprintf(fp, " kmem_cache_size: %ld\n",
|
|
OFFSET(kmem_cache_size));
|
|
--
|
|
2.37.1
|
|
|