[Crash-utility] [PATCH] Fix for "timer -r" option on Linux 5.4-rc1

Kazuhito Hagio k-hagio at ab.jp.nec.com
Mon Oct 14 20:22:12 UTC 2019


Fix for Linux 5.4-rc1 and later kernels that contain commit
511885d7061eda3eb1faf3f57dcc936ff75863f1, titled "lib/timerqueue: Rely on
rbtree semantics for next timer".  Without the patch, "timer -r" option
fails with the following error:

  timer: invalid structure member offset: timerqueue_head_next
         FILE: kernel.c  LINE: 7652  FUNCTION: dump_active_timers()

Also fix a typo in MEMBER_OFFSET_INIT(timerqueue_node_node, ...).

Signed-off-by: Kazuhito Hagio <k-hagio at ab.jp.nec.com>
---
 defs.h    |  2 ++
 kernel.c  | 16 ++++++++++++++--
 symbols.c |  4 ++++
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/defs.h b/defs.h
index 502e7c268448..efa40b9e1688 100644
--- a/defs.h
+++ b/defs.h
@@ -2073,6 +2073,8 @@ struct offset_table {                    /* stash of commonly-used offsets */
 	long cpu_context_save_r7;
 	long dentry_d_sb;
 	long device_private_knode_class;
+	long timerqueue_head_rb_root;
+	long rb_root_cached_rb_leftmost;
 };
 
 struct size_table {         /* stash of commonly-used sizes */
diff --git a/kernel.c b/kernel.c
index 375e1b4ceb67..c4cb0018962e 100644
--- a/kernel.c
+++ b/kernel.c
@@ -783,7 +783,13 @@ kernel_init()
 		MEMBER_OFFSET_INIT(timerqueue_node_expires, 
 			"timerqueue_node", "expires");
 		MEMBER_OFFSET_INIT(timerqueue_node_node, 
-			"timerqueue_node_node", "node");
+			"timerqueue_node", "node");
+		if (INVALID_MEMBER(timerqueue_head_next)) {
+			MEMBER_OFFSET_INIT(timerqueue_head_rb_root,
+				"timerqueue_head", "rb_root");
+			MEMBER_OFFSET_INIT(rb_root_cached_rb_leftmost,
+				"rb_root_cached", "rb_leftmost");
+		}
 	}
 	MEMBER_OFFSET_INIT(hrtimer_softexpires, "hrtimer", "_softexpires");
 	MEMBER_OFFSET_INIT(hrtimer_function, "hrtimer", "function");
@@ -7647,11 +7653,17 @@ next_one:
 		readmem((ulong)(base + OFFSET(hrtimer_clock_base_first)),
 			KVADDR,	&curr, sizeof(curr), "hrtimer_clock_base first",
 			FAULT_ON_ERROR);
-	else
+	else if (VALID_MEMBER(timerqueue_head_next))
 		readmem((ulong)(base + OFFSET(hrtimer_clock_base_active) +
 				OFFSET(timerqueue_head_next)),
 			KVADDR, &curr, sizeof(curr), "hrtimer_clock base",
 			FAULT_ON_ERROR);
+	else
+		readmem((ulong)(base + OFFSET(hrtimer_clock_base_active) +
+				OFFSET(timerqueue_head_rb_root) +
+				OFFSET(rb_root_cached_rb_leftmost)),
+			KVADDR, &curr, sizeof(curr),
+			"hrtimer_clock_base active", FAULT_ON_ERROR);
 
 	while (curr && i < next) {
 		curr = rb_next(curr);
diff --git a/symbols.c b/symbols.c
index 7af5e69da39b..eb88ca119751 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10032,6 +10032,8 @@ dump_offset_table(char *spec, ulong makestruct)
                 OFFSET(rb_node_rb_left));
         fprintf(fp, "              rb_node_rb_right: %ld\n",
                 OFFSET(rb_node_rb_right));
+        fprintf(fp, "    rb_root_cached_rb_leftmost: %ld\n",
+                OFFSET(rb_root_cached_rb_leftmost));
 
 	fprintf(fp, "            x8664_pda_pcurrent: %ld\n",
 		OFFSET(x8664_pda_pcurrent));
@@ -10388,6 +10390,8 @@ dump_offset_table(char *spec, ulong makestruct)
 		OFFSET(hrtimer_function));
 	fprintf(fp, "          timerqueue_head_next: %ld\n",
 		OFFSET(timerqueue_head_next));
+	fprintf(fp, "       timerqueue_head_rb_root: %ld\n",
+		OFFSET(timerqueue_head_rb_root));
 	fprintf(fp, "       timerqueue_node_expires: %ld\n",
 		OFFSET(timerqueue_node_expires));
 	fprintf(fp, "          timerqueue_node_node: %ld\n",
-- 
2.18.1




More information about the Crash-utility mailing list