[Crash-utility] [PATCH] timers: add option to show expired timers only

Oleksandr Natalenko oleksandr at redhat.com
Wed Jun 19 13:11:28 UTC 2019


Implement `timer` command option (namely, `-e`) that allows filtering
out all the non-expired timers.

This is useful to verify what CPU is blocked due to looping with
interrupts disabled or due to lack of resources to run the vCPU on a
hypervisor side.

Signed-off-by: Oleksandr Natalenko <oleksandr at redhat.com>
---
 help.c   |   1 +
 kernel.c | 213 ++++++++++++++++++++++++++++++++-----------------------
 2 files changed, 125 insertions(+), 89 deletions(-)

diff --git a/help.c b/help.c
index c0c750f..fa856d1 100644
--- a/help.c
+++ b/help.c
@@ -2886,6 +2886,7 @@ char *help_timer[] = {
 "        chronological order.  In the case of the old-style hrtimers, the",
 "        expiration time is a single value; in the new-style hrtimers, the",
 "        expiration time is a range.",
+"    -e  Display expired timers only.",
 " -C cpu Restrict the output to one or more CPUs, where multiple cpu[s] can", 
 "        be specified, for example, as \"1,3,5\", \"1-3\", or \"1,3,5-7,10\".",
 "\nEXAMPLES",
diff --git a/kernel.c b/kernel.c
index 22909d2..afc66da 100644
--- a/kernel.c
+++ b/kernel.c
@@ -38,24 +38,24 @@ 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 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);
-static void dump_active_timers(const void *, ulonglong);
+static void dump_hrtimer_data(const ulong *, int);
+static void dump_hrtimer_clock_base(const void *, const int, int);
+static void dump_hrtimer_base(const void *, const int, int);
+static void dump_active_timers(const void *, ulonglong, int);
 static int get_expires_len(const int, const ulong *, const int);
-static void print_timer(const void *);
+static void print_timer(const void *, ulonglong, int);
 static ulonglong ktime_to_ns(const void *);
-static void dump_timer_data(const ulong *cpus);
-static void dump_timer_data_tvec_bases_v1(const ulong *cpus);
-static void dump_timer_data_tvec_bases_v2(const ulong *cpus);
-static void dump_timer_data_tvec_bases_v3(const ulong *cpus);
-static void dump_timer_data_timer_bases(const ulong *cpus);
+static void dump_timer_data(const ulong *, int);
+static void dump_timer_data_tvec_bases_v1(const ulong *, int);
+static void dump_timer_data_tvec_bases_v2(const ulong *, int);
+static void dump_timer_data_tvec_bases_v3(const ulong *, int);
+static void dump_timer_data_timer_bases(const ulong *, int);
 struct tv_range;
 static void init_tv_ranges(struct tv_range *, int, int, int);
-static int do_timer_list(ulong,int, ulong *, void *,ulong *,struct tv_range *);
-static int do_timer_list_v3(ulong, int, ulong *, void *,ulong *);
+static int do_timer_list(ulong,int, ulong *, void *,ulong *,struct tv_range *, ulong, int);
+static int do_timer_list_v3(ulong, int, ulong *, void *,ulong *, ulong, int);
 struct timer_bases_data;
-static int do_timer_list_v4(struct timer_bases_data *);
+static int do_timer_list_v4(struct timer_bases_data *, ulong, int);
 static int compare_timer_data(const void *, const void *);
 static void panic_this_kernel(void);
 static void dump_waitq(ulong, char *);
