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(a)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