On Fri, Aug 30, 2024 at 7:39 PM <devel-request@lists.crash-utility.osci.io> wrote:
Date: Fri, 30 Aug 2024 10:33:03 -0000
From: qiwu.chen@transsion.com
Subject: [Crash-utility] [PATCH] kmem: fix the determination for slab
        page
To: devel@lists.crash-utility.osci.io
Message-ID: <20240830103303.2824.23557@lists.crash-utility.osci.io>
Content-Type: text/plain; charset="utf-8"

The determination for a slab page is changed since kernel commit
8db00ad564617 which migrates PG_slab flag from page flags to the
lower 16 bit of the page type.


Thank you for the fix, qiwu.

Can you help double check if the code related to PG_* flags in the crash tool needs to be changed accordingly?

Thanks
Lianbo
 
Before apply this patch:
crash> kmem -s ffff000002aa4100
kmem: address is not allocated in slab subsystem: ffff000002aa4100

After apply this patch:
crash> kmem -s ffff000002aa4100
CACHE             OBJSIZE  ALLOCATED     TOTAL  SLABS  SSIZE  NAME
ffff00000140f900     4096         94       126     18    32k  task_struct
  SLAB              MEMORY            NODE  TOTAL  ALLOCATED  FREE
  fffffdffc00aa800  ffff000002aa0000     0      7          5     2
  FREE / [ALLOCATED]
  [ffff000002aa4100]

Signed-off-by: qiwu.chen <qiwu.chen@transsion.com>
---
 defs.h   |  1 +
 memory.c | 23 +++++++++++++++++++----
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/defs.h b/defs.h
index e9eb9e3..9ef7f97 100644
--- a/defs.h
+++ b/defs.h
@@ -2289,6 +2289,7 @@ struct offset_table {                    /* stash of commonly-used offsets */
        long track_cpu;
        long track_when;
        long track_handle;
+       long page_page_type;
 };

 struct size_table {         /* stash of commonly-used sizes */
diff --git a/memory.c b/memory.c
index 7bf8f86..f9ad6e4 100644
--- a/memory.c
+++ b/memory.c
@@ -509,6 +509,8 @@ vm_init(void)
                ANON_MEMBER_OFFSET_INIT(page_compound_head, "page", "compound_head");
        MEMBER_OFFSET_INIT(page_private, "page", "private");
        MEMBER_OFFSET_INIT(page_freelist, "page", "freelist");
+       if (MEMBER_EXISTS("page", "page_type"))
+               MEMBER_OFFSET_INIT(page_page_type, "page", "page_type");

        MEMBER_OFFSET_INIT(mm_struct_pgd, "mm_struct", "pgd");

@@ -10114,7 +10116,7 @@ static char *
 vaddr_to_kmem_cache(ulong vaddr, char *buf, int verbose)
 {
        physaddr_t paddr;
-       ulong page, cache, page_flags;
+       ulong page, cache, page_flags, page_type;

         if (!kvtop(NULL, vaddr, &paddr, 0)) {
                if (verbose)
@@ -10143,7 +10145,10 @@ vaddr_to_kmem_cache(ulong vaddr, char *buf, int verbose)
                                readmem(compound_head(page)+OFFSET(page_flags), KVADDR,
                                        &page_flags, sizeof(ulong), "page.flags",
                                        FAULT_ON_ERROR);
-                               if (!(page_flags & (1 << vt->PG_slab)))
+                               readmem(page + OFFSET(page_page_type), KVADDR, &page_type,
+                                       sizeof(ulong), "page type", FAULT_ON_ERROR);
+                               if (!(page_flags & (1 << vt->PG_slab)) &&
+                                       !(page_type & (1 << vt->PG_slab)))
                                        return NULL;
                        } else
                                return NULL;
@@ -20688,7 +20693,7 @@ char *
 is_slab_page(struct meminfo *si, char *buf)
 {
        int i, cnt;
-       ulong page_slab, page_flags, name;
+       ulong page_slab, page_flags, page_type, name;
         ulong *cache_list;
         char *retval;

@@ -20703,7 +20708,17 @@ is_slab_page(struct meminfo *si, char *buf)
            RETURN_ON_ERROR|QUIET))
                return NULL;

-       if (!(page_flags & (1 << vt->PG_slab)))
+       if (!readmem(si->spec_addr + OFFSET(page_page_type), KVADDR,
+           &page_type, sizeof(ulong), "page.page_type",
+           RETURN_ON_ERROR|QUIET))
+               return NULL;
+
+       /*
+        * PG_slab is migrated from the page flags to the lower 16 bit
+        * of the page type since linux commit 8db00ad564617.
+        */
+       if (!(page_flags & (1 << vt->PG_slab)) &&
+               !(page_type & (1 << vt->PG_slab)))
                return NULL;

        if (!readmem(si->spec_addr + OFFSET(page_slab), KVADDR,
--
2.25.1