@@ -7402,18 +7402,24 @@ cmd_timer(void)
 {
         int c;
 	int rflag;
+	int eflag;
 	char *cpuspec;
 	ulong *cpus = NULL;
 
 	rflag = 0;
+	eflag = 0;
 
-        while ((c = getopt(argcnt, args, "rC:")) != EOF) {
+        while ((c = getopt(argcnt, args, "reC:")) != EOF) {
                 switch(c)
                 {
 		case 'r':
 			rflag = 1;
 			break;
 
+		case 'e':
+			eflag = 1;
+			break;
+
 		case 'C':
 			cpuspec = optarg;
 			cpus = get_cpumask_buf();
@@ -7430,16 +7436,16 @@ cmd_timer(void)
                 cmd_usage(pc->curcmd, SYNOPSIS);
 
 	if (rflag)
-		dump_hrtimer_data(cpus);
+		dump_hrtimer_data(cpus, eflag);
 	else
-		dump_timer_data(cpus);
+		dump_timer_data(cpus, eflag);
 
 	if (cpus)
 		FREEBUF(cpus);
 }
 
 static void
-dump_hrtimer_data(const ulong *cpus)
+dump_hrtimer_data(const ulong *cpus, int eflag)
 {
 	int i, j, k = 0;
 	int hrtimer_max_clock_bases, max_hrtimer_bases;
@@ -7487,7 +7493,7 @@ dump_hrtimer_data(const ulong *cpus)
 					fprintf(fp, "\n");
 				dump_hrtimer_clock_base(
 					(void *)(hrtimer_bases->value) +
-					kt->__per_cpu_offset[i], j);
+					kt->__per_cpu_offset[i], j, eflag);
 			}
 		} else {
 			fprintf(fp, "\n");
@@ -7496,7 +7502,7 @@ dump_hrtimer_data(const ulong *cpus)
 					fprintf(fp, "\n");
 				dump_hrtimer_base(
 					(void *)(hrtimer_bases->value) +
-					kt->__per_cpu_offset[i], j);
+					kt->__per_cpu_offset[i], j, eflag);
 			}
 		}
 	}
@@ -7506,7 +7512,7 @@ static int expires_len = -1;
 static int softexpires_len = -1;
 
 static void
-dump_hrtimer_clock_base(const void *hrtimer_bases, const int num)
+dump_hrtimer_clock_base(const void *hrtimer_bases, const int num, int eflag)
 {
 	void *base;
 	ulonglong current_time, now;
@@ -7530,11 +7536,11 @@ dump_hrtimer_clock_base(const void *hrtimer_bases, const int num)
 		offset = ktime_to_ns(base + OFFSET(hrtimer_clock_base_offset));
 	now = current_time * (1000000000LL / machdep->hz) + offset;
 
-	dump_active_timers(base, now);
+	dump_active_timers(base, now, eflag);
 }
 
 static void
-dump_hrtimer_base(const void *hrtimer_bases, const int num)
+dump_hrtimer_base(const void *hrtimer_bases, const int num, int eflag)
 {
 	void *base;
 	ulonglong current_time, now;
@@ -7552,11 +7558,11 @@ dump_hrtimer_base(const void *hrtimer_bases, const int num)
 	get_uptime(NULL, &current_time);
 	now = current_time * (1000000000LL / machdep->hz);
 
-	dump_active_timers(base, now);
+	dump_active_timers(base, now, eflag);
 }
 
 static void
-dump_active_timers(const void *base, ulonglong now)
+dump_active_timers(const void *base, ulonglong now, int eflag)
 {
 	int next, i, t;
 	struct rb_node *curr;
@@ -7664,7 +7670,7 @@ next_one:
 		else
 			timer = (void *)(timer_list[t] - OFFSET(hrtimer_node));
 
-		print_timer(timer);
+		print_timer(timer, now, eflag);
 	}
 }
 
@@ -7715,7 +7721,7 @@ get_expires_len(const int timer_cnt, const ulong *timer_list, const int getsoft)
  * print hrtimer and its related information
  */
 static void
-print_timer(const void *timer)
+print_timer(const void *timer, ulonglong now, int eflag)
 {
 	ulonglong softexpires, expires;
 	
@@ -7724,6 +7730,15 @@ print_timer(const void *timer)
 	char buf2[BUFSIZE];
 	char buf3[BUFSIZE];
 
+	if (VALID_MEMBER(hrtimer_expires))
+		expires = ktime_to_ns(timer + OFFSET(hrtimer_expires));
+	else
+		expires = ktime_to_ns(timer + OFFSET(hrtimer_node) +
+			OFFSET(timerqueue_node_expires));
+
+	if (eflag && expires >= now)
+		return;
+
 	/* align information */
 	fprintf(fp, "  ");
 
@@ -7732,11 +7747,6 @@ print_timer(const void *timer)
 		return;
 	}
 
