Hi crash maintainers, The previous patch is a mistake that can be ignored. Please help review the following rework patch, thanks! The determination for a slab page has changed due to changing PG_slab from a page flag to a page type since kernel commit 46df8e73a4a3. 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@xxxxxxxxxxxxx> --- defs.h | 7 ++++++ memory.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/defs.h b/defs.h index dfbd241..d6cb2af 100644 --- a/defs.h +++ b/defs.h @@ -1416,6 +1416,7 @@ struct offset_table { /* stash of commonly-used offsets */ long page_buffers; long page_lru; long page_pte; + long page_page_type; long swap_info_struct_swap_file; long swap_info_struct_swap_vfsmnt; long swap_info_struct_flags; @@ -2651,6 +2652,7 @@ struct vm_table { /* kernel VM-related data */ ulong max_mem_section_nr; ulong zero_paddr; ulong huge_zero_paddr; + uint page_type_base; }; #define NODES (0x1) @@ -2684,6 +2686,11 @@ struct vm_table { /* kernel VM-related data */ #define SLAB_CPU_CACHE (0x10000000) #define SLAB_ROOT_CACHES (0x20000000) #define USE_VMAP_NODES (0x40000000) +/* + * The SLAB_PAGEFLAGS flag is introduced to detect the change of + * PG_slab's type from a page flag to a page type. + */ +#define SLAB_PAGEFLAGS (0x80000000) #define IS_FLATMEM() (vt->flags & FLATMEM) #define IS_DISCONTIGMEM() (vt->flags & DISCONTIGMEM) diff --git a/memory.c b/memory.c index a74ebaf..f4905a2 100644 --- a/memory.c +++ b/memory.c @@ -323,6 +323,7 @@ static ulong kmem_cache_nodelists(ulong); static void dump_hstates(void); static ulong freelist_ptr(struct meminfo *, ulong, ulong); static ulong handle_each_vm_area(struct handle_each_vm_area_args *); +static void page_type_init(void); /* * Memory display modes specific to this file. @@ -504,6 +505,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"); @@ -1278,6 +1281,8 @@ vm_init(void) page_flags_init(); + page_type_init(); + rss_page_types_init(); vt->flags |= VM_INIT; @@ -5645,6 +5650,36 @@ PG_slab_flag_init(void) #define PGMM_CACHED (512) +#define PAGE_TYPE_BASE 0xf0000000 +#define PageType(page_type, flag) \ + ((page_type & (vt->page_type_base | flag)) == vt->page_type_base) + + +static void page_type_init(void) +{ + /* + * The page type macros covert into enum since kernel commit ff202303c398e, + * use the default macro value if the vmcoreinfo without enum pagetype. + */ + if (!enumerator_value("PAGE_TYPE_BASE", (long *)&vt->page_type_base)) + vt->page_type_base = PAGE_TYPE_BASE; +} + +/* + * The PG_slab's type has changed from a page flag to a page type + * since kernel commit 46df8e73a4a3. + */ +static bool PageSlab(ulong flags, uint page_type) +{ + if (vt->flags & SLAB_PAGEFLAGS) { + if ((flags >> vt->PG_slab) & 1) + return TRUE; + } else if (PageType(page_type, (uint)vt->PG_slab)) + return TRUE; + else + return FALSE; +} + static void dump_mem_map_SPARSEMEM(struct meminfo *mi) { @@ -5657,7 +5692,7 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi) ulong PG_reserved_flag; long buffers; ulong inode, offset, flags, mapping, index; - uint count; + uint count, page_type; int print_hdr, pg_spec, phys_spec, done; int v22; char hdr[BUFSIZE]; @@ -5904,6 +5939,7 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi) if (SIZE(page_flags) == 4) flags &= 0xffffffff; count = UINT(pcache + OFFSET(page_count)); + page_type = UINT(pcache + OFFSET(page_page_type)); switch (mi->flags) { @@ -5931,7 +5967,7 @@ dump_mem_map_SPARSEMEM(struct meminfo *mi) if ((flags >> v22_PG_Slab) & 1) slabs++; } else if (vt->PG_slab) { - if ((flags >> vt->PG_slab) & 1) + if (PageSlab(flags, page_type)) slabs++; } else { if ((flags >> v24_PG_slab) & 1) @@ -6142,7 +6178,7 @@ dump_mem_map(struct meminfo *mi) long buffers; ulong inode, offset, flags, mapping, index; ulong node_size; - uint count; + uint count, page_type; int print_hdr, pg_spec, phys_spec, done; int v22; struct node_table *nt; @@ -6354,6 +6390,7 @@ dump_mem_map(struct meminfo *mi) if (SIZE(page_flags) == 4) flags &= 0xffffffff; count = UINT(pcache + OFFSET(page_count)); + page_type = UINT(pcache + OFFSET(page_page_type)); switch (mi->flags) { @@ -6381,7 +6418,7 @@ dump_mem_map(struct meminfo *mi) if ((flags >> v22_PG_Slab) & 1) slabs++; } else if (vt->PG_slab) { - if ((flags >> vt->PG_slab) & 1) + if (PageSlab(flags, page_type)) slabs++; } else { if ((flags >> v24_PG_slab) & 1) @@ -6694,7 +6731,6 @@ dump_hstates() FREEBUF(hstate); } - static void page_flags_init(void) { @@ -6775,6 +6811,9 @@ page_flags_init_from_pageflag_names(void) vt->pageflags_data[i].name = nameptr; vt->pageflags_data[i].mask = mask; + if (!strncmp(nameptr, "slab", 4)) + vt->flags |= SLAB_PAGEFLAGS; + if (CRASHDEBUG(1)) { fprintf(fp, " %08lx %s\n", vt->pageflags_data[i].mask, @@ -6835,8 +6874,9 @@ page_flags_init_from_pageflags_enum(void) } strcpy(nameptr, arglist[0] + strlen("PG_")); vt->pageflags_data[p].name = nameptr; - vt->pageflags_data[p].mask = 1 << atoi(arglist[2]); - + vt->pageflags_data[p].mask = 1 << atoi(arglist[2]); + if (!strcmp(nameptr, "slab")) + vt->flags |= SLAB_PAGEFLAGS; p++; } } else @@ -9715,6 +9755,7 @@ vaddr_to_kmem_cache(ulong vaddr, char *buf, int verbose) { physaddr_t paddr; ulong page, cache, page_flags; + uint page_type; if (!kvtop(NULL, vaddr, &paddr, 0)) { if (verbose) @@ -9736,14 +9777,20 @@ vaddr_to_kmem_cache(ulong vaddr, char *buf, int verbose) readmem(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(page_type), "page_type", + FAULT_ON_ERROR); + if (!PageSlab(page_flags, page_type)) { if (((vt->flags & KMALLOC_SLUB) || VALID_MEMBER(page_compound_head)) || ((vt->flags & KMALLOC_COMMON) && VALID_MEMBER(page_slab) && VALID_MEMBER(page_first_page))) { 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(compound_head(page)+OFFSET(page_page_type), KVADDR, + &page_type, sizeof(page_type), "page_type", + FAULT_ON_ERROR); + if (!PageSlab(page_flags, page_type)) return NULL; } else return NULL; @@ -20195,6 +20242,7 @@ is_slab_page(struct meminfo *si, char *buf) { int i, cnt; ulong page_slab, page_flags, name; + uint page_type; ulong *cache_list; char *retval; @@ -20209,7 +20257,12 @@ 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; + + if (!PageSlab(page_flags, page_type)) return NULL; if (!readmem(si->spec_addr + OFFSET(page_slab), KVADDR, -- 2.25.1 -- Crash-utility mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxxxxxx https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/ Contribution Guidelines: https://github.com/crash-utility/crash/wiki