[PATCH] Fix for "runq -g" option failure
by Lianbo Jiang
The "runq -g" option may fail on some vmcores from customers, and report
the following error:
crash> runq -g
...
malloc_bp[1998]: 11592c20
malloc_bp[1999]: 11662490
...
average size: 11922
runq: cannot allocate any more memory!
This is because the maximum number of malloc() was reached through
GETBUF(), currently which is limited to MAX_MALLOC_BUFS(2000).
Furthermore, the error messages is not very clear.
Given that, let's expand the limitation of MAX_MALLOC_BUFS and make the
error message clear and concise.
With the patch:
crash> runq -g
...
CPU 95
CURRENT: PID: 64281 TASK: ffff9f541b064000 COMMAND: "xxx_64281_sv"
ROOT_TASK_GROUP: ffffffffa64ff940 RT_RQ: ffff9f86bfdf3a80
[no tasks queued]
ROOT_TASK_GROUP: ffffffffa64ff940 CFS_RQ: ffff9f86bfdf38c0
[120] PID: 64281 TASK: ffff9f541b064000 COMMAND: "xxx_64281_sv" [CURRENT]
TASK_GROUP: ffff9f47cb3b9180 CFS_RQ: ffff9f67c0417a00 <user.slice>
[120] PID: 65275 TASK: ffff9f6820208000 COMMAND: "server"
TASK_GROUP: ffff9f67f9ac2300 CFS_RQ: ffff9f6803662000 <oratfagroup>
[120] PID: 1209636 TASK: ffff9f582f25c000 COMMAND: "crsctl"
Reported-by: Buland Kumar Singh <bsingh(a)redhat.com>
Signed-off-by: Lianbo Jiang <lijiang(a)redhat.com>
---
tools.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools.c b/tools.c
index a9ad18d520d9..6676881c182a 100644
--- a/tools.c
+++ b/tools.c
@@ -5698,7 +5698,7 @@ ll_power(long long base, long long exp)
#define B32K (4)
#define SHARED_BUF_SIZES (B32K+1)
-#define MAX_MALLOC_BUFS (2000)
+#define MAX_MALLOC_BUFS (3072)
#define MAX_CACHE_SIZE (KILOBYTES(32))
struct shared_bufs {
@@ -6130,7 +6130,7 @@ getbuf(long reqsize)
dump_shared_bufs();
return ((char *)(long)
- error(FATAL, "cannot allocate any more memory!\n"));
+ error(FATAL, "cannot allocate any more memory, reached to max numbers of malloc() via GETBUF()!\n"));
}
/*
--
2.51.1
12 hours, 39 minutes
[PATCH RFC] sys: Display livepatch transition status in KERNEL line
by Motomasa Suzuki
This commit enhances the 'sys' command to show if a kernel livepatch is
currently in a transition phase, directly within the KERNEL output line.
Currently, diagnosing system state during or immediately after livepatch
operations can be ambiguous. While 'livepatch' is indicated by
'[LIVEPATCH]', there's no direct indicator within 'crash' itself to show
if a livepatch is actively applying, reverting, or in some other
transient state. This lack of immediate visibility can complicate crash
analysis, as the system might be in an inconsistent state due to an
ongoing patch application/reversion.
This change introduces a new '[TRANSITION]' flag which appears next to
'[LIVEPATCH]' and '[TAINTED]' in the 'sys' command output. This flag is
set if the livepatch subsystem indicates an in-progress transition
(e.g., as exposed via '/sys/kernel/livepatch/<patch_name>/transition').
Example 'sys' output with this change:
KERNEL: /usr/lib/debug/lib/modules/<version_name>/vmlinux [LIVEPATCH]
[TRANSITION] [TAINTED]
This enhancement provides critical, at-a-glance information for
developers and administrators, allowing them to quickly ascertain if
ongoing livepatch activity might be influencing a system's behavior
during crash investigations. It directly leverages existing kernel
livepatch status infrastructure to enrich the crash utility's diagnostic
capabilities.
Signed-off-by: Motomasa Suzuki <suzuki.motomasa(a)fujitsu.com>
---
defs.h | 1 +
kernel.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 51 insertions(+), 3 deletions(-)
diff --git a/defs.h b/defs.h
index ab4aee8..b459d4d 100644
--- a/defs.h
+++ b/defs.h
@@ -2280,6 +2280,7 @@ struct offset_table { /* stash of commonly-used offsets */
long bpf_ringbuf_map_rb;
long bpf_ringbuf_consumer_pos;
long bpf_ringbuf_nr_pages;
+ long klp_patch_list;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/kernel.c b/kernel.c
index 13f3374..1ca18e4 100644
--- a/kernel.c
+++ b/kernel.c
@@ -461,7 +461,10 @@ kernel_init()
error(WARNING,
"list_head.next offset: %ld: list command may fail\n",
OFFSET(list_head_next));
-
+ if (STRUCT_EXISTS("klp_patch")) {
+ if (MEMBER_EXISTS("klp_patch", "list"))
+ MEMBER_OFFSET_INIT(klp_patch_list, "klp_patch", "list");
+ }
MEMBER_OFFSET_INIT(hlist_node_next, "hlist_node", "next");
MEMBER_OFFSET_INIT(hlist_node_pprev, "hlist_node", "pprev");
STRUCT_SIZE_INIT(hlist_head, "hlist_head");
@@ -5681,6 +5684,48 @@ is_livepatch(void)
return FALSE;
}
+#define KLP_PATCH_ITER_LIMIT 1024
+
+static int
+is_livepatch_transition(void)
+{
+ struct kernel_list_head head;
+ struct kernel_list_head node;
+ ulong transition_patch;
+ ulong list_addr;
+ ulong current;
+ ulong patch_addr;
+ int loops;
+
+ if (!try_get_symbol_data("klp_transition_patch", sizeof(ulong),
+ &transition_patch) || !transition_patch)
+ return FALSE;
+
+ if (!kernel_symbol_exists("klp_patches") || !VALID_MEMBER(klp_patch_list))
+ return FALSE;
+
+ list_addr = symbol_value("klp_patches");
+ if (!readmem(list_addr, KVADDR, &head, sizeof(head), "klp_patches",
+ RETURN_ON_ERROR | QUIET))
+ return FALSE;
+
+ for (current = (ulong)head.next, loops = 0;
+ current && current != list_addr && loops < KLP_PATCH_ITER_LIMIT;
+ current = (ulong)node.next, loops++) {
+
+ if (!readmem(list_addr, KVADDR, &head, sizeof(head),
+ "klp_patch list entry", RETURN_ON_ERROR | QUIET))
+ return FALSE;
+
+ patch_addr = current - (ulong)OFFSET(klp_patch_list);
+
+ if (patch_addr == transition_patch)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/*
* Display system stats at init-time or for the sys command.
*/
@@ -5724,17 +5769,19 @@ display_sys_stats(void)
}
} else {
if (pc->system_map) {
- fprintf(fp, " SYSTEM MAP: %s%s%s\n", pc->system_map,
+ fprintf(fp, " SYSTEM MAP: %s%s%s%s\n", pc->system_map,
is_livepatch() ? " [LIVEPATCH]" : "",
+ is_livepatch_transition() ? " [TRANSITION]" : "",
is_kernel_tainted() ? " [TAINTED]" : "");
fprintf(fp, "DEBUG KERNEL: %s %s\n",
pc->namelist_orig ?
pc->namelist_orig : pc->namelist,
debug_kernel_version(pc->namelist));
} else
- fprintf(fp, " KERNEL: %s%s%s\n", pc->namelist_orig ?
+ fprintf(fp, " KERNEL: %s%s%s%s\n", pc->namelist_orig ?
pc->namelist_orig : pc->namelist,
is_livepatch() ? " [LIVEPATCH]" : "",
+ is_livepatch_transition() ? " [TRANSITION]" : "",
is_kernel_tainted() ? " [TAINTED]" : "");
}
--
2.47.3
17 hours, 29 minutes
[PATCH] Revert "vmcoreinfo: read vmcoreinfo using 'vmcoreinfo_data' when unavailable in elf note"
by Tao Liu
This patch will cause a regression on some x86_64 vmcores.
$ crash -s vmcore vmlinux.gz
WARNING: vmcoreinfo is empty, will read from symbols
crash: cannot malloc vmcoreinfo buffer
crash: /var/tmp/vmlinux.gz_fWV3kA and vmcore do not match!
The root cause is, in main.c, is_kdump() calls is_netdump(), which will
set pc->read_vmcoreinfo as vmcoreinfo_read_from_memory(), rather than
original vmcoreinfo_read_string().
Later in machdep_init(PRE_SYMTAB), vmcoreinfo_read_from_memory() doesn't
get "relocate" string, so fails for set kaslr flag, then fails for
linux_banner detection:
Thread 1 "crash" hit Breakpoint 2, verify_version ():
1096 if (!IS_KVADDR(linux_banner))
(gdb) p/x linux_banner
$4 = 0xffffffff81e00100
crash> sym linux_banner
ffffffff9aa00100 (R) linux_banner
As we can see with the patch applied, linux_banner got a wrong address.
So this patch currently is unsafe, and should be reverted before the fix.
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
Since it is too close to the new release date of crash utility, I don't
have enough time for full root cause analysis and re-testing. So currently
the best option is to revert it for now, and fix it in the next release then
re-apply.
---
defs.h | 1 -
diskdump.c | 18 ------------------
kernel.c | 17 +++++------------
netdump.c | 19 -------------------
4 files changed, 5 insertions(+), 50 deletions(-)
diff --git a/defs.h b/defs.h
index ab4aee8..ae6ea01 100644
--- a/defs.h
+++ b/defs.h
@@ -6225,7 +6225,6 @@ void dump_kernel_table(int);
void dump_bt_info(struct bt_info *, char *where);
void dump_log(int);
void parse_kernel_version(char *);
-char *vmcoreinfo_read_from_memory(const char *);
#define LOG_LEVEL(v) ((v) & 0x07)
#define SHOW_LOG_LEVEL (0x1)
diff --git a/diskdump.c b/diskdump.c
index de90755..ce3cbb7 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -1041,13 +1041,6 @@ pfn_to_pos(ulong pfn)
return desc_pos;
}
-/**
- * Check if vmcoreinfo in vmcore is missing/empty
- */
-static bool is_diskdump_vmcoreinfo_empty(void)
-{
- return (dd->sub_header_kdump->size_vmcoreinfo == 0);
-}
/*
* Determine whether a file is a diskdump creation, and if TRUE,
@@ -1095,17 +1088,6 @@ is_diskdump(char *file)
pc->read_vmcoreinfo = vmcoreinfo_read_string;
- /*
- * vmcoreinfo can be empty in case of dump collected via virsh-dump
- *
- * check if vmcoreinfo is not available in vmcore, and try to read
- * the vmcoreinfo from memory, using "vmcoreinfo_data" symbol
- */
- if (is_diskdump_vmcoreinfo_empty()) {
- error(WARNING, "vmcoreinfo is empty, will read from symbols\n");
- pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
- }
-
if ((pc->flags2 & GET_LOG) && KDUMP_CMPRS_VALID()) {
pc->dfd = dd->dfd;
pc->readmem = read_diskdump;
diff --git a/kernel.c b/kernel.c
index 13f3374..e077275 100644
--- a/kernel.c
+++ b/kernel.c
@@ -99,6 +99,7 @@ static ulong dump_audit_skb_queue(ulong);
static ulong __dump_audit(char *);
static void dump_audit(void);
static void dump_printk_safe_seq_buf(int);
+static char *vmcoreinfo_read_string(const char *);
static void check_vmcoreinfo(void);
static int is_pvops_xen(void);
static int get_linux_banner_from_vmlinux(char *, size_t);
@@ -11894,8 +11895,8 @@ dump_printk_safe_seq_buf(int msg_flags)
* Returns a string (that has to be freed by the caller) that contains the
* value for key or NULL if the key has not been found.
*/
-char *
-vmcoreinfo_read_from_memory(const char *key)
+static char *
+vmcoreinfo_read_string(const char *key)
{
char *buf, *value_string, *p1, *p2;
size_t value_length;
@@ -11905,14 +11906,6 @@ vmcoreinfo_read_from_memory(const char *key)
buf = value_string = NULL;
- if (!(pc->flags & GDB_INIT)) {
- /*
- * GDB interface hasn't been initialised yet, so can't
- * access vmcoreinfo_data
- */
- return NULL;
- }
-
switch (get_symbol_type("vmcoreinfo_data", NULL, NULL))
{
case TYPE_CODE_PTR:
@@ -11968,10 +11961,10 @@ check_vmcoreinfo(void)
switch (get_symbol_type("vmcoreinfo_data", NULL, NULL))
{
case TYPE_CODE_PTR:
- pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
+ pc->read_vmcoreinfo = vmcoreinfo_read_string;
break;
case TYPE_CODE_ARRAY:
- pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
+ pc->read_vmcoreinfo = vmcoreinfo_read_string;
break;
}
}
diff --git a/netdump.c b/netdump.c
index 69100a9..c7ff009 100644
--- a/netdump.c
+++ b/netdump.c
@@ -111,14 +111,6 @@ map_cpus_to_prstatus(void)
FREEBUF(nt_ptr);
}
-/**
- * Check if vmcoreinfo in vmcore is missing/empty
- */
-static bool is_netdump_vmcoreinfo_empty(void)
-{
- return (nd->size_vmcoreinfo == 0);
-}
-
/*
* Determine whether a file is a netdump/diskdump/kdump creation,
* and if TRUE, initialize the vmcore_data structure.
@@ -472,17 +464,6 @@ is_netdump(char *file, ulong source_query)
pc->read_vmcoreinfo = vmcoreinfo_read_string;
- /*
- * vmcoreinfo can be empty in case of dump collected via virsh-dump
- *
- * check if vmcoreinfo is not available in vmcore, and try to read
- * the vmcoreinfo from memory, using "vmcoreinfo_data" symbol
- */
- if (is_netdump_vmcoreinfo_empty()) {
- error(WARNING, "vmcoreinfo is empty, will read from symbols\n");
- pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
- }
-
if ((source_query == KDUMP_LOCAL) &&
(pc->flags2 & GET_OSRELEASE))
kdump_get_osrelease();
--
2.47.0
1 day, 10 hours
[ANNOUNCE] crash-9.0.1 is available
by Tao Liu
Hi,
Thank you all for your contributions to the crash-utility, crash-9.0.1 is
now available.
Download from:
https://crash-utility.github.io/
or
https://github.com/crash-utility/crash/releases
The GitHub master branch serves as a development branch that will contain
all patches that are queued for the next release:
$ git clone https://github.com/crash-utility/crash.git
Changelog:
9cd43f5 crash-9.0.0 -> crash-9.0.1
82e6523 Add blk_mq_tag_set shared_tags check
72e2776 Revert "vmcoreinfo: read vmcoreinfo using 'vmcoreinfo_data' when
unavailable in elf note"
fbb2e9e s390x: Add basic 'bt -e' support for s390x
8d8fb30 s390x: Expand bt output with PSW mode and pt_regs address
141d542 gdb: set req->typecode when type resolvation success
3631b85 Revert "eppic.patch: Add customized functions to eppic"
3d57b4b Fix for "set" command failure
7636c13 vmcoreinfo: read vmcoreinfo using 'vmcoreinfo_data' when
unavailable in elf note
3fc8d40 eppic.patch: Add customized functions to eppic
5a564c2 extensions: Search all possible paths
536a0d7 RISCV64: fix wrong information of PMD and PTE - SA39(4K page)
support
21bdb00 s390x: Always perform kernel address translation in vtop verbose
mode.
0c55a29 s390x: Remove redundant vmalloc_start check from s390x_kvtop()
7debd84 s390x: Add non-zero vmalloc_start check to
s390x_vr_IS_VMALLOC_ADDR()
5190061 bpf: Implement ringbuf_map memory usage calculation
7b7e3e2 Fix the misleading uncompress error message
37c1e2b Add "log -R" to display human readable Rust symbol name
c62b317 Fix "mount" MNT_CURSOR entries (kernels 5.8-6.7)
be38ac1 Fix "mount <address>" fail when "super_block.s_files" unavaliable
8f1f826 Fix get_pathname() not handling stacked mounts
069ab89 Optimize extensions's compiler from gcc to $(CC)
0df7634 Fix for log command printed a couple of empty lines
9495fa7 Fix a compilation error on the old gcc version 8.5.0
99bb57a Enable resolving mangled Rust symbol in lockless ring buffer
a5942e3 Enable demangling a mangled Rust support
bd977d8 Add a rustfilt command to demangle a mangled Rust symbol
33f492f Fix the segfault issue caused by "dis -s" command
4e848b2 vmware_guestdump: support segment registers
4f2426d vmware_vmss: support segment registers
b3c8d98 RISCV64: Add 'PAGE DIRECTORY' property to the 'vtop' command
d2fb3f6 Support running on X86_64 with RISCV target
6248640 Add blk_mq shared tags support for dev -d/-D
2c69f93 gdb: Disable DT_DEBUG lookup by GDB inside the vmcore
31a69d3 Fix crash initialization failure on LoongArch with recent GDB
versions
6642b27 gdb: Fix a regression for eppic extension on gdb-16.2
6167a55 doc: Update requirements for building on Fedora
145cc6a x86_64: filter unwanted warning message for "bt -T" cmd
7e8a279 Fix "kmem -p" option on Linux 6.16-rc1 and later kernels
e906eac Fix the issue of "page excluded" messages flooding
0c14080 ppc64: Add gdb multi-stack unwind support
08271e4 arm64: Add gdb multi-stack unwind support
7b48881 x86_64: Add gdb multi-stack unwind support
d3ef6e4 Call cmd_bt silently after "set pid"
099f746 Add multi-threads support in crash target
6eb51d8 Fix incorrect task state during exit
a18b8a7 vmware_guestdump: Version 7 support
57c97d4 CI: enable ci-test with Testing Farm as github action
4002f53 Mark start of 9.0.1 development phase with version 9.0.0++
Full ChangeLog:
https://crash-utility.github.io/changelog/ChangeLog-9.0.1.txt
or
https://github.com/crash-utility/crash/compare/9.0.0...9.0.1
1 day, 11 hours
Re: [PATCH] Revert "vmcoreinfo: read vmcoreinfo using 'vmcoreinfo_data' when unavailable in elf note"
by lijiang
On Wed, Nov 19, 2025 at 12:51 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Wed, 19 Nov 2025 17:06:32 +1300
> From: Tao Liu <ltao(a)redhat.com>
> Subject: [Crash-utility] [PATCH] Revert "vmcoreinfo: read vmcoreinfo
> using 'vmcoreinfo_data' when unavailable in elf note"
> To: devel(a)lists.crash-utility.osci.io
> Cc: Tao Liu <ltao(a)redhat.com>
> Message-ID: <20251119040631.19214-2-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> This patch will cause a regression on some x86_64 vmcores.
>
> $ crash -s vmcore vmlinux.gz
> WARNING: vmcoreinfo is empty, will read from symbols
> crash: cannot malloc vmcoreinfo buffer
> crash: /var/tmp/vmlinux.gz_fWV3kA and vmcore do not match!
>
> The root cause is, in main.c, is_kdump() calls is_netdump(), which will
> set pc->read_vmcoreinfo as vmcoreinfo_read_from_memory(), rather than
> original vmcoreinfo_read_string().
>
> Later in machdep_init(PRE_SYMTAB), vmcoreinfo_read_from_memory() doesn't
> get "relocate" string, so fails for set kaslr flag, then fails for
> linux_banner detection:
>
> Thread 1 "crash" hit Breakpoint 2, verify_version ():
> 1096 if (!IS_KVADDR(linux_banner))
> (gdb) p/x linux_banner
> $4 = 0xffffffff81e00100
>
> crash> sym linux_banner
> ffffffff9aa00100 (R) linux_banner
>
> As we can see with the patch applied, linux_banner got a wrong address.
> So this patch currently is unsafe, and should be reverted before the fix.
>
> Signed-off-by: Tao Liu <ltao(a)redhat.com>
> ---
>
> Since it is too close to the new release date of crash utility, I don't
> have enough time for full root cause analysis and re-testing. So currently
> the best option is to revert it for now, and fix it in the next release
> then
> re-apply.
>
>
Agree. Thanks for working on it, Tao. So: Acke
Lianbo
---
> defs.h | 1 -
> diskdump.c | 18 ------------------
> kernel.c | 17 +++++------------
> netdump.c | 19 -------------------
> 4 files changed, 5 insertions(+), 50 deletions(-)
>
> diff --git a/defs.h b/defs.h
> index ab4aee8..ae6ea01 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -6225,7 +6225,6 @@ void dump_kernel_table(int);
> void dump_bt_info(struct bt_info *, char *where);
> void dump_log(int);
> void parse_kernel_version(char *);
> -char *vmcoreinfo_read_from_memory(const char *);
>
> #define LOG_LEVEL(v) ((v) & 0x07)
> #define SHOW_LOG_LEVEL (0x1)
> diff --git a/diskdump.c b/diskdump.c
> index de90755..ce3cbb7 100644
> --- a/diskdump.c
> +++ b/diskdump.c
> @@ -1041,13 +1041,6 @@ pfn_to_pos(ulong pfn)
> return desc_pos;
> }
>
> -/**
> - * Check if vmcoreinfo in vmcore is missing/empty
> - */
> -static bool is_diskdump_vmcoreinfo_empty(void)
> -{
> - return (dd->sub_header_kdump->size_vmcoreinfo == 0);
> -}
>
> /*
> * Determine whether a file is a diskdump creation, and if TRUE,
> @@ -1095,17 +1088,6 @@ is_diskdump(char *file)
>
> pc->read_vmcoreinfo = vmcoreinfo_read_string;
>
> - /*
> - * vmcoreinfo can be empty in case of dump collected via virsh-dump
> - *
> - * check if vmcoreinfo is not available in vmcore, and try to read
> - * the vmcoreinfo from memory, using "vmcoreinfo_data" symbol
> - */
> - if (is_diskdump_vmcoreinfo_empty()) {
> - error(WARNING, "vmcoreinfo is empty, will read from
> symbols\n");
> - pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
> - }
> -
> if ((pc->flags2 & GET_LOG) && KDUMP_CMPRS_VALID()) {
> pc->dfd = dd->dfd;
> pc->readmem = read_diskdump;
> diff --git a/kernel.c b/kernel.c
> index 13f3374..e077275 100644
> --- a/kernel.c
> +++ b/kernel.c
> @@ -99,6 +99,7 @@ static ulong dump_audit_skb_queue(ulong);
> static ulong __dump_audit(char *);
> static void dump_audit(void);
> static void dump_printk_safe_seq_buf(int);
> +static char *vmcoreinfo_read_string(const char *);
> static void check_vmcoreinfo(void);
> static int is_pvops_xen(void);
> static int get_linux_banner_from_vmlinux(char *, size_t);
> @@ -11894,8 +11895,8 @@ dump_printk_safe_seq_buf(int msg_flags)
> * Returns a string (that has to be freed by the caller) that contains the
> * value for key or NULL if the key has not been found.
> */
> -char *
> -vmcoreinfo_read_from_memory(const char *key)
> +static char *
> +vmcoreinfo_read_string(const char *key)
> {
> char *buf, *value_string, *p1, *p2;
> size_t value_length;
> @@ -11905,14 +11906,6 @@ vmcoreinfo_read_from_memory(const char *key)
>
> buf = value_string = NULL;
>
> - if (!(pc->flags & GDB_INIT)) {
> - /*
> - * GDB interface hasn't been initialised yet, so can't
> - * access vmcoreinfo_data
> - */
> - return NULL;
> - }
> -
> switch (get_symbol_type("vmcoreinfo_data", NULL, NULL))
> {
> case TYPE_CODE_PTR:
> @@ -11968,10 +11961,10 @@ check_vmcoreinfo(void)
> switch (get_symbol_type("vmcoreinfo_data", NULL, NULL))
> {
> case TYPE_CODE_PTR:
> - pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
> + pc->read_vmcoreinfo = vmcoreinfo_read_string;
> break;
> case TYPE_CODE_ARRAY:
> - pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
> + pc->read_vmcoreinfo = vmcoreinfo_read_string;
> break;
> }
> }
> diff --git a/netdump.c b/netdump.c
> index 69100a9..c7ff009 100644
> --- a/netdump.c
> +++ b/netdump.c
> @@ -111,14 +111,6 @@ map_cpus_to_prstatus(void)
> FREEBUF(nt_ptr);
> }
>
> -/**
> - * Check if vmcoreinfo in vmcore is missing/empty
> - */
> -static bool is_netdump_vmcoreinfo_empty(void)
> -{
> - return (nd->size_vmcoreinfo == 0);
> -}
> -
> /*
> * Determine whether a file is a netdump/diskdump/kdump creation,
> * and if TRUE, initialize the vmcore_data structure.
> @@ -472,17 +464,6 @@ is_netdump(char *file, ulong source_query)
>
> pc->read_vmcoreinfo = vmcoreinfo_read_string;
>
> - /*
> - * vmcoreinfo can be empty in case of dump collected via virsh-dump
> - *
> - * check if vmcoreinfo is not available in vmcore, and try to read
> - * the vmcoreinfo from memory, using "vmcoreinfo_data" symbol
> - */
> - if (is_netdump_vmcoreinfo_empty()) {
> - error(WARNING, "vmcoreinfo is empty, will read from
> symbols\n");
> - pc->read_vmcoreinfo = vmcoreinfo_read_from_memory;
> - }
> -
> if ((source_query == KDUMP_LOCAL) &&
> (pc->flags2 & GET_OSRELEASE))
> kdump_get_osrelease();
> --
> 2.47.0
>
1 day, 11 hours
Re: [PATCH] Add blk_mq_tag_set shared_tags check
by lijiang
On Wed, Nov 19, 2025 at 12:51 PM <devel-request(a)lists.crash-utility.osci.io>
wrote:
> Date: Wed, 19 Nov 2025 15:36:29 +1300
> From: Tao Liu <ltao(a)redhat.com>
> Subject: [Crash-utility] [PATCH] Add blk_mq_tag_set shared_tags check
> To: devel(a)lists.crash-utility.osci.io
> Cc: Tao Liu <ltao(a)redhat.com>
> Message-ID: <20251119023628.15998-2-ltao(a)redhat.com>
> Content-Type: text/plain; charset="US-ASCII"; x-default=true
>
> A regression of cmd dev -d/-D noticed on some vmcores as:
>
> dev: invalid structure member offset: blk_mq_tag_set_shared_tags
> FILE: dev.c LINE: 4468 FUNCTION: blk_mq_queue_tag_busy_iter()
>
> MAJOR GENDISK NAME REQUEST_QUEUE TOTAL ASYNC
> SYNC
> [crash] error trace: 91aa85 => 91a552 => 94d6ba => 94d647
>
> 94d647: OFFSET_verify.part.0+55
> 94d6ba: OFFSET_verify+42
> 91a552: get_diskio_1+2194
> 91aa85: display_all_diskio+1253
>
> The root cause is, though upstream kernel have defined
> BLK_MQ_F_TAG_HCTX_SHARED
> as (1 << 3), the value might be set different, e.g. [1]. So a single
>
We should be able to get the value of BLK_MQ_F_TAG_HCTX_SHARED via
the dump_enumerator_list(), and then test it in the following function:
static bool blk_mq_is_shared_tags(unsigned int flags)
{
return flags & BLK_MQ_F_TAG_HCTX_SHARED;
}
That can follow the changes once the upstream kernel modifies the value.
blk_mq_is_shared_tags() check is not sufficient. This patch will add
> shared_tagsblk_mq_is_shared_tags() check is not sufficient. This patch will
> add shared_tags
> member check within blk_mq_tag_set struct as an enhancment.
>
Anyway, this change looks good, so: Ack
Lianbo
[1]:
> https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-8/-/blob...
>
> Fixes: 62486400d35b ("Add blk_mq shared tags support for dev -d/-D")
> Signed-off-by: Tao Liu <ltao(a)redhat.com>
> ---
> dev.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/dev.c b/dev.c
> index 8391d71..27318e8 100644
> --- a/dev.c
> +++ b/dev.c
> @@ -4464,7 +4464,7 @@ static void blk_mq_queue_tag_busy_iter(ulong q,
> ulong *hctx, uint cnt,
> readmem(addr + OFFSET(blk_mq_tag_set_flags), KVADDR,
> &flags, sizeof(uint), "blk_mq_tag_set.flags",
> RETURN_ON_ERROR);
>
> - if (blk_mq_is_shared_tags(flags)) {
> + if (blk_mq_is_shared_tags(flags) &&
> VALID_MEMBER(blk_mq_tag_set_shared_tags)) {
> addr = addr + OFFSET(blk_mq_tag_set_shared_tags);
> queue_for_each_hw_ctx(q, addr, bitmap_tags_is_ptr, dio);
> return;
> --
> 2.47.0
>
1 day, 11 hours
[PATCH v3] Enhance blk_mq_tag_set shared_tags check
by Tao Liu
A regression of cmd dev -d/-D noticed on some vmcores as:
dev: invalid structure member offset: blk_mq_tag_set_shared_tags
FILE: dev.c LINE: 4468 FUNCTION: blk_mq_queue_tag_busy_iter()
MAJOR GENDISK NAME REQUEST_QUEUE TOTAL ASYNC SYNC
[crash] error trace: 91aa85 => 91a552 => 94d6ba => 94d647
94d647: OFFSET_verify.part.0+55
94d6ba: OFFSET_verify+42
91a552: get_diskio_1+2194
91aa85: display_all_diskio+1253
The root cause is, though upstream kernel have defined BLK_MQ_F_TAG_HCTX_SHARED
as (1 << 3), the value might be set different, e.g. [1]. So a single
blk_mq_is_shared_tags() check is not sufficient. This patch will resolve
BLK_MQ_F_TAG_HCTX_SHARED at runtime and add shared_tags member check within
blk_mq_tag_set struct as an enhancment.
[1]: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-8/-/blob...
Fixes: 62486400d35b ("Add blk_mq shared tags support for dev -d/-D")
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
v2 -> v3: replace arg_to_datatype() to enumerator_value().
---
dev.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/dev.c b/dev.c
index 8391d71..5ab6855 100644
--- a/dev.c
+++ b/dev.c
@@ -4326,11 +4326,25 @@ struct bt_iter_data {
#define MQ_RQ_IN_FLIGHT 1
#define REQ_OP_BITS 8
#define REQ_OP_MASK ((1 << REQ_OP_BITS) - 1)
-#define BLK_MQ_F_TAG_HCTX_SHARED (1 << 3)
static bool blk_mq_is_shared_tags(unsigned int flags)
{
- return flags & BLK_MQ_F_TAG_HCTX_SHARED;
+ static long value = -1;
+ static bool value_fetched = false;
+ struct datatype_member dm;
+
+ if (value_fetched)
+ goto out;
+
+ value_fetched = true;
+ if (enumerator_value("BLK_MQ_F_TAG_HCTX_SHARED", &value))
+ value = dm.value;
+out:
+ if (value < 0)
+ /* Invalid BLK_MQ_F_TAG_HCTX_SHARED */
+ return false;
+ else
+ return flags & value;
}
static uint op_is_write(uint op)
@@ -4464,7 +4478,7 @@ static void blk_mq_queue_tag_busy_iter(ulong q, ulong *hctx, uint cnt,
readmem(addr + OFFSET(blk_mq_tag_set_flags), KVADDR,
&flags, sizeof(uint), "blk_mq_tag_set.flags", RETURN_ON_ERROR);
- if (blk_mq_is_shared_tags(flags)) {
+ if (blk_mq_is_shared_tags(flags) && VALID_MEMBER(blk_mq_tag_set_shared_tags)) {
addr = addr + OFFSET(blk_mq_tag_set_shared_tags);
queue_for_each_hw_ctx(q, addr, bitmap_tags_is_ptr, dio);
return;
--
2.47.0
1 day, 17 hours
[PATCH v2] Enhance blk_mq_tag_set shared_tags check
by Tao Liu
A regression of cmd dev -d/-D noticed on some vmcores as:
dev: invalid structure member offset: blk_mq_tag_set_shared_tags
FILE: dev.c LINE: 4468 FUNCTION: blk_mq_queue_tag_busy_iter()
MAJOR GENDISK NAME REQUEST_QUEUE TOTAL ASYNC SYNC
[crash] error trace: 91aa85 => 91a552 => 94d6ba => 94d647
94d647: OFFSET_verify.part.0+55
94d6ba: OFFSET_verify+42
91a552: get_diskio_1+2194
91aa85: display_all_diskio+1253
The root cause is, though upstream kernel have defined BLK_MQ_F_TAG_HCTX_SHARED
as (1 << 3), the value might be set different, e.g. [1]. So a single
blk_mq_is_shared_tags() check is not sufficient. This patch will resolve
BLK_MQ_F_TAG_HCTX_SHARED at runtime and add shared_tags member check within
blk_mq_tag_set struct as an enhancment.
[1]: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-8/-/blob...
Fixes: 62486400d35b ("Add blk_mq shared tags support for dev -d/-D")
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
dev.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/dev.c b/dev.c
index 8391d71..7384de4 100644
--- a/dev.c
+++ b/dev.c
@@ -4326,11 +4326,28 @@ struct bt_iter_data {
#define MQ_RQ_IN_FLIGHT 1
#define REQ_OP_BITS 8
#define REQ_OP_MASK ((1 << REQ_OP_BITS) - 1)
-#define BLK_MQ_F_TAG_HCTX_SHARED (1 << 3)
static bool blk_mq_is_shared_tags(unsigned int flags)
{
- return flags & BLK_MQ_F_TAG_HCTX_SHARED;
+ static int value = -1;
+ static bool value_fetched = false;
+ struct datatype_member dm;
+
+ if (value_fetched)
+ goto out;
+
+ value_fetched = true;
+ if (!arg_to_datatype("BLK_MQ_F_TAG_HCTX_SHARED", &dm, RETURN_ON_ERROR) ||
+ (dm.size < 0) || (dm.type != 0x2000)) {
+ goto out;
+ }
+ value = dm.value;
+out:
+ if (value < 0)
+ /* Invalid BLK_MQ_F_TAG_HCTX_SHARED */
+ return false;
+ else
+ return flags & value;
}
static uint op_is_write(uint op)
@@ -4464,7 +4481,7 @@ static void blk_mq_queue_tag_busy_iter(ulong q, ulong *hctx, uint cnt,
readmem(addr + OFFSET(blk_mq_tag_set_flags), KVADDR,
&flags, sizeof(uint), "blk_mq_tag_set.flags", RETURN_ON_ERROR);
- if (blk_mq_is_shared_tags(flags)) {
+ if (blk_mq_is_shared_tags(flags) && VALID_MEMBER(blk_mq_tag_set_shared_tags)) {
addr = addr + OFFSET(blk_mq_tag_set_shared_tags);
queue_for_each_hw_ctx(q, addr, bitmap_tags_is_ptr, dio);
return;
--
2.47.0
2 days
[PATCH] Add blk_mq_tag_set shared_tags check
by Tao Liu
A regression of cmd dev -d/-D noticed on some vmcores as:
dev: invalid structure member offset: blk_mq_tag_set_shared_tags
FILE: dev.c LINE: 4468 FUNCTION: blk_mq_queue_tag_busy_iter()
MAJOR GENDISK NAME REQUEST_QUEUE TOTAL ASYNC SYNC
[crash] error trace: 91aa85 => 91a552 => 94d6ba => 94d647
94d647: OFFSET_verify.part.0+55
94d6ba: OFFSET_verify+42
91a552: get_diskio_1+2194
91aa85: display_all_diskio+1253
The root cause is, though upstream kernel have defined BLK_MQ_F_TAG_HCTX_SHARED
as (1 << 3), the value might be set different, e.g. [1]. So a single
blk_mq_is_shared_tags() check is not sufficient. This patch will add shared_tags
member check within blk_mq_tag_set struct as an enhancment.
[1]: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-8/-/blob...
Fixes: 62486400d35b ("Add blk_mq shared tags support for dev -d/-D")
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
dev.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dev.c b/dev.c
index 8391d71..27318e8 100644
--- a/dev.c
+++ b/dev.c
@@ -4464,7 +4464,7 @@ static void blk_mq_queue_tag_busy_iter(ulong q, ulong *hctx, uint cnt,
readmem(addr + OFFSET(blk_mq_tag_set_flags), KVADDR,
&flags, sizeof(uint), "blk_mq_tag_set.flags", RETURN_ON_ERROR);
- if (blk_mq_is_shared_tags(flags)) {
+ if (blk_mq_is_shared_tags(flags) && VALID_MEMBER(blk_mq_tag_set_shared_tags)) {
addr = addr + OFFSET(blk_mq_tag_set_shared_tags);
queue_for_each_hw_ctx(q, addr, bitmap_tags_is_ptr, dio);
return;
--
2.47.0
2 days, 17 hours
[PATCH] Fix "timer -r" option on Linux 6.18 and later kernels
by HAGIO KAZUHITO(萩尾 一仁)
Kernel commit 009eb5da29a9 ("hrtimer: Remove hrtimer_clock_base::
Get_time") removed the get_time member from struct hrtimer_clock_base.
As a result, the "timer -r" option fails with the following error:
crash> timer -r
timer: invalid structure member offset: hrtimer_clock_base_get_time
FILE: kernel.c LINE: 7953 FUNCTION: dump_hrtimer_clock_base()
As the get_time function is switched by __hrtimer_cb_get_time() function
with clock_id macro value, crash cannot follow their changes
automatically. So change what "timer -r" displays there from the
get_time function name to enum hrtimer_base_type name.
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
I refered to page_flags_init_from_pageflags_enum() function to use
dump_enumerator_list(), pc->flags2 and etc.
defs.h | 1 +
kernel.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++----
symbols.c | 2 ++
3 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/defs.h b/defs.h
index ab4aee8520a7..7f87e8e939e9 100644
--- a/defs.h
+++ b/defs.h
@@ -2280,6 +2280,7 @@ struct offset_table { /* stash of commonly-used offsets */
long bpf_ringbuf_map_rb;
long bpf_ringbuf_consumer_pos;
long bpf_ringbuf_nr_pages;
+ long hrtimer_clock_base_index;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/kernel.c b/kernel.c
index 13f33742990e..ec287bb55c05 100644
--- a/kernel.c
+++ b/kernel.c
@@ -43,6 +43,7 @@ static void display_bh_1(void);
static void display_bh_2(void);
static void display_bh_3(void);
static void display_bh_4(void);
+static int hrtimer_base_type_init(void);
static void dump_hrtimer_data(const ulong *cpus);
static void dump_hrtimer_clock_base(const void *, const int);
static void dump_hrtimer_base(const void *, const int);
@@ -796,6 +797,12 @@ kernel_init()
"hrtimer_clock_base", "first");
MEMBER_OFFSET_INIT(hrtimer_clock_base_get_time,
"hrtimer_clock_base", "get_time");
+ if (INVALID_MEMBER(hrtimer_clock_base_get_time)) {
+ /* Linux 6.18: 009eb5da29a9 */
+ MEMBER_OFFSET_INIT(hrtimer_clock_base_index, "hrtimer_clock_base", "index");
+ if (!hrtimer_base_type_init())
+ error(WARNING, "cannot get enum hrtimer_base_type\n");
+ }
}
STRUCT_SIZE_INIT(hrtimer_base, "hrtimer_base");
@@ -7938,6 +7945,52 @@ static int expires_len = -1;
static int softexpires_len = -1;
static int tte_len = -1;
+static char **hrtimer_base_type = NULL;
+static int
+hrtimer_base_type_init(void)
+{
+ long max_bases;
+ int i, c ATTRIBUTE_UNUSED;
+ char buf[BUFSIZE];
+ char *arglist[MAXARGS];
+
+ if (!enumerator_value("HRTIMER_MAX_CLOCK_BASES", &max_bases))
+ return FALSE;
+
+ hrtimer_base_type = (char **)calloc(max_bases, sizeof(char *));
+ if (!hrtimer_base_type)
+ return FALSE;
+
+ pc->flags2 |= ALLOW_FP; /* Required during initialization */
+ open_tmpfile();
+ if (dump_enumerator_list("hrtimer_base_type")) {
+ rewind(pc->tmpfile);
+ while (fgets(buf, BUFSIZE, pc->tmpfile)) {
+ if (!strstr(buf, " = "))
+ continue;
+ c = parse_line(buf, arglist);
+ i = atoi(arglist[2]);
+ if (0 <= i && i < max_bases)
+ hrtimer_base_type[i] = strdup(arglist[0]);
+ }
+ close_tmpfile();
+ pc->flags2 &= ~ALLOW_FP;
+ } else {
+ close_tmpfile();
+ pc->flags2 &= ~ALLOW_FP;
+ free(hrtimer_base_type);
+ hrtimer_base_type = NULL;
+ return FALSE;
+ }
+
+ if (CRASHDEBUG(1)) {
+ for (i = 0; i < max_bases; i++)
+ fprintf(fp, "hrtimer_base_type[%d] = %s\n", i, hrtimer_base_type[i]);
+ }
+
+ return TRUE;
+}
+
static void
dump_hrtimer_clock_base(const void *hrtimer_bases, const int num)
{
@@ -7949,11 +8002,23 @@ dump_hrtimer_clock_base(const void *hrtimer_bases, const int num)
base = (void *)hrtimer_bases + OFFSET(hrtimer_cpu_base_clock_base) +
SIZE(hrtimer_clock_base) * num;
- readmem((ulong)(base + OFFSET(hrtimer_clock_base_get_time)), KVADDR,
- &get_time, sizeof(get_time), "hrtimer_clock_base get_time",
- FAULT_ON_ERROR);
- fprintf(fp, " CLOCK: %d HRTIMER_CLOCK_BASE: %lx [%s]\n", num,
- (ulong)base, value_to_symstr(get_time, buf, 0));
+
+ if (INVALID_MEMBER(hrtimer_clock_base_get_time)) {
+ /* Linux 6.18: 009eb5da29a9 */
+ if (hrtimer_base_type) {
+ uint index;
+ readmem((ulong)(base + OFFSET(hrtimer_clock_base_index)), KVADDR, &index,
+ sizeof(index), "hrtimer_clock_base index", FAULT_ON_ERROR);
+ fprintf(fp, " CLOCK: %d HRTIMER_CLOCK_BASE: %lx [%s]\n", num,
+ (ulong)base, hrtimer_base_type[index]);
+ } else
+ fprintf(fp, " CLOCK: %d HRTIMER_CLOCK_BASE: %lx\n", num, (ulong)base);
+ } else {
+ readmem((ulong)(base + OFFSET(hrtimer_clock_base_get_time)), KVADDR, &get_time,
+ sizeof(get_time), "hrtimer_clock_base get_time", FAULT_ON_ERROR);
+ fprintf(fp, " CLOCK: %d HRTIMER_CLOCK_BASE: %lx [%s]\n", num,
+ (ulong)base, value_to_symstr(get_time, buf, 0));
+ }
/* get current time(uptime) */
get_uptime(NULL, ¤t_time);
diff --git a/symbols.c b/symbols.c
index 480fdb6d98b3..c446beb43a76 100644
--- a/symbols.c
+++ b/symbols.c
@@ -11760,6 +11760,8 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(hrtimer_clock_base_first));
fprintf(fp, " hrtimer_clock_base_get_time: %ld\n",
OFFSET(hrtimer_clock_base_get_time));
+ fprintf(fp, " hrtimer_clock_base_index: %ld\n",
+ OFFSET(hrtimer_clock_base_index));
fprintf(fp, " hrtimer_base_first: %ld\n",
OFFSET(hrtimer_base_first));
fprintf(fp, " hrtimer_base_pending: %ld\n",
--
2.31.1
3 days, 10 hours