-	if (VALID_MEMBER(hrtimer_expires))
-		expires = ktime_to_ns(timer + OFFSET(hrtimer_expires));
-	else
-		expires = ktime_to_ns(timer + OFFSET(hrtimer_node) +
-			OFFSET(timerqueue_node_expires));
 
 	if (VALID_MEMBER(hrtimer_softexpires)) {
 		softexpires = ktime_to_ns(timer + OFFSET(hrtimer_softexpires));
@@ -7818,7 +7828,7 @@ struct tv_range {
 #define TVN (6)
 
 static void
-dump_timer_data(const ulong *cpus)
+dump_timer_data(const ulong *cpus, int eflag)
 {
 	int i;
 	ulong timer_active;
@@ -7839,16 +7849,16 @@ dump_timer_data(const ulong *cpus)
         struct tv_range tv[TVN];
 
 	if (kt->flags2 & TIMER_BASES) {
-		dump_timer_data_timer_bases(cpus);
+		dump_timer_data_timer_bases(cpus, eflag);
 		return;
 	} else if (kt->flags2 & TVEC_BASES_V3) {
-		dump_timer_data_tvec_bases_v3(cpus);
+		dump_timer_data_tvec_bases_v3(cpus, eflag);
 		return;
 	} else if (kt->flags & TVEC_BASES_V2) {
-		dump_timer_data_tvec_bases_v2(cpus);
+		dump_timer_data_tvec_bases_v2(cpus, eflag);
 		return;
 	} else if (kt->flags & TVEC_BASES_V1) {
-		dump_timer_data_tvec_bases_v1(cpus);
+		dump_timer_data_tvec_bases_v1(cpus, eflag);
 		return;
 	}
 		
@@ -7888,23 +7898,24 @@ dump_timer_data(const ulong *cpus)
 
 	init_tv_ranges(tv, vec_root_size, vec_size, 0);
 
+	get_symbol_data("jiffies", sizeof(ulong), &jiffies);
+	get_symbol_data("timer_jiffies", sizeof(ulong), &timer_jiffies);
+
         count += do_timer_list(symbol_value("tv1") + OFFSET(timer_vec_root_vec),
-		vec_root_size, vec, NULL, NULL, tv);
+		vec_root_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(symbol_value("tv2") + OFFSET(timer_vec_vec),
-		vec_size, vec, NULL, NULL, tv);
+		vec_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(symbol_value("tv3") + OFFSET(timer_vec_vec),
-		vec_size, vec, NULL, NULL, tv);
+		vec_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(symbol_value("tv4") + OFFSET(timer_vec_vec),
-		vec_size, vec, NULL, NULL, tv);
+		vec_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(symbol_value("tv4") + OFFSET(timer_vec_vec),
-		vec_size, vec, NULL, NULL, tv);
+		vec_size, vec, NULL, NULL, tv, jiffies, eflag);
 
 	td = (struct timer_data *)
 		GETBUF((count*2) * sizeof(struct timer_data));
 	tdx = 0;
 
-	get_symbol_data("jiffies", sizeof(ulong), &jiffies);
-	get_symbol_data("timer_jiffies", sizeof(ulong), &timer_jiffies);
 	if (old_timers_exist)
 		get_symbol_data("timer_active", sizeof(ulong), &timer_active);
 
@@ -7916,6 +7927,8 @@ dump_timer_data(const ulong *cpus)
 
                 if (!(mask & timer_active)) 
                         continue;
+		if (eflag && tp->expires >= jiffies)
+			continue;
 
 		td[tdx].address = i;
 		td[tdx].expires = tp->expires;
@@ -7926,15 +7939,15 @@ dump_timer_data(const ulong *cpus)
         }
 
 	do_timer_list(symbol_value("tv1") + OFFSET(timer_vec_root_vec),
-		vec_root_size, vec, (void *)td, &highest, tv);
+		vec_root_size, vec, (void *)td, &highest, tv, jiffies, eflag);
 	do_timer_list(symbol_value("tv2") + OFFSET(timer_vec_vec),
-		vec_size, vec, (void *)td, &highest, tv);
+		vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
 	do_timer_list(symbol_value("tv3") + OFFSET(timer_vec_vec),
-		vec_size, vec, (void *)td, &highest, tv);
+		vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
 	do_timer_list(symbol_value("tv4") + OFFSET(timer_vec_vec),
-		vec_size, vec, (void *)td, &highest, tv);
+		vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
 	tdx = do_timer_list(symbol_value("tv5") + OFFSET(timer_vec_vec),
-		vec_size, vec, (void *)td, &highest, tv);
+		vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
 
         qsort(td, tdx, sizeof(struct timer_data), compare_timer_data);
 
