From b29bd2b531502ca0274ad9c4531417920102fb26 Mon Sep 17 00:00:00 2001 From: Kazuhito Hagio Date: Fri, 10 Mar 2023 02:38:26 +0000 Subject: [PATCH 81/89] Fix "kmem -n" option to display memory blocks on Linux 6.3-rc1 and later Kernel commit d2bf38c088e0 ("driver core: remove private pointer from struct bus_type") removed the bus_type.p member, and the "kmem -n" option fails with the following error before displaying memory block information on Linux 6.3-rc1 and later kernels. kmem: invalid structure member offset: bus_type_p FILE: memory.c LINE: 17852 FUNCTION: init_memory_block() Search bus_kset.list instead for subsys_private of memory subsys. Signed-off-by: Kazuhito Hagio Signed-off-by: Lianbo Jiang --- defs.h | 2 ++ memory.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++------ symbols.c | 2 ++ 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/defs.h b/defs.h index 6cfc21487497..9091397a7012 100644 --- a/defs.h +++ b/defs.h @@ -2214,6 +2214,8 @@ struct offset_table { /* stash of commonly-used offsets */ long inet6_ifaddr_if_list; long inet6_ifaddr_if_next; long in6_addr_in6_u; + long kset_kobj; + long subsys_private_subsys; }; struct size_table { /* stash of commonly-used sizes */ diff --git a/memory.c b/memory.c index c4a6ecd18004..592a5ef49d50 100644 --- a/memory.c +++ b/memory.c @@ -17822,6 +17822,13 @@ static void init_memory_block_offset(void) { MEMBER_OFFSET_INIT(bus_type_p, "bus_type", "p"); + if (INVALID_MEMBER(bus_type_p)) { + MEMBER_OFFSET_INIT(kset_list, "kset", "list"); + MEMBER_OFFSET_INIT(kset_kobj, "kset", "kobj"); + MEMBER_OFFSET_INIT(kobject_name, "kobject", "name"); + MEMBER_OFFSET_INIT(kobject_entry, "kobject", "entry"); + MEMBER_OFFSET_INIT(subsys_private_subsys, "subsys_private", "subsys"); + } MEMBER_OFFSET_INIT(subsys_private_klist_devices, "subsys_private", "klist_devices"); MEMBER_OFFSET_INIT(klist_k_list, "klist", "k_list"); @@ -17842,15 +17849,60 @@ init_memory_block_offset(void) } static void -init_memory_block(struct list_data *ld, int *klistcnt, ulong **klistbuf) +init_memory_block(int *klistcnt, ulong **klistbuf) { - ulong memory_subsys = symbol_value("memory_subsys"); ulong private, klist, start; + struct list_data list_data, *ld; + + ld = &list_data; + private = 0; init_memory_block_offset(); - readmem(memory_subsys + OFFSET(bus_type_p), KVADDR, &private, - sizeof(void *), "memory_subsys.private", FAULT_ON_ERROR); + /* + * v6.3-rc1 + * d2bf38c088e0 driver core: remove private pointer from struct bus_type + */ + if (INVALID_MEMBER(bus_type_p)) { + int i, cnt; + char buf[32]; + ulong bus_kset, list, name; + + BZERO(ld, sizeof(struct list_data)); + + get_symbol_data("bus_kset", sizeof(ulong), &bus_kset); + readmem(bus_kset + OFFSET(kset_list), KVADDR, &list, + sizeof(ulong), "bus_kset.list", FAULT_ON_ERROR); + + ld->flags |= LIST_ALLOCATE; + ld->start = list; + ld->end = bus_kset + OFFSET(kset_list); + ld->list_head_offset = OFFSET(kobject_entry); + + cnt = do_list(ld); + for (i = 0; i < cnt; i++) { + readmem(ld->list_ptr[i] + OFFSET(kobject_name), KVADDR, &name, + sizeof(ulong), "kobject.name", FAULT_ON_ERROR); + read_string(name, buf, sizeof(buf)-1); + if (CRASHDEBUG(1)) + fprintf(fp, "kobject: %lx name: %s\n", ld->list_ptr[i], buf); + if (STREQ(buf, "memory")) { + /* entry is subsys_private.subsys.kobj. See bus_to_subsys(). */ + private = ld->list_ptr[i] - OFFSET(kset_kobj) + - OFFSET(subsys_private_subsys); + break; + } + } + FREEBUF(ld->list_ptr); + } else { + ulong memory_subsys = symbol_value("memory_subsys"); + readmem(memory_subsys + OFFSET(bus_type_p), KVADDR, &private, + sizeof(void *), "memory_subsys.private", FAULT_ON_ERROR); + } + + if (!private) + error(FATAL, "cannot determine subsys_private for memory.\n"); + klist = private + OFFSET(subsys_private_klist_devices) + OFFSET(klist_k_list); BZERO(ld, sizeof(struct list_data)); @@ -17875,7 +17927,6 @@ dump_memory_blocks(int initialize) ulong memory_block, device; ulong *klistbuf; int klistcnt, i; - struct list_data list_data; char mb_hdr[BUFSIZE]; char paddr_hdr[BUFSIZE]; char buf1[BUFSIZE]; @@ -17892,7 +17943,7 @@ dump_memory_blocks(int initialize) if (initialize) return; - init_memory_block(&list_data, &klistcnt, &klistbuf); + init_memory_block(&klistcnt, &klistbuf); if ((symbol_exists("memory_block_size_probed")) || (MEMBER_EXISTS("memory_block", "end_section_nr"))) diff --git a/symbols.c b/symbols.c index 158c95459bec..1d083b876f87 100644 --- a/symbols.c +++ b/symbols.c @@ -10416,6 +10416,7 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(kobject_entry)); fprintf(fp, " kset_list: %ld\n", OFFSET(kset_list)); + fprintf(fp, " kset_kobj: %ld\n", OFFSET(kset_kobj)); fprintf(fp, " request_list_count: %ld\n", OFFSET(request_list_count)); fprintf(fp, " request_cmd_flags: %ld\n", @@ -10453,6 +10454,7 @@ dump_offset_table(char *spec, ulong makestruct) fprintf(fp, " blk_mq_tags_rqs: %ld\n", OFFSET(blk_mq_tags_rqs)); + fprintf(fp, " subsys_private_subsys: %ld\n", OFFSET(subsys_private_subsys)); fprintf(fp, " subsys_private_klist_devices: %ld\n", OFFSET(subsys_private_klist_devices)); fprintf(fp, " subsystem_kset: %ld\n", -- 2.37.1