@@ -7951,6 +7964,9 @@ dump_timer_data(const ulong *cpus)
 		mkstring(buf, flen, CENTER|LJUST, "EXPIRES"));
 
         for (i = 0; i < tdx; i++) {
+		if (eflag && td[i].expires >= jiffies)
+			continue;
+
         	fprintf(fp, "%s", 
 		    mkstring(buf, flen, RJUST|LONG_DEC, MKSTR(td[i].expires)));
 
@@ -7990,7 +8006,7 @@ dump_timer_data(const ulong *cpus)
  */
 
 static void
-dump_timer_data_tvec_bases_v1(const ulong *cpus)
+dump_timer_data_tvec_bases_v1(const ulong *cpus, int eflag)
 {
 	int i, cpu, tdx, flen;
         struct timer_data *td;
@@ -8026,34 +8042,35 @@ next_cpu:
 
         init_tv_ranges(tv, vec_root_size, vec_size, cpu);
 
+	get_symbol_data("jiffies", sizeof(ulong), &jiffies);
+
         count += do_timer_list(tv[1].base + OFFSET(tvec_root_s_vec),
-                vec_root_size, vec, NULL, NULL, tv);
+                vec_root_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(tv[2].base + OFFSET(tvec_s_vec),
-                vec_size, vec, NULL, NULL, tv);
+                vec_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(tv[3].base + OFFSET(tvec_s_vec),
-                vec_size, vec, NULL, NULL, tv);
+                vec_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(tv[4].base + OFFSET(tvec_s_vec),
-                vec_size, vec, NULL, NULL, tv);
+                vec_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(tv[5].base + OFFSET(tvec_s_vec),
-                vec_size, vec, NULL, NULL, tv);
+                vec_size, vec, NULL, NULL, tv, jiffies, eflag);
 
 	if (count)
         	td = (struct timer_data *)
                 	GETBUF((count*2) * sizeof(struct timer_data));
         tdx = 0;
 	highest = 0;
-        get_symbol_data("jiffies", sizeof(ulong), &jiffies);
 
         do_timer_list(tv[1].base + OFFSET(tvec_root_s_vec),
-                vec_root_size, vec, (void *)td, &highest, tv);
+                vec_root_size, vec, (void *)td, &highest, tv, jiffies, eflag);
         do_timer_list(tv[2].base + OFFSET(tvec_s_vec),
-                vec_size, vec, (void *)td, &highest, tv);
+                vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
         do_timer_list(tv[3].base + OFFSET(tvec_s_vec),
-                vec_size, vec, (void *)td, &highest, tv);
+                vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
         do_timer_list(tv[4].base + OFFSET(tvec_s_vec),
-                vec_size, vec, (void *)td, &highest, tv);
+                vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
         tdx = do_timer_list(tv[5].base + OFFSET(tvec_s_vec),
-                vec_size, vec, (void *)td, &highest, tv);
+                vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
 
         qsort(td, tdx, sizeof(struct timer_data), compare_timer_data);
 
@@ -8110,7 +8127,7 @@ next_cpu:
  */
 
 static void
-dump_timer_data_tvec_bases_v2(const ulong *cpus)
+dump_timer_data_tvec_bases_v2(const ulong *cpus, int eflag)
 {
 	int i, cpu, tdx, flen;
         struct timer_data *td;
@@ -8168,34 +8185,35 @@ next_cpu:
 
         init_tv_ranges(tv, vec_root_size, vec_size, cpu);
 
+	get_symbol_data("jiffies", sizeof(ulong), &jiffies);
+
         count += do_timer_list(tv[1].base + OFFSET(tvec_root_s_vec),
-                vec_root_size, vec, NULL, NULL, tv);
+                vec_root_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(tv[2].base + OFFSET(tvec_s_vec),
-                vec_size, vec, NULL, NULL, tv);
+                vec_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(tv[3].base + OFFSET(tvec_s_vec),
-                vec_size, vec, NULL, NULL, tv);
+                vec_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(tv[4].base + OFFSET(tvec_s_vec),
-                vec_size, vec, NULL, NULL, tv);
+                vec_size, vec, NULL, NULL, tv, jiffies, eflag);
         count += do_timer_list(tv[5].base + OFFSET(tvec_s_vec),
-                vec_size, vec, NULL, NULL, tv);
+                vec_size, vec, NULL, NULL, tv, jiffies, eflag);
 
 	if (count)
         	td = (struct timer_data *)
                 	GETBUF((count*2) * sizeof(struct timer_data));
         tdx = 0;
 	highest = 0;
-        get_symbol_data("jiffies", sizeof(ulong), &jiffies);
 
         do_timer_list(tv[1].base + OFFSET(tvec_root_s_vec),
-                vec_root_size, vec, (void *)td, &highest, tv);
+                vec_root_size, vec, (void *)td, &highest, tv, jiffies, eflag);
         do_timer_list(tv[2].base + OFFSET(tvec_s_vec),
-                vec_size, vec, (void *)td, &highest, tv);
+                vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
         do_timer_list(tv[3].base + OFFSET(tvec_s_vec),
-                vec_size, vec, (void *)td, &highest, tv);
+                vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
         do_timer_list(tv[4].base + OFFSET(tvec_s_vec),
-                vec_size, vec, (void *)td, &highest, tv);
+                vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
         tdx = do_timer_list(tv[5].base + OFFSET(tvec_s_vec),
-                vec_size, vec, (void *)td, &highest, tv);
+                vec_size, vec, (void *)td, &highest, tv, jiffies, eflag);
 
         qsort(td, tdx, sizeof(struct timer_data), compare_timer_data);
 
@@ -8261,7 +8279,7 @@ next_cpu:
  *  Linux 4.2 timers use new tvec_root, tvec and timer_list structures
  */
 static void
-dump_timer_data_tvec_bases_v3(const ulong *cpus)
+dump_timer_data_tvec_bases_v3(const ulong *cpus, int eflag)
 {
 	int i, cpu, tdx, flen;
 	struct timer_data *td;
@@ -8313,34 +8331,35 @@ next_cpu:
 	BZERO(tv, sizeof(struct tv_range) * TVN);
 	init_tv_ranges(tv, vec_root_size, vec_size, cpu);
 
+	get_symbol_data("jiffies", sizeof(ulong), &jiffies);
+
 	count += do_timer_list_v3(tv[1].base + OFFSET(tvec_root_s_vec),
-		vec_root_size, vec, NULL, NULL);
+		vec_root_size, vec, NULL, NULL, jiffies, eflag);
 	count += do_timer_list_v3(tv[2].base + OFFSET(tvec_s_vec),
-		vec_size, vec, NULL, NULL);
+		vec_size, vec, NULL, NULL, jiffies, eflag);
 	count += do_timer_list_v3(tv[3].base + OFFSET(tvec_s_vec),
-		vec_size, vec, NULL, NULL);
+		vec_size, vec, NULL, NULL, jiffies, eflag);
 	count += do_timer_list_v3(tv[4].base + OFFSET(tvec_s_vec),
-		vec_size, vec, NULL, NULL);
+		vec_size, vec, NULL, NULL, jiffies, eflag);
 	count += do_timer_list_v3(tv[5].base + OFFSET(tvec_s_vec),
-		vec_size, vec, NULL, NULL);
+		vec_size, vec, NULL, NULL, jiffies, eflag);
 
 	if (count)
 		td = (struct timer_data *)
 			GETBUF((count*2) * sizeof(struct timer_data));
 	tdx = 0;
 	highest = 0;
-	get_symbol_data("jiffies", sizeof(ulong), &jiffies);
 
 	do_timer_list_v3(tv[1].base + OFFSET(tvec_root_s_vec),
-		vec_root_size, vec, (void *)td, &highest);
+		vec_root_size, vec, (void *)td, &highest, jiffies, eflag);
 	do_timer_list_v3(tv[2].base + OFFSET(tvec_s_vec),
-		vec_size, vec, (void *)td, &highest);
+		vec_size, vec, (void *)td, &highest, jiffies, eflag);
 	do_timer_list_v3(tv[3].base + OFFSET(tvec_s_vec),
-		vec_size, vec, (void *)td, &highest);
+		vec_size, vec, (void *)td, &highest, jiffies, eflag);
 	do_timer_list_v3(tv[4].base + OFFSET(tvec_s_vec),
-		vec_size, vec, (void *)td, &highest);
+		vec_size, vec, (void *)td, &highest, jiffies, eflag);
 	tdx = do_timer_list_v3(tv[5].base + OFFSET(tvec_s_vec),
-		vec_size, vec, (void *)td, &highest);
+		vec_size, vec, (void *)td, &highest, jiffies, eflag);
 
 	qsort(td, tdx, sizeof(struct timer_data), compare_timer_data);
 
@@ -8506,7 +8525,9 @@ do_timer_list(ulong vec_kvaddr,
 	      ulong *vec, 
 	      void *option, 
 	      ulong *highest,
-	      struct tv_range *tv)
+	      struct tv_range *tv,
+	      ulong jiffies,
+	      int eflag)
 {
 	int i, t; 
 	int count, tdx;
@@ -8577,6 +8598,9 @@ do_timer_list(ulong vec_kvaddr,
 
                                 expires = ULONG(timer_list_buf +
                                         OFFSET(timer_list_expires));
+				if (eflag && expires >= jiffies)
+					continue;
+
                                 function = ULONG(timer_list_buf +
                                         OFFSET(timer_list_function));
 
@@ -8641,6 +8665,9 @@ new_timer_list_format:
 
                         expires = ULONG(timer_list_buf + 
 				OFFSET(timer_list_expires));
+			if (eflag && expires >= jiffies)
+				continue;
+
                         function = ULONG(timer_list_buf +
                         	OFFSET(timer_list_function));
 
@@ -8666,7 +8693,9 @@ do_timer_list_v3(ulong vec_kvaddr,
 	      int size, 
 	      ulong *vec, 
 	      void *option, 
-	      ulong *highest)
+	      ulong *highest,
+	      ulong jiffies,
+	      int eflag)
 {
 	int i, t; 
 	int count, tdx;
@@ -8725,6 +8754,9 @@ do_timer_list_v3(ulong vec_kvaddr,
 
 			expires = ULONG(timer_list_buf + 
 				OFFSET(timer_list_expires));
+			if (eflag && expires >= jiffies)
+				continue;
+
 			function = ULONG(timer_list_buf +
 				OFFSET(timer_list_function));
 
@@ -8755,7 +8787,7 @@ struct timer_bases_data {
 };
 
 static int
-do_timer_list_v4(struct timer_bases_data *data)
+do_timer_list_v4(struct timer_bases_data *data, ulong jiffies, int eflag)
 {
 	int i, t, timer_cnt, found;
 	struct list_data list_data, *ld;
@@ -8810,6 +8842,9 @@ do_timer_list_v4(struct timer_bases_data *data)
 				continue;
 
 			expires = ULONG(timer_list_buf + OFFSET(timer_list_expires));
+			if (eflag && expires >= jiffies)
+				continue;
+
 			function = ULONG(timer_list_buf + OFFSET(timer_list_function));
 
 			data->timers[data->cnt].address = timer_list[t];
@@ -8839,7 +8874,7 @@ do_timer_list_v4(struct timer_bases_data *data)
  *  Linux 4.8 timers use new timer_bases[][]
  */
 static void
-dump_timer_data_timer_bases(const ulong *cpus)
+dump_timer_data_timer_bases(const ulong *cpus, int eflag)
 {
 	int i, cpu, flen, base, nr_bases, found, display, j = 0;
 	struct syment *sp;
@@ -8901,7 +8936,7 @@ next_base:
 	data.cnt = 0;
 	data.timer_base = timer_base;
 
-	found = do_timer_list_v4(&data);
+	found = do_timer_list_v4(&data, jiffies, eflag);
 	
 	qsort(data.timers, found, sizeof(struct timer_data), compare_timer_data);
 
-- 
2.22.0




More information about the Crash-utility mailing list