Browse Source

Merge branch 'c8-beta' into a8-beta

a8-beta
eabdullin 2 months ago
committed by Stepan Oksanichenko
parent
commit
19e1eadac5
  1. 2
      .crash.metadata
  2. 2
      .gitignore
  3. 70
      SOURCES/0001-Fix-pvops-Xen-detection-for-arm-machine.patch
  4. 379
      SOURCES/0001-arm64-Support-overflow-stack-panic.patch
  5. 31
      SOURCES/0001-ppc64-update-the-NR_CPUS-to-8192.patch
  6. 101
      SOURCES/0002-Handle-blk_mq_ctx-member-changes-for-kernels-5.16-rc.patch
  7. 41
      SOURCES/0002-defs.h-fix-breakage-of-compatibility-of-struct-symbo.patch
  8. 62
      SOURCES/0002-sbitmapq-remove-struct-and-member-validation-in-sbit.patch
  9. 59
      SOURCES/0003-Fix-for-timer-r-option-to-display-all-the-per-CPU-cl.patch
  10. 118
      SOURCES/0003-sbitmapq-fix-invalid-offset-for-sbitmap_queue_alloc_.patch
  11. 69
      SOURCES/0004-Fix-for-bt-v-option-to-display-the-stack-end-address.patch
  12. 103
      SOURCES/0004-sbitmapq-fix-invalid-offset-for-sbitmap_queue_round_.patch
  13. 35
      SOURCES/0005-Fix-for-HZ-calculation-on-Linux-5.14-and-later.patch
  14. 101
      SOURCES/0005-sbitmapq-fix-invalid-offset-for-sbitmap_word_depth-o.patch
  15. 40
      SOURCES/0006-memory-Handle-struct-slab-changes-on-Linux-5.17-rc1-.patch
  16. 75
      SOURCES/0007-Move-the-initialization-of-boot_date-to-task_init.patch
  17. 205
      SOURCES/0007-bt-x86_64-filter-out-idle-task-stack.patch
  18. 79
      SOURCES/0008-Remove-ptype-command-from-ps-t-option-to-reduce-memo.patch
  19. 96
      SOURCES/0008-bt-arm64-add-support-for-bt-n-idle.patch
  20. 150
      SOURCES/0009-Improve-the-ps-performance-for-vmcores-with-large-nu.patch
  21. 392
      SOURCES/0010-Enhance-dev-d-D-options-to-support-blk-mq-sbitmap.patch
  22. 59
      SOURCES/0010-arm64-Fix-segfault-by-bt-command-with-offline-cpus.patch
  23. 121
      SOURCES/0011-Fix-for-dev-d-D-options-to-support-blk-mq-change-on-.patch
  24. 89
      SOURCES/0011-Fix-for-kmem-s-S-and-bt-F-F-on-Linux-5.17-rc1.patch
  25. 43
      SOURCES/0012-Doc-update-man-page-for-the-bpf-and-sbitmapq-command.patch
  26. 48
      SOURCES/0013-sbitmapq-Fix-for-sbitmap_queue-without-ws_active-mem.patch
  27. 110
      SOURCES/0014-sbitmapq-Fix-for-sbitmap_word-without-cleared-member.patch
  28. 49
      SOURCES/0015-sbitmapq-Fix-for-sbitmap_queue-without-min_shallow_d.patch
  29. 84
      SOURCES/0016-Make-dev-d-D-options-parse-sbitmap-on-Linux-4.18-and.patch
  30. 44
      SOURCES/0017-sbitmapq-Fix-for-kernels-without-struct-wait_queue_h.patch
  31. 43
      SOURCES/0018-sbitmapq-Limit-kernels-without-sbitmap-again.patch
  32. 13
      SOURCES/lzo_snappy_zstd.patch
  33. 15
      SOURCES/rhel8_build.patch
  34. 21
      SOURCES/rhel8_freepointer.patch
  35. 47
      SPECS/crash.spec

2
.crash.metadata

@ -1,2 +1,2 @@
f230368e17058e61a0be4c22f0969bed76cd6c29 SOURCES/crash-7.3.1.tar.gz
aab889c6471bfc42cf2b1d065a881ea33d8ba0b7 SOURCES/crash-7.3.2.tar.gz
026f4c9e1c8152a2773354551c523acd32d7f00e SOURCES/gdb-7.6.tar.gz

2
.gitignore

@ -1,2 +1,2 @@
SOURCES/crash-7.3.1.tar.gz
SOURCES/crash-7.3.2.tar.gz
SOURCES/gdb-7.6.tar.gz

70
SOURCES/0001-Fix-pvops-Xen-detection-for-arm-machine.patch

@ -1,70 +0,0 @@
From 5c4f786450ea61b87d4db0092288df83dd5cb454 Mon Sep 17 00:00:00 2001
From: Qi Zheng <zhengqi.arch@bytedance.com>
Date: Tue, 21 Dec 2021 15:40:31 +0800
Subject: [PATCH 01/11] Fix pvops Xen detection for arm machine
Since the xen_start_info on the arm/arm64 platform points to a static
variable '_xen_start_info'(see its definition as below), which makes
that the address of xen_start_info will never be null.
arch/arm/xen/enlighten.c:40:static struct start_info _xen_start_info;
arch/arm/xen/enlighten.c:41:struct start_info *xen_start_info = &_xen_start_info;
arch/arm/xen/enlighten.c:42:EXPORT_SYMBOL(xen_start_info);
As a result, the is_pvops_xen() in commit 4badc6229c69 ("Fix pvops
Xen detection for kernels >= v4.20") always returns TRUE because it
can always read out the non-null address of xen_start_info, finally
the following error will be reported on arm/arm64 platform(non-Xen
environment) because p2m_mid_missing and xen_p2m_addr are not defined:
crash: cannot resolve "p2m_top"
For the arm/arm64 platform, fix it by using xen_vcpu_info instead of
xen_start_info to detect Xen dumps.
In addition, also explicitly narrow the scope of the xen_start_info
check to x86 with the machine_type(), there is no need to check it on
other architectures.
Fixes: 4badc6229c69 ("Fix pvops Xen detection for kernels >= v4.20")
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Acked-by: Kazuhito Hagio <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
kernel.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/kernel.c b/kernel.c
index 8ae9e0c169ff..a637dd0eb8f8 100644
--- a/kernel.c
+++ b/kernel.c
@@ -10754,11 +10754,21 @@ is_pvops_xen(void)
STREQ(sym, "paravirt_patch_default")))
return TRUE;
- if (symbol_exists("xen_start_info") &&
- readmem(symbol_value("xen_start_info"), KVADDR, &addr,
- sizeof(void *), "xen_start_info", RETURN_ON_ERROR) &&
- addr != 0)
- return TRUE;
+ if (machine_type("X86") || machine_type("X86_64")) {
+ if (symbol_exists("xen_start_info") &&
+ readmem(symbol_value("xen_start_info"), KVADDR, &addr,
+ sizeof(void *), "xen_start_info", RETURN_ON_ERROR) &&
+ addr != 0)
+ return TRUE;
+ }
+
+ if (machine_type("ARM") || machine_type("ARM64")) {
+ if (symbol_exists("xen_vcpu_info") &&
+ readmem(symbol_value("xen_vcpu_info"), KVADDR, &addr,
+ sizeof(void *), "xen_vcpu_info", RETURN_ON_ERROR) &&
+ addr != 0)
+ return TRUE;
+ }
return FALSE;
}
--
2.20.1

379
SOURCES/0001-arm64-Support-overflow-stack-panic.patch

@ -1,379 +0,0 @@
From c05db8d7d83389a342664073547bd29eda900158 Mon Sep 17 00:00:00 2001
From: Hong YANG <hong.yang3@nio.com>
Date: Mon, 15 Nov 2021 15:41:01 +0800
Subject: [PATCH 1/2] arm64: Support overflow stack panic
Kernel commit <872d8327ce89> ("arm64: add VMAP_STACK overflow detection")
has supported the overflow stack exception handling. Without the patch, the
"bt" command will make crash generate a core dump because of segmentation
fault. With the patch, the "bt" command can display the overflow stack.
Before:
crash> bt
PID: 3607 TASK: ffffffcbf9a4da00 CPU: 2 COMMAND: "sh"
Segmentation fault (core dumped)
After:
crash> bt
PID: 3607 TASK: ffffffcbf9a4da00 CPU: 2 COMMAND: "sh"
#0 [ffffffccbfd85f50] __delay at ffffff8008ceded8
...
#5 [ffffffccbfd85fd0] emergency_restart at ffffff80080d49fc
#6 [ffffffccbfd86140] panic at ffffff80080af4c0
#7 [ffffffccbfd86150] nmi_panic at ffffff80080af150
#8 [ffffffccbfd86190] handle_bad_stack at ffffff800808b0b8
#9 [ffffffccbfd862d0] __bad_stack at ffffff800808285c
PC: ffffff8008082e80 [el1_sync]
LR: ffffff8000d6c214 [stack_overflow_demo+84]
SP: ffffff1a79930070 PSTATE: 204003c5
X29: ffffff8011b03d00 X28: ffffffcbf9a4da00 X27: ffffff8008e02000
X26: 0000000000000040 X25: 0000000000000124 X24: ffffffcbf9a4da00
X23: 0000007daec2e288 X22: ffffffcbfe03b800 X21: 0000007daec2e288
X20: 0000000000000002 X19: 0000000000000002 X18: 0000000000000002
X17: 00000000000003e7 X16: 0000000000000000 X15: 0000000000000000
X14: ffffffcc17facb00 X13: ffffffccb4c25c00 X12: 0000000000000000
X11: ffffffcc17fad660 X10: 0000000000000af0 X9: 0000000000000000
X8: ffffff1a799334f0 X7: 0000000000000000 X6: 000000000000003f
X5: 0000000000000040 X4: 0000000000000010 X3: 00000065981d07f0
X2: 00000065981d07f0 X1: 0000000000000000 X0: ffffff1a799334f0
Signed-off-by: Hong YANG <hong.yang3@nio.com>
---
arm64.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++------
defs.h | 6 ++
2 files changed, 159 insertions(+), 16 deletions(-)
diff --git a/arm64.c b/arm64.c
index 94681d1a37db..23c3d75d85aa 100644
--- a/arm64.c
+++ b/arm64.c
@@ -45,6 +45,7 @@ static int arm64_vtop_3level_4k(ulong, ulong, physaddr_t *, int);
static int arm64_vtop_4level_4k(ulong, ulong, physaddr_t *, int);
static ulong arm64_get_task_pgd(ulong);
static void arm64_irq_stack_init(void);
+static void arm64_overflow_stack_init(void);
static void arm64_stackframe_init(void);
static int arm64_eframe_search(struct bt_info *);
static int arm64_is_kernel_exception_frame(struct bt_info *, ulong);
@@ -63,6 +64,7 @@ static int arm64_get_dumpfile_stackframe(struct bt_info *, struct arm64_stackfra
static int arm64_in_kdump_text(struct bt_info *, struct arm64_stackframe *);
static int arm64_in_kdump_text_on_irq_stack(struct bt_info *);
static int arm64_switch_stack(struct bt_info *, struct arm64_stackframe *, FILE *);
+static int arm64_switch_stack_from_overflow(struct bt_info *, struct arm64_stackframe *, FILE *);
static int arm64_get_stackframe(struct bt_info *, struct arm64_stackframe *);
static void arm64_get_stack_frame(struct bt_info *, ulong *, ulong *);
static void arm64_gen_hidden_frame(struct bt_info *bt, ulong, struct arm64_stackframe *);
@@ -78,8 +80,11 @@ static int arm64_get_smp_cpus(void);
static void arm64_clear_machdep_cache(void);
static int arm64_on_process_stack(struct bt_info *, ulong);
static int arm64_in_alternate_stack(int, ulong);
+static int arm64_in_alternate_stackv(int cpu, ulong stkptr, ulong *stacks, ulong stack_size);
static int arm64_on_irq_stack(int, ulong);
+static int arm64_on_overflow_stack(int, ulong);
static void arm64_set_irq_stack(struct bt_info *);
+static void arm64_set_overflow_stack(struct bt_info *);
static void arm64_set_process_stack(struct bt_info *);
static int arm64_get_kvaddr_ranges(struct vaddr_range *);
static void arm64_get_crash_notes(void);
@@ -463,6 +468,7 @@ arm64_init(int when)
machdep->hz = 100;
arm64_irq_stack_init();
+ arm64_overflow_stack_init();
arm64_stackframe_init();
break;
@@ -1715,6 +1721,49 @@ arm64_irq_stack_init(void)
}
}
+/*
+ * Gather Overflow stack values.
+ *
+ * Overflow stack supported since 4.14, in commit 872d8327c
+ */
+static void
+arm64_overflow_stack_init(void)
+{
+ int i;
+ struct syment *sp;
+ struct gnu_request request, *req;
+ struct machine_specific *ms = machdep->machspec;
+ req = &request;
+
+ if (symbol_exists("overflow_stack") &&
+ (sp = per_cpu_symbol_search("overflow_stack")) &&
+ get_symbol_type("overflow_stack", NULL, req)) {
+ if (CRASHDEBUG(1)) {
+ fprintf(fp, "overflow_stack: \n");
+ fprintf(fp, " type: %x, %s\n",
+ (int)req->typecode,
+ (req->typecode == TYPE_CODE_ARRAY) ?
+ "TYPE_CODE_ARRAY" : "other");
+ fprintf(fp, " target_typecode: %x, %s\n",
+ (int)req->target_typecode,
+ req->target_typecode == TYPE_CODE_INT ?
+ "TYPE_CODE_INT" : "other");
+ fprintf(fp, " target_length: %ld\n",
+ req->target_length);
+ fprintf(fp, " length: %ld\n", req->length);
+ }
+
+ if (!(ms->overflow_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong)))))
+ error(FATAL, "cannot malloc overflow_stack addresses\n");
+
+ ms->overflow_stack_size = ARM64_OVERFLOW_STACK_SIZE;
+ machdep->flags |= OVERFLOW_STACKS;
+
+ for (i = 0; i < kt->cpus; i++)
+ ms->overflow_stacks[i] = kt->__per_cpu_offset[i] + sp->value;
+ }
+}
+
/*
* Gather and verify all of the backtrace requirements.
*/
@@ -1960,6 +2009,7 @@ static char *arm64_exception_functions[] = {
"do_mem_abort",
"do_el0_irq_bp_hardening",
"do_sp_pc_abort",
+ "handle_bad_stack",
NULL
};
@@ -1978,7 +2028,10 @@ arm64_in_exception_text(ulong ptr)
if ((ptr >= ms->__exception_text_start) &&
(ptr < ms->__exception_text_end))
return TRUE;
- } else if ((name = closest_symbol(ptr))) { /* Linux 5.5 and later */
+ }
+
+ name = closest_symbol(ptr);
+ if (name != NULL) { /* Linux 5.5 and later */
for (func = &arm64_exception_functions[0]; *func; func++) {
if (STREQ(name, *func))
return TRUE;
@@ -2252,15 +2305,14 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
if ((frame->fp == 0) && (frame->pc == 0))
return FALSE;
- if (!(machdep->flags & IRQ_STACKS))
- return TRUE;
-
- if (!(machdep->flags & IRQ_STACKS))
+ if (!(machdep->flags & (IRQ_STACKS | OVERFLOW_STACKS)))
return TRUE;
if (machdep->flags & UNW_4_14) {
- if ((bt->flags & BT_IRQSTACK) &&
- !arm64_on_irq_stack(bt->tc->processor, frame->fp)) {
+ if (((bt->flags & BT_IRQSTACK) &&
+ !arm64_on_irq_stack(bt->tc->processor, frame->fp)) ||
+ ((bt->flags & BT_OVERFLOW_STACK) &&
+ !arm64_on_overflow_stack(bt->tc->processor, frame->fp))) {
if (arm64_on_process_stack(bt, frame->fp)) {
arm64_set_process_stack(bt);
@@ -2677,6 +2729,9 @@ arm64_back_trace_cmd(struct bt_info *bt)
if (arm64_on_irq_stack(bt->tc->processor, bt->frameptr)) {
arm64_set_irq_stack(bt);
bt->flags |= BT_IRQSTACK;
+ } else if (arm64_on_overflow_stack(bt->tc->processor, bt->frameptr)) {
+ arm64_set_overflow_stack(bt);
+ bt->flags |= BT_OVERFLOW_STACK;
}
stackframe.sp = bt->stkptr;
stackframe.pc = bt->instptr;
@@ -2731,7 +2786,9 @@ arm64_back_trace_cmd(struct bt_info *bt)
break;
if (arm64_in_exception_text(bt->instptr) && INSTACK(stackframe.fp, bt)) {
- if (!(bt->flags & BT_IRQSTACK) ||
+ if (bt->flags & BT_OVERFLOW_STACK) {
+ exception_frame = stackframe.fp - KERN_EFRAME_OFFSET;
+ } else if (!(bt->flags & BT_IRQSTACK) ||
((stackframe.sp + SIZE(pt_regs)) < bt->stacktop)) {
if (arm64_is_kernel_exception_frame(bt, stackframe.fp - KERN_EFRAME_OFFSET))
exception_frame = stackframe.fp - KERN_EFRAME_OFFSET;
@@ -2745,6 +2802,12 @@ arm64_back_trace_cmd(struct bt_info *bt)
break;
}
+ if ((bt->flags & BT_OVERFLOW_STACK) &&
+ !arm64_on_overflow_stack(bt->tc->processor, stackframe.fp)) {
+ bt->flags &= ~BT_OVERFLOW_STACK;
+ if (arm64_switch_stack_from_overflow(bt, &stackframe, ofp) == USER_MODE)
+ break;
+ }
level++;
}
@@ -3131,6 +3194,43 @@ arm64_switch_stack(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp
return KERNEL_MODE;
}
+static int
+arm64_switch_stack_from_overflow(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp)
+{
+ int i;
+ ulong stacktop, words, addr;
+ ulong *stackbuf;
+ char buf[BUFSIZE];
+ struct machine_specific *ms = machdep->machspec;
+
+ if (bt->flags & BT_FULL) {
+ stacktop = ms->overflow_stacks[bt->tc->processor] + ms->overflow_stack_size;
+ words = (stacktop - bt->bptr) / sizeof(ulong);
+ stackbuf = (ulong *)GETBUF(words * sizeof(ulong));
+ readmem(bt->bptr, KVADDR, stackbuf, words * sizeof(long),
+ "top of overflow stack", FAULT_ON_ERROR);
+
+ addr = bt->bptr;
+ for (i = 0; i < words; i++) {
+ if (!(i & 1))
+ fprintf(ofp, "%s %lx: ", i ? "\n" : "", addr);
+ fprintf(ofp, "%s ", format_stack_entry(bt, buf, stackbuf[i], 0));
+ addr += sizeof(ulong);
+ }
+ fprintf(ofp, "\n");
+ FREEBUF(stackbuf);
+ }
+ fprintf(ofp, "--- <Overflow stack> ---\n");
+
+ if (frame->fp == 0)
+ return USER_MODE;
+
+ if (!(machdep->flags & UNW_4_14))
+ arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
+
+ return KERNEL_MODE;
+}
+
static int
arm64_get_dumpfile_stackframe(struct bt_info *bt, struct arm64_stackframe *frame)
{
@@ -3682,6 +3782,16 @@ arm64_display_machine_stats(void)
machdep->machspec->irq_stacks[i]);
}
}
+ if (machdep->machspec->overflow_stack_size) {
+ fprintf(fp, "OVERFLOW STACK SIZE: %ld\n",
+ machdep->machspec->overflow_stack_size);
+ fprintf(fp, " OVERFLOW STACKS:\n");
+ for (i = 0; i < kt->cpus; i++) {
+ pad = (i < 10) ? 3 : (i < 100) ? 2 : (i < 1000) ? 1 : 0;
+ fprintf(fp, "%s CPU %d: %lx\n", space(pad), i,
+ machdep->machspec->overflow_stacks[i]);
+ }
+ }
}
static int
@@ -3875,24 +3985,41 @@ arm64_on_process_stack(struct bt_info *bt, ulong stkptr)
}
static int
-arm64_on_irq_stack(int cpu, ulong stkptr)
+arm64_in_alternate_stackv(int cpu, ulong stkptr, ulong *stacks, ulong stack_size)
{
- return arm64_in_alternate_stack(cpu, stkptr);
+ if ((cpu >= kt->cpus) || (stacks == NULL) || !stack_size)
+ return FALSE;
+
+ if ((stkptr >= stacks[cpu]) &&
+ (stkptr < (stacks[cpu] + stack_size)))
+ return TRUE;
+
+ return FALSE;
}
static int
arm64_in_alternate_stack(int cpu, ulong stkptr)
+{
+ return (arm64_on_irq_stack(cpu, stkptr) ||
+ arm64_on_overflow_stack(cpu, stkptr));
+}
+
+static int
+arm64_on_irq_stack(int cpu, ulong stkptr)
{
struct machine_specific *ms = machdep->machspec;
- if (!ms->irq_stack_size || (cpu >= kt->cpus))
- return FALSE;
+ return arm64_in_alternate_stackv(cpu, stkptr,
+ ms->irq_stacks, ms->irq_stack_size);
+}
- if ((stkptr >= ms->irq_stacks[cpu]) &&
- (stkptr < (ms->irq_stacks[cpu] + ms->irq_stack_size)))
- return TRUE;
+static int
+arm64_on_overflow_stack(int cpu, ulong stkptr)
+{
+ struct machine_specific *ms = machdep->machspec;
- return FALSE;
+ return arm64_in_alternate_stackv(cpu, stkptr,
+ ms->overflow_stacks, ms->overflow_stack_size);
}
static void
@@ -3905,6 +4032,16 @@ arm64_set_irq_stack(struct bt_info *bt)
alter_stackbuf(bt);
}
+static void
+arm64_set_overflow_stack(struct bt_info *bt)
+{
+ struct machine_specific *ms = machdep->machspec;
+
+ bt->stackbase = ms->overflow_stacks[bt->tc->processor];
+ bt->stacktop = bt->stackbase + ms->overflow_stack_size;
+ alter_stackbuf(bt);
+}
+
static void
arm64_set_process_stack(struct bt_info *bt)
{
diff --git a/defs.h b/defs.h
index 43eff46b105d..caaa11e50c87 100644
--- a/defs.h
+++ b/defs.h
@@ -3218,6 +3218,7 @@ typedef signed int s32;
#define UNW_4_14 (0x200)
#define FLIPPED_VM (0x400)
#define HAS_PHYSVIRT_OFFSET (0x800)
+#define OVERFLOW_STACKS (0x1000)
/*
* Get kimage_voffset from /dev/crash
@@ -3260,6 +3261,7 @@ typedef signed int s32;
#define ARM64_STACK_SIZE (16384)
#define ARM64_IRQ_STACK_SIZE ARM64_STACK_SIZE
+#define ARM64_OVERFLOW_STACK_SIZE (4096)
#define _SECTION_SIZE_BITS 30
#define _SECTION_SIZE_BITS_5_12 27
@@ -3332,6 +3334,9 @@ struct machine_specific {
char *irq_stackbuf;
ulong __irqentry_text_start;
ulong __irqentry_text_end;
+ ulong overflow_stack_size;
+ ulong *overflow_stacks;
+ char *overflow_stackbuf;
/* for exception vector code */
ulong exp_entry1_start;
ulong exp_entry1_end;
@@ -5778,6 +5783,7 @@ ulong cpu_map_addr(const char *type);
#define BT_CPUMASK (0x1000000000000ULL)
#define BT_SHOW_ALL_REGS (0x2000000000000ULL)
#define BT_REGS_NOT_FOUND (0x4000000000000ULL)
+#define BT_OVERFLOW_STACK (0x8000000000000ULL)
#define BT_SYMBOL_OFFSET (BT_SYMBOLIC_ARGS)
#define BT_REF_HEXVAL (0x1)
--
2.30.2

31
SOURCES/0001-ppc64-update-the-NR_CPUS-to-8192.patch

@ -0,0 +1,31 @@
From ae52398a13fa9a238279114ed671c7c514c154ee Mon Sep 17 00:00:00 2001
From: Sourabh Jain <sourabhjain@linux.ibm.com>
Date: Mon, 9 May 2022 12:49:56 +0530
Subject: [PATCH 01/18] ppc64: update the NR_CPUS to 8192
Since the kernel commit 2d8ae638bb86 ("powerpc: Make the NR_CPUS max 8192")
the NR_CPUS on Linux kernel ranges from 1-8192. So let's match NR_CPUS with
the max NR_CPUS count on the Linux kernel.
Signed-off-by: Sourabh Jain <sourabhjain@linux.ibm.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
defs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/defs.h b/defs.h
index 1e8360d65a3b..a6735d07b32f 100644
--- a/defs.h
+++ b/defs.h
@@ -136,7 +136,7 @@
#define NR_CPUS (4096)
#endif
#ifdef PPC64
-#define NR_CPUS (2048)
+#define NR_CPUS (8192)
#endif
#ifdef S390
#define NR_CPUS (512)
--
2.30.2

101
SOURCES/0002-Handle-blk_mq_ctx-member-changes-for-kernels-5.16-rc.patch

@ -1,101 +0,0 @@
From 78255e3b33f8d51eb893e662dd1b05a008246b9d Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Fri, 24 Dec 2021 18:56:35 +0800
Subject: [PATCH 02/11] Handle blk_mq_ctx member changes for kernels 5.16-rc1
and later
Kernel commit 9a14d6ce4135 ("block: remove debugfs blk_mq_ctx
dispatched/merged/completed attributes") removed the member
rq_dispatched and rq_completed from struct blk_mq_ctx. Without
the patch, "dev -d|-D" options will fail with the following error:
crash> dev -d
MAJOR GENDISK NAME REQUEST_QUEUE TOTAL ASYNC SYNC
dev: invalid structure member offset: blk_mq_ctx_rq_dispatched
FILE: dev.c LINE: 4229 FUNCTION: get_one_mctx_diskio()
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
---
dev.c | 57 +++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 39 insertions(+), 18 deletions(-)
diff --git a/dev.c b/dev.c
index effe789f38d8..a493e51ac95c 100644
--- a/dev.c
+++ b/dev.c
@@ -4246,6 +4246,10 @@ get_mq_diskio(unsigned long q, unsigned long *mq_count)
unsigned long mctx_addr;
struct diskio tmp;
+ if (INVALID_MEMBER(blk_mq_ctx_rq_dispatched) ||
+ INVALID_MEMBER(blk_mq_ctx_rq_completed))
+ return;
+
memset(&tmp, 0x00, sizeof(struct diskio));
readmem(q + OFFSET(request_queue_queue_ctx), KVADDR, &queue_ctx,
@@ -4475,24 +4479,41 @@ display_one_diskio(struct iter *i, unsigned long gendisk, ulong flags)
&& (io.read + io.write == 0))
return;
- fprintf(fp, "%s%s%s %s%s%s%s %s%5d%s%s%s%s%s",
- mkstring(buf0, 5, RJUST|INT_DEC, (char *)(unsigned long)major),
- space(MINSPACE),
- mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, (char *)gendisk),
- space(MINSPACE),
- mkstring(buf2, 10, LJUST, disk_name),
- space(MINSPACE),
- mkstring(buf3, VADDR_PRLEN <= 11 ? 11 : VADDR_PRLEN,
- LJUST|LONG_HEX, (char *)queue_addr),
- space(MINSPACE),
- io.read + io.write,
- space(MINSPACE),
- mkstring(buf4, 5, RJUST|INT_DEC,
- (char *)(unsigned long)io.read),
- space(MINSPACE),
- mkstring(buf5, 5, RJUST|INT_DEC,
- (char *)(unsigned long)io.write),
- space(MINSPACE));
+ if (use_mq_interface(queue_addr) &&
+ (INVALID_MEMBER(blk_mq_ctx_rq_dispatched) ||
+ INVALID_MEMBER(blk_mq_ctx_rq_completed)))
+ fprintf(fp, "%s%s%s %s%s%s%s %s%s%s",
+ mkstring(buf0, 5, RJUST|INT_DEC, (char *)(unsigned long)major),
+ space(MINSPACE),
+ mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, (char *)gendisk),
+ space(MINSPACE),
+ mkstring(buf2, 10, LJUST, disk_name),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN <= 11 ? 11 : VADDR_PRLEN,
+ LJUST|LONG_HEX, (char *)queue_addr),
+ space(MINSPACE),
+ mkstring(buf4, 17, RJUST, "(not supported)"),
+ space(MINSPACE));
+
+ else
+ fprintf(fp, "%s%s%s %s%s%s%s %s%5d%s%s%s%s%s",
+ mkstring(buf0, 5, RJUST|INT_DEC, (char *)(unsigned long)major),
+ space(MINSPACE),
+ mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, (char *)gendisk),
+ space(MINSPACE),
+ mkstring(buf2, 10, LJUST, disk_name),
+ space(MINSPACE),
+ mkstring(buf3, VADDR_PRLEN <= 11 ? 11 : VADDR_PRLEN,
+ LJUST|LONG_HEX, (char *)queue_addr),
+ space(MINSPACE),
+ io.read + io.write,
+ space(MINSPACE),
+ mkstring(buf4, 5, RJUST|INT_DEC,
+ (char *)(unsigned long)io.read),
+ space(MINSPACE),
+ mkstring(buf5, 5, RJUST|INT_DEC,
+ (char *)(unsigned long)io.write),
+ space(MINSPACE));
if (VALID_MEMBER(request_queue_in_flight)) {
if (!use_mq_interface(queue_addr)) {
--
2.20.1

41
SOURCES/0002-defs.h-fix-breakage-of-compatibility-of-struct-symbo.patch

@ -1,41 +0,0 @@
From a0eec39c14ee1db95a6c1a649a8f69b97e260dc6 Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
Date: Wed, 8 Dec 2021 12:07:34 +0000
Subject: [PATCH 2/2] defs.h: fix breakage of compatibility of struct
symbol_table_data for extension modules
Commit <3ab39203ddd9> ("symbols: Implement install and remove operations
for mod_symname_hash") added new member variable mod_symname_hash in the
middle of struct symbol_table_date, which breaks compatibility of struct
symbol_table_data for extension modules. As the result, crash trace command
results in segmentation fault.
Fixes: 3ab39203ddd9 ("symbols: Implement install and remove operations for mod_symname_hash")
Signed-off-by: HATAYAMA Daisuke <d.hatayama@fujitsu.com>
---
defs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/defs.h b/defs.h
index caaa11e50c87..41b6cbc6cc85 100644
--- a/defs.h
+++ b/defs.h
@@ -2753,7 +2753,6 @@ struct symbol_table_data {
double val_hash_searches;
double val_hash_iterations;
struct syment *symname_hash[SYMNAME_HASH];
- struct syment *mod_symname_hash[SYMNAME_HASH];
struct symbol_namespace kernel_namespace;
struct syment *ext_module_symtable;
struct syment *ext_module_symend;
@@ -2780,6 +2779,7 @@ struct symbol_table_data {
ulong kaiser_init_vmlinux;
int kernel_symbol_type;
ulong linux_banner_vmlinux;
+ struct syment *mod_symname_hash[SYMNAME_HASH];
};
/* flags for st */
--
2.30.2

62
SOURCES/0002-sbitmapq-remove-struct-and-member-validation-in-sbit.patch

@ -0,0 +1,62 @@
From 364b2e413c69daf189d2bc0238e3ba9b0dcbd937 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 23 May 2022 18:04:13 +0800
Subject: [PATCH 02/18] sbitmapq: remove struct and member validation in
sbitmapq_init()
Let's remove the struct and member validation from sbitmapq_init(), which
will help the crash to display the actual error when the sbitmapq fails.
Without the patch:
crash> sbitmapq ffff8e99d0dc8010
sbitmapq: command not supported or applicable on this architecture or kernel
With the patch:
crash> sbitmapq ffff8e99d0dc8010
sbitmapq: invalid structure member offset: sbitmap_queue_alloc_hint
FILE: sbitmap.c LINE: 365 FUNCTION: sbitmap_queue_context_load()
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
sbitmap.c | 24 ------------------------
1 file changed, 24 deletions(-)
diff --git a/sbitmap.c b/sbitmap.c
index 96a61e6c2c71..7693eef6cebd 100644
--- a/sbitmap.c
+++ b/sbitmap.c
@@ -525,30 +525,6 @@ void sbitmapq_init(void)
MEMBER_OFFSET_INIT(sbq_wait_state_wait_cnt, "sbq_wait_state", "wait_cnt");
MEMBER_OFFSET_INIT(sbq_wait_state_wait, "sbq_wait_state", "wait");
- if (!VALID_SIZE(sbitmap_word) ||
- !VALID_SIZE(sbitmap) ||
- !VALID_SIZE(sbitmap_queue) ||
- !VALID_SIZE(sbq_wait_state) ||
- INVALID_MEMBER(sbitmap_word_depth) ||
- INVALID_MEMBER(sbitmap_word_word) ||
- INVALID_MEMBER(sbitmap_word_cleared) ||
- INVALID_MEMBER(sbitmap_depth) ||
- INVALID_MEMBER(sbitmap_shift) ||
- INVALID_MEMBER(sbitmap_map_nr) ||
- INVALID_MEMBER(sbitmap_map) ||
- INVALID_MEMBER(sbitmap_queue_sb) ||
- INVALID_MEMBER(sbitmap_queue_alloc_hint) ||
- INVALID_MEMBER(sbitmap_queue_wake_batch) ||
- INVALID_MEMBER(sbitmap_queue_wake_index) ||
- INVALID_MEMBER(sbitmap_queue_ws) ||
- INVALID_MEMBER(sbitmap_queue_ws_active) ||
- INVALID_MEMBER(sbitmap_queue_round_robin) ||
- INVALID_MEMBER(sbitmap_queue_min_shallow_depth) ||
- INVALID_MEMBER(sbq_wait_state_wait_cnt) ||
- INVALID_MEMBER(sbq_wait_state_wait)) {
- command_not_supported();
- }
-
sb_flags |= SB_FLAG_INIT;
}
--
2.30.2

59
SOURCES/0003-Fix-for-timer-r-option-to-display-all-the-per-CPU-cl.patch

@ -1,59 +0,0 @@
From c48177972f351d7853abb2a57709628c75ee38bc Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Thu, 6 Jan 2022 22:34:26 +0800
Subject: [PATCH 03/11] Fix for "timer -r" option to display all the per-CPU
clocks
Currently, the hrtimer_max_clock_bases is hard-coded to 3, which
makes that crash only prints three clocks, and the rest of clocks
are not displayed.
Without the patch:
crash> timer -r -C 11
CPU: 11 HRTIMER_CPU_BASE: ffff9a775f95ee00
CLOCK: 0 HRTIMER_CLOCK_BASE: ffff9a775f95ee80 [ktime_get]
(empty)
CLOCK: 1 HRTIMER_CLOCK_BASE: ffff9a775f95ef00 [ktime_get_real]
(empty)
CLOCK: 2 HRTIMER_CLOCK_BASE: ffff9a775f95ef80 [ktime_get_boottime]
(empty)
With the patch:
crash> timer -r -C 11
CPU: 11 HRTIMER_CPU_BASE: ffff9a775f95ee00
CLOCK: 0 HRTIMER_CLOCK_BASE: ffff9a775f95ee80 [ktime_get]
(empty)
CLOCK: 1 HRTIMER_CLOCK_BASE: ffff9a775f95ef00 [ktime_get_real]
(empty)
CLOCK: 2 HRTIMER_CLOCK_BASE: ffff9a775f95ef80 [ktime_get_boottime]
(empty)
...
CLOCK: 7 HRTIMER_CLOCK_BASE: ffff9a775f95f200 [ktime_get_clocktai]
(empty)
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
kernel.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel.c b/kernel.c
index a637dd0eb8f8..a44a9c52ace0 100644
--- a/kernel.c
+++ b/kernel.c
@@ -7672,7 +7672,8 @@ dump_hrtimer_data(const ulong *cpus)
if (VALID_STRUCT(hrtimer_clock_base)) {
hrtimer_max_clock_bases = 2;
if (symbol_exists("ktime_get_boottime"))
- hrtimer_max_clock_bases = 3;
+ hrtimer_max_clock_bases = MEMBER_SIZE("hrtimer_cpu_base", "clock_base") /
+ SIZE(hrtimer_clock_base);
} else if (VALID_STRUCT(hrtimer_base)) {
max_hrtimer_bases = 2;
} else
--
2.20.1

118
SOURCES/0003-sbitmapq-fix-invalid-offset-for-sbitmap_queue_alloc_.patch

@ -0,0 +1,118 @@
From a295cb40cd5d24fb5995cc78d29c5def3843d285 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 23 May 2022 18:04:14 +0800
Subject: [PATCH 03/18] sbitmapq: fix invalid offset for
"sbitmap_queue_alloc_hint" on Linux v5.13-rc1
Kernel commit c548e62bcf6a ("scsi: sbitmap: Move allocation hint
into sbitmap") moved the alloc_hint member from struct sbitmap_queue
to struct sbitmap. Without the patch, the sbitmapq will fail:
crash> sbitmapq 0xffff8e99d0dc8010
sbitmapq: invalid structure member offset: sbitmap_queue_alloc_hint
FILE: sbitmap.c LINE: 365 FUNCTION: sbitmap_queue_context_load()
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
defs.h | 2 ++
sbitmap.c | 14 ++++++++++++--
symbols.c | 2 ++
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index a6735d07b32f..0aeb98c4f654 100644
--- a/defs.h
+++ b/defs.h
@@ -2168,6 +2168,7 @@ struct offset_table { /* stash of commonly-used offsets */
long sbitmap_queue_min_shallow_depth;
long sbq_wait_state_wait_cnt;
long sbq_wait_state_wait;
+ long sbitmap_alloc_hint;
};
struct size_table { /* stash of commonly-used sizes */
@@ -5907,6 +5908,7 @@ struct sbitmap_context {
unsigned shift;
unsigned map_nr;
ulong map_addr;
+ ulong alloc_hint;
};
typedef bool (*sbitmap_for_each_fn)(unsigned int idx, void *p);
diff --git a/sbitmap.c b/sbitmap.c
index 7693eef6cebd..2921d5447c65 100644
--- a/sbitmap.c
+++ b/sbitmap.c
@@ -285,6 +285,7 @@ void sbitmap_for_each_set(const struct sbitmap_context *sc,
static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
const struct sbitmap_context *sc)
{
+ ulong alloc_hint_addr = 0;
int cpus = get_cpus_possible();
int sbq_wait_state_size, wait_cnt_off, wait_off, list_head_off;
char *sbq_wait_state_buf;
@@ -297,6 +298,11 @@ static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
fprintf(fp, "bits_per_word = %u\n", 1U << sc->shift);
fprintf(fp, "map_nr = %u\n", sc->map_nr);
+ if (VALID_MEMBER(sbitmap_queue_alloc_hint))
+ alloc_hint_addr = sqc->alloc_hint;
+ else if (VALID_MEMBER(sbitmap_alloc_hint)) /* 5.13 and later */
+ alloc_hint_addr = sc->alloc_hint;
+
fputs("alloc_hint = {", fp);
first = true;
for (i = 0; i < cpus; i++) {
@@ -307,7 +313,7 @@ static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
fprintf(fp, ", ");
first = false;
- ptr = kt->__per_cpu_offset[i] + sqc->alloc_hint;
+ ptr = kt->__per_cpu_offset[i] + alloc_hint_addr;
readmem(ptr, KVADDR, &val, sizeof(val), "alloc_hint", FAULT_ON_ERROR);
fprintf(fp, "%u", val);
@@ -362,7 +368,8 @@ static void sbitmap_queue_context_load(ulong addr, struct sbitmap_queue_context
error(FATAL, "cannot read sbitmap_queue\n");
}
- sqc->alloc_hint = ULONG(sbitmap_queue_buf + OFFSET(sbitmap_queue_alloc_hint));
+ if (VALID_MEMBER(sbitmap_queue_alloc_hint))
+ sqc->alloc_hint = ULONG(sbitmap_queue_buf + OFFSET(sbitmap_queue_alloc_hint));
sqc->wake_batch = UINT(sbitmap_queue_buf + OFFSET(sbitmap_queue_wake_batch));
sqc->wake_index = INT(sbitmap_queue_buf + OFFSET(sbitmap_queue_wake_index));
sqc->ws_addr = ULONG(sbitmap_queue_buf + OFFSET(sbitmap_queue_ws));
@@ -387,6 +394,8 @@ void sbitmap_context_load(ulong addr, struct sbitmap_context *sc)
sc->shift = UINT(sbitmap_buf + OFFSET(sbitmap_shift));
sc->map_nr = UINT(sbitmap_buf + OFFSET(sbitmap_map_nr));
sc->map_addr = ULONG(sbitmap_buf + OFFSET(sbitmap_map));
+ if (VALID_MEMBER(sbitmap_alloc_hint))
+ sc->alloc_hint = ULONG(sbitmap_buf + OFFSET(sbitmap_alloc_hint));
FREEBUF(sbitmap_buf);
}
@@ -512,6 +521,7 @@ void sbitmapq_init(void)
MEMBER_OFFSET_INIT(sbitmap_shift, "sbitmap", "shift");
MEMBER_OFFSET_INIT(sbitmap_map_nr, "sbitmap", "map_nr");
MEMBER_OFFSET_INIT(sbitmap_map, "sbitmap", "map");
+ MEMBER_OFFSET_INIT(sbitmap_alloc_hint, "sbitmap", "alloc_hint");
MEMBER_OFFSET_INIT(sbitmap_queue_sb, "sbitmap_queue", "sb");
MEMBER_OFFSET_INIT(sbitmap_queue_alloc_hint, "sbitmap_queue", "alloc_hint");
diff --git a/symbols.c b/symbols.c
index ba5e2741347d..fd0eb06899f0 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10708,6 +10708,8 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(sbitmap_map_nr));
fprintf(fp, " sbitmap_map: %ld\n",
OFFSET(sbitmap_map));
+ fprintf(fp, " sbitmap_alloc_hint: %ld\n",
+ OFFSET(sbitmap_alloc_hint));
fprintf(fp, " sbitmap_queue_sb: %ld\n",
OFFSET(sbitmap_queue_sb));
fprintf(fp, " sbitmap_queue_alloc_hint: %ld\n",
--
2.30.2

69
SOURCES/0004-Fix-for-bt-v-option-to-display-the-stack-end-address.patch

@ -1,69 +0,0 @@
From 1706f8b6ab50cd25e8fdabe8d50a37ce89bd60e0 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Thu, 6 Jan 2022 12:01:17 +0800
Subject: [PATCH 04/11] Fix for "bt -v" option to display the stack-end address
correctly
The "bt -v" command prints incorrect stack-end address when the
"CONFIG_THREAD_INFO_IN_TASK=y" is enabled in kernel, the "bt -v"
command output shows that the value stored at 0xffff8dee0312c198
is 0xffffffffc076400a, however, the value stored actually at
0xffff8dee0312c198 is NULL(0x0000000000000000), the stack-end
address is incorrect.
Without the patch:
crash> bt -v
PID: 28642 TASK: ffff8dee0312c180 CPU: 0 COMMAND: "insmod"
possible stack overflow: ffff8dee0312c198: ffffffffc076400a != STACK_END_MAGIC
^^^^^^^^^^^^^^^^
crash> rd 0xffff8dee0312c198
ffff8dee0312c198: 0000000000000000 ........
^^^^^^^^^^^^^^^^
With the patch:
crash> bt -v
PID: 28642 TASK: ffff8dee0312c180 CPU: 0 COMMAND: "insmod"
possible stack overflow: ffff991340bc0000: ffffffffc076400a != STACK_END_MAGIC
crash> rd 0xffff991340bc0000
ffff991340bc0000: ffffffffc076400a .@v.....
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
task.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/task.c b/task.c
index bb6a5da8ad33..b5ddc88e0acb 100644
--- a/task.c
+++ b/task.c
@@ -11202,7 +11202,7 @@ check_stack_overflow(void)
{
int i, overflow, cpu_size, cpu, total;
char buf[BUFSIZE];
- ulong magic, task, stackbase;
+ ulong magic, task, stackbase, location;
struct task_context *tc;
if (!tt->stack_end_magic &&
@@ -11286,9 +11286,15 @@ check_stack_end_magic:
if (magic != STACK_END_MAGIC) {
if (!overflow)
print_task_header(fp, tc, 0);
+
+ if (tt->flags & THREAD_INFO_IN_TASK)
+ location = task_to_stackbase(tc->task);
+ else
+ location = tc->thread_info + SIZE(thread_info);
+
fprintf(fp,
" possible stack overflow: %lx: %lx != STACK_END_MAGIC\n",
- tc->thread_info + SIZE(thread_info), magic);
+ location, magic);
overflow++, total++;
}
--
2.20.1

103
SOURCES/0004-sbitmapq-fix-invalid-offset-for-sbitmap_queue_round_.patch

@ -0,0 +1,103 @@
From 530fe6ad7e4d7ff6254596c1219d25ed929e3867 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 23 May 2022 18:04:15 +0800
Subject: [PATCH 04/18] sbitmapq: fix invalid offset for
"sbitmap_queue_round_robin" on Linux v5.13-rc1
Kernel commit efe1f3a1d583 ("scsi: sbitmap: Maintain allocation
round_robin in sbitmap") moved the round_robin member from struct
sbitmap_queue to struct sbitmap. Without the patch, the sbitmapq
will fail:
crash> sbitmapq 0xffff8e99d0dc8010
sbitmapq: invalid structure member offset: sbitmap_queue_round_robin
FILE: sbitmap.c LINE: 378 FUNCTION: sbitmap_queue_context_load()
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
defs.h | 2 ++
sbitmap.c | 12 ++++++++++--
symbols.c | 2 ++
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index 0aeb98c4f654..ecbced24d2e3 100644
--- a/defs.h
+++ b/defs.h
@@ -2169,6 +2169,7 @@ struct offset_table { /* stash of commonly-used offsets */
long sbq_wait_state_wait_cnt;
long sbq_wait_state_wait;
long sbitmap_alloc_hint;
+ long sbitmap_round_robin;
};
struct size_table { /* stash of commonly-used sizes */
@@ -5909,6 +5910,7 @@ struct sbitmap_context {
unsigned map_nr;
ulong map_addr;
ulong alloc_hint;
+ bool round_robin;
};
typedef bool (*sbitmap_for_each_fn)(unsigned int idx, void *p);
diff --git a/sbitmap.c b/sbitmap.c
index 2921d5447c65..7b318b533702 100644
--- a/sbitmap.c
+++ b/sbitmap.c
@@ -352,7 +352,11 @@ static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
FREEBUF(sbq_wait_state_buf);
- fprintf(fp, "round_robin = %d\n", sqc->round_robin);
+ if (VALID_MEMBER(sbitmap_queue_round_robin))
+ fprintf(fp, "round_robin = %d\n", sqc->round_robin);
+ else if (VALID_MEMBER(sbitmap_round_robin)) /* 5.13 and later */
+ fprintf(fp, "round_robin = %d\n", sc->round_robin);
+
fprintf(fp, "min_shallow_depth = %u\n", sqc->min_shallow_depth);
}
@@ -374,7 +378,8 @@ static void sbitmap_queue_context_load(ulong addr, struct sbitmap_queue_context
sqc->wake_index = INT(sbitmap_queue_buf + OFFSET(sbitmap_queue_wake_index));
sqc->ws_addr = ULONG(sbitmap_queue_buf + OFFSET(sbitmap_queue_ws));
sqc->ws_active = INT(sbitmap_queue_buf + OFFSET(sbitmap_queue_ws_active));
- sqc->round_robin = BOOL(sbitmap_queue_buf + OFFSET(sbitmap_queue_round_robin));
+ if (VALID_MEMBER(sbitmap_queue_round_robin))
+ sqc->round_robin = BOOL(sbitmap_queue_buf + OFFSET(sbitmap_queue_round_robin));
sqc->min_shallow_depth = UINT(sbitmap_queue_buf + OFFSET(sbitmap_queue_min_shallow_depth));
FREEBUF(sbitmap_queue_buf);
@@ -396,6 +401,8 @@ void sbitmap_context_load(ulong addr, struct sbitmap_context *sc)
sc->map_addr = ULONG(sbitmap_buf + OFFSET(sbitmap_map));
if (VALID_MEMBER(sbitmap_alloc_hint))
sc->alloc_hint = ULONG(sbitmap_buf + OFFSET(sbitmap_alloc_hint));
+ if (VALID_MEMBER(sbitmap_round_robin))
+ sc->round_robin = BOOL(sbitmap_buf + OFFSET(sbitmap_round_robin));
FREEBUF(sbitmap_buf);
}
@@ -522,6 +529,7 @@ void sbitmapq_init(void)
MEMBER_OFFSET_INIT(sbitmap_map_nr, "sbitmap", "map_nr");
MEMBER_OFFSET_INIT(sbitmap_map, "sbitmap", "map");
MEMBER_OFFSET_INIT(sbitmap_alloc_hint, "sbitmap", "alloc_hint");
+ MEMBER_OFFSET_INIT(sbitmap_round_robin, "sbitmap", "round_robin");
MEMBER_OFFSET_INIT(sbitmap_queue_sb, "sbitmap_queue", "sb");
MEMBER_OFFSET_INIT(sbitmap_queue_alloc_hint, "sbitmap_queue", "alloc_hint");
diff --git a/symbols.c b/symbols.c
index fd0eb06899f0..5d12a021c769 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10710,6 +10710,8 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(sbitmap_map));
fprintf(fp, " sbitmap_alloc_hint: %ld\n",
OFFSET(sbitmap_alloc_hint));
+ fprintf(fp, " sbitmap_round_robin: %ld\n",
+ OFFSET(sbitmap_round_robin));
fprintf(fp, " sbitmap_queue_sb: %ld\n",
OFFSET(sbitmap_queue_sb));
fprintf(fp, " sbitmap_queue_alloc_hint: %ld\n",
--
2.30.2

35
SOURCES/0005-Fix-for-HZ-calculation-on-Linux-5.14-and-later.patch

@ -1,35 +0,0 @@
From f5637f341533ef2b28e2d6a6b12fcfb00d0fff2d Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 10 Jan 2022 17:25:06 +0800
Subject: [PATCH 05/11] Fix for HZ calculation on Linux 5.14 and later
Kernel commit 3e9a99eba058 ("block/mq-deadline: Rename dd_init_queue()
and dd_exit_queue()") renamed dd_init_queue to dd_init_sched. Without
the patch, the 'help -m' may print incorrect hz value as follows:
crash> help -m | grep hz
hz: 1000 <---The correct hz value on ppc64le machine is 100.
^^^^
Fixes: b93027ce5c75 ("Add alternate HZ calculation using write_expire")
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
task.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/task.c b/task.c
index b5ddc88e0acb..76e184ae70b1 100644
--- a/task.c
+++ b/task.c
@@ -440,6 +440,8 @@ task_init(void)
}
} else if ((symbol_exists("dd_init_queue") &&
gdb_set_crash_scope(symbol_value("dd_init_queue"), "dd_init_queue")) ||
+ (symbol_exists("dd_init_sched") &&
+ gdb_set_crash_scope(symbol_value("dd_init_sched"), "dd_init_sched")) ||
(symbol_exists("deadline_init_queue") &&
gdb_set_crash_scope(symbol_value("deadline_init_queue"), "deadline_init_queue"))) {
char buf[BUFSIZE];
--
2.20.1

101
SOURCES/0005-sbitmapq-fix-invalid-offset-for-sbitmap_word_depth-o.patch

@ -0,0 +1,101 @@
From 3750803f6ae5f5ad071f86ca916dbbb17b7a83a5 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 23 May 2022 18:04:16 +0800
Subject: [PATCH 05/18] sbitmapq: fix invalid offset for "sbitmap_word_depth"
on Linux v5.18-rc1
Kernel commit 3301bc53358a ("lib/sbitmap: kill 'depth' from sbitmap_word")
removed the depth member from struct sbitmap_word. Without the patch, the
sbitmapq will fail:
crash> sbitmapq 0xffff8e99d0dc8010
sbitmapq: invalid structure member offset: sbitmap_word_depth
FILE: sbitmap.c LINE: 84 FUNCTION: __sbitmap_weight()
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
sbitmap.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/sbitmap.c b/sbitmap.c
index 7b318b533702..e8ebd62fe01c 100644
--- a/sbitmap.c
+++ b/sbitmap.c
@@ -78,10 +78,16 @@ static unsigned long bitmap_weight(unsigned long bitmap, unsigned int bits)
return w;
}
+static inline unsigned int __map_depth(const struct sbitmap_context *sc, int index)
+{
+ if (index == sc->map_nr - 1)
+ return sc->depth - (index << sc->shift);
+ return 1U << sc->shift;
+}
+
static unsigned int __sbitmap_weight(const struct sbitmap_context *sc, bool set)
{
const ulong sbitmap_word_size = SIZE(sbitmap_word);
- const ulong w_depth_off = OFFSET(sbitmap_word_depth);
const ulong w_word_off = OFFSET(sbitmap_word_word);
const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
@@ -99,7 +105,7 @@ static unsigned int __sbitmap_weight(const struct sbitmap_context *sc, bool set)
error(FATAL, "cannot read sbitmap_word\n");
}
- depth = ULONG(sbitmap_word_buf + w_depth_off);
+ depth = __map_depth(sc, i);
if (set) {
word = ULONG(sbitmap_word_buf + w_word_off);
@@ -142,7 +148,6 @@ static void sbitmap_emit_byte(unsigned int offset, uint8_t byte)
static void sbitmap_bitmap_show(const struct sbitmap_context *sc)
{
const ulong sbitmap_word_size = SIZE(sbitmap_word);
- const ulong w_depth_off = OFFSET(sbitmap_word_depth);
const ulong w_word_off = OFFSET(sbitmap_word_word);
const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
@@ -165,7 +170,7 @@ static void sbitmap_bitmap_show(const struct sbitmap_context *sc)
word = ULONG(sbitmap_word_buf + w_word_off);
cleared = ULONG(sbitmap_word_buf + w_cleared_off);
- word_bits = ULONG(sbitmap_word_buf + w_depth_off);
+ word_bits = __map_depth(sc, i);
word &= ~cleared;
@@ -213,7 +218,6 @@ static void __sbitmap_for_each_set(const struct sbitmap_context *sc,
unsigned int start, sbitmap_for_each_fn fn, void *data)
{
const ulong sbitmap_word_size = SIZE(sbitmap_word);
- const ulong w_depth_off = OFFSET(sbitmap_word_depth);
const ulong w_word_off = OFFSET(sbitmap_word_word);
const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
@@ -232,7 +236,7 @@ static void __sbitmap_for_each_set(const struct sbitmap_context *sc,
while (scanned < sc->depth) {
unsigned long w_addr = sc->map_addr + (sbitmap_word_size * index);
- unsigned long w_depth, w_word, w_cleared;
+ unsigned long w_word, w_cleared;
unsigned long word, depth;
if (!readmem(w_addr, KVADDR, sbitmap_word_buf, sbitmap_word_size, "sbitmap_word", RETURN_ON_ERROR)) {
@@ -240,11 +244,10 @@ static void __sbitmap_for_each_set(const struct sbitmap_context *sc,
error(FATAL, "cannot read sbitmap_word\n");
}
- w_depth = ULONG(sbitmap_word_buf + w_depth_off);
w_word = ULONG(sbitmap_word_buf + w_word_off);
w_cleared = ULONG(sbitmap_word_buf + w_cleared_off);
- depth = min(w_depth - nr, sc->depth - scanned);
+ depth = min(__map_depth(sc, index) - nr, sc->depth - scanned);
scanned += depth;
word = w_word & ~w_cleared;
--
2.30.2

40
SOURCES/0006-memory-Handle-struct-slab-changes-on-Linux-5.17-rc1-.patch

@ -1,40 +0,0 @@
From a392b27653e4e75460753522af0f006006b4dc4e Mon Sep 17 00:00:00 2001
From: Alexander Egorenkov <egorenar@linux.ibm.com>
Date: Mon, 6 Dec 2021 16:04:19 +0100
Subject: [PATCH 06/11] memory: Handle struct slab changes on Linux 5.17-rc1
and later
Since kernel commit d122019bf061 ("mm: Split slab into its own type"),
the struct slab is used for both SLAB and SLUB. Therefore, don't depend
on the non-presence of the struct slab to decide whether SLAB implementation
should be chosen and use the member variable "cpu_slab" of the struct
kmem_cache instead, it should be present only in SLUB.
Without the patch, crash fails to start with the error message:
crash: invalid structure member offset: kmem_cache_s_num
FILE: memory.c LINE: 9619 FUNCTION: kmem_cache_init()
Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
memory.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/memory.c b/memory.c
index 86c02c132890..5af45fd7d834 100644
--- a/memory.c
+++ b/memory.c
@@ -576,7 +576,8 @@ vm_init(void)
STRUCT_SIZE_INIT(cpucache_s, "cpucache_s");
} else if (!VALID_STRUCT(kmem_slab_s) &&
- !VALID_STRUCT(slab_s) &&
+ !VALID_STRUCT(slab_s) &&
+ !MEMBER_EXISTS("kmem_cache", "cpu_slab") &&
(VALID_STRUCT(slab) || (vt->flags & SLAB_OVERLOAD_PAGE))) {
vt->flags |= PERCPU_KMALLOC_V2;
--
2.20.1

75
SOURCES/0007-Move-the-initialization-of-boot_date-to-task_init.patch

@ -1,75 +0,0 @@
From fa0b6453a05c5600849e4e531c94594ed9c90270 Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Mon, 17 Jan 2022 15:14:00 +0800
Subject: [PATCH 07/11] Move the initialization of "boot_date" to task_init()
The "boot_date" is initialized conditionally in the cmd_log(), which may
display incorrect "boot_date" value with the following command before
running the "log -T" command:
crash> help -k | grep date
date: Wed Dec 22 13:39:29 IST 2021
boot_date: Thu Jan 1 05:30:00 IST 1970
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The calculation of "boot_date" depends on the HZ value, and the HZ will
be calculated in task_init() at the latest, so let's move it here.
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
kernel.c | 18 +++---------------
task.c | 10 ++++++++++
2 files changed, 13 insertions(+), 15 deletions(-)
diff --git a/kernel.c b/kernel.c
index a44a9c52ace0..9afddc0c918c 100644
--- a/kernel.c
+++ b/kernel.c
@@ -5026,21 +5026,9 @@ cmd_log(void)
if (argerrs)
cmd_usage(pc->curcmd, SYNOPSIS);
- if (msg_flags & SHOW_LOG_CTIME) {
- if (pc->flags & MINIMAL_MODE) {
- error(WARNING, "the option '-T' is not available in minimal mode\n");
- return;
- }
-
- if (kt->boot_date.tv_sec == 0) {
- ulonglong uptime_jiffies;
- ulong uptime_sec;
-
- get_uptime(NULL, &uptime_jiffies);
- uptime_sec = (uptime_jiffies)/(ulonglong)machdep->hz;
- kt->boot_date.tv_sec = kt->date.tv_sec - uptime_sec;
- kt->boot_date.tv_nsec = 0;
- }
+ if (msg_flags & SHOW_LOG_CTIME && pc->flags & MINIMAL_MODE) {
+ error(WARNING, "the option '-T' is not available in minimal mode\n");
+ return;
}
if (msg_flags & SHOW_LOG_AUDIT) {
diff --git a/task.c b/task.c
index 76e184ae70b1..263a8344dd94 100644
--- a/task.c
+++ b/task.c
@@ -692,6 +692,16 @@ task_init(void)
stack_overflow_check_init();
+ if (machdep->hz) {
+ ulonglong uptime_jiffies;
+ ulong uptime_sec;
+
+ get_uptime(NULL, &uptime_jiffies);
+ uptime_sec = (uptime_jiffies)/(ulonglong)machdep->hz;
+ kt->boot_date.tv_sec = kt->date.tv_sec - uptime_sec;
+ kt->boot_date.tv_nsec = 0;
+ }
+
tt->flags |= TASK_INIT_DONE;
}
--
2.20.1

205
SOURCES/0007-bt-x86_64-filter-out-idle-task-stack.patch

@ -0,0 +1,205 @@
From 6833262bf87177d8affe4f91b2e7d2c76ecdf636 Mon Sep 17 00:00:00 2001
From: Qi Zheng <zhengqi.arch@bytedance.com>
Date: Tue, 24 May 2022 20:25:53 +0800
Subject: [PATCH 07/18] bt: x86_64: filter out idle task stack
When we use crash to troubleshoot softlockup and other problems,
we often use the 'bt -a' command to print the stacks of running
processes on all CPUs. But now some servers have hundreds of CPUs
(such as AMD machines), which causes the 'bt -a' command to output
a lot of process stacks. And many of these stacks are the stacks
of the idle process, which are not needed by us.
Therefore, in order to reduce this part of the interference information,
this patch adds the -n option to the bt command. When we specify
'-n idle' (meaning no idle), the stack of the idle process will be
filtered out, thus speeding up our troubleshooting.
And the option works only for crash dumps captured by kdump.
The command output is as follows:
crash> bt -a -n idle
[...]
PID: 0 TASK: ffff889ff8c34380 CPU: 8 COMMAND: "swapper/8"
PID: 0 TASK: ffff889ff8c32d00 CPU: 9 COMMAND: "swapper/9"
PID: 0 TASK: ffff889ff8c31680 CPU: 10 COMMAND: "swapper/10"
PID: 0 TASK: ffff889ff8c35a00 CPU: 11 COMMAND: "swapper/11"
PID: 0 TASK: ffff889ff8c3c380 CPU: 12 COMMAND: "swapper/12"
PID: 150773 TASK: ffff889fe85a1680 CPU: 13 COMMAND: "bash"
#0 [ffffc9000d35bcd0] machine_kexec at ffffffff8105a407
#1 [ffffc9000d35bd28] __crash_kexec at ffffffff8113033d
#2 [ffffc9000d35bdf0] panic at ffffffff81081930
#3 [ffffc9000d35be70] sysrq_handle_crash at ffffffff814e38d1
#4 [ffffc9000d35be78] __handle_sysrq.cold.12 at ffffffff814e4175
#5 [ffffc9000d35bea8] write_sysrq_trigger at ffffffff814e404b
#6 [ffffc9000d35beb8] proc_reg_write at ffffffff81330d86
#7 [ffffc9000d35bed0] vfs_write at ffffffff812a72d5
#8 [ffffc9000d35bf00] ksys_write at ffffffff812a7579
#9 [ffffc9000d35bf38] do_syscall_64 at ffffffff81004259
RIP: 00007fa7abcdc274 RSP: 00007fffa731f678 RFLAGS: 00000246
RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007fa7abcdc274
RDX: 0000000000000002 RSI: 0000563ca51ee6d0 RDI: 0000000000000001
RBP: 0000563ca51ee6d0 R8: 000000000000000a R9: 00007fa7abd6be80
R10: 000000000000000a R11: 0000000000000246 R12: 00007fa7abdad760
R13: 0000000000000002 R14: 00007fa7abda8760 R15: 0000000000000002
ORIG_RAX: 0000000000000001 CS: 0033 SS: 002b
[...]
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Acked-by: Kazuhito Hagio <k-hagio-ab@nec.com>
Acked-by: Lianbo Jiang <lijiang@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
defs.h | 1 +
help.c | 33 ++++++++++++++++++++++++++++++++-
kernel.c | 13 ++++++++++++-
x86_64.c | 8 ++++++++
4 files changed, 53 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index ecbced24d2e3..c8444b4e54eb 100644
--- a/defs.h
+++ b/defs.h
@@ -5832,6 +5832,7 @@ ulong cpu_map_addr(const char *type);
#define BT_SHOW_ALL_REGS (0x2000000000000ULL)
#define BT_REGS_NOT_FOUND (0x4000000000000ULL)
#define BT_OVERFLOW_STACK (0x8000000000000ULL)
+#define BT_SKIP_IDLE (0x10000000000000ULL)
#define BT_SYMBOL_OFFSET (BT_SYMBOLIC_ARGS)
#define BT_REF_HEXVAL (0x1)
diff --git a/help.c b/help.c
index 51a0fe3d687c..e1bbc5abe029 100644
--- a/help.c
+++ b/help.c
@@ -1909,12 +1909,14 @@ char *help_bt[] = {
"bt",
"backtrace",
"[-a|-c cpu(s)|-g|-r|-t|-T|-l|-e|-E|-f|-F|-o|-O|-v|-p] [-R ref] [-s [-x|d]]"
-"\n [-I ip] [-S sp] [pid | task]",
+"\n [-I ip] [-S sp] [-n idle] [pid | task]",
" Display a kernel stack backtrace. If no arguments are given, the stack",
" trace of the current context will be displayed.\n",
" -a displays the stack traces of the active task on each CPU.",
" (only applicable to crash dumps)",
" -A same as -a, but also displays vector registers (S390X only).",
+" -n idle filter the stack of idle tasks (x86_64).",
+" (only applicable to crash dumps)",
" -p display the stack trace of the panic task only.",
" (only applicable to crash dumps)",
" -c cpu display the stack trace of the active task on one or more CPUs,",
@@ -2004,6 +2006,35 @@ char *help_bt[] = {
" DS: 002b ESI: bfffc8a0 ES: 002b EDI: 00000000 ",
" SS: 002b ESP: bfffc82c EBP: bfffd224 ",
" CS: 0023 EIP: 400d032e ERR: 0000008e EFLAGS: 00000246 ",
+" ",
+" Display the stack trace of the active task(s) when the kernel panicked,",
+" and filter out the stack of the idle tasks:",
+" ",
+" %s> bt -a -n idle",
+" ...",
+" PID: 0 TASK: ffff889ff8c35a00 CPU: 11 COMMAND: \"swapper/11\"",
+" ",
+" PID: 0 TASK: ffff889ff8c3c380 CPU: 12 COMMAND: \"swapper/12\"",
+" ",
+" PID: 150773 TASK: ffff889fe85a1680 CPU: 13 COMMAND: \"bash\"",
+" #0 [ffffc9000d35bcd0] machine_kexec at ffffffff8105a407",
+" #1 [ffffc9000d35bd28] __crash_kexec at ffffffff8113033d",
+" #2 [ffffc9000d35bdf0] panic at ffffffff81081930",
+" #3 [ffffc9000d35be70] sysrq_handle_crash at ffffffff814e38d1",
+" #4 [ffffc9000d35be78] __handle_sysrq.cold.12 at ffffffff814e4175",
+" #5 [ffffc9000d35bea8] write_sysrq_trigger at ffffffff814e404b",
+" #6 [ffffc9000d35beb8] proc_reg_write at ffffffff81330d86",
+" #7 [ffffc9000d35bed0] vfs_write at ffffffff812a72d5",
+" #8 [ffffc9000d35bf00] ksys_write at ffffffff812a7579",
+" #9 [ffffc9000d35bf38] do_syscall_64 at ffffffff81004259",
+" RIP: 00007fa7abcdc274 RSP: 00007fffa731f678 RFLAGS: 00000246",
+" RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007fa7abcdc274",
+" RDX: 0000000000000002 RSI: 0000563ca51ee6d0 RDI: 0000000000000001",
+" RBP: 0000563ca51ee6d0 R8: 000000000000000a R9: 00007fa7abd6be80",
+" R10: 000000000000000a R11: 0000000000000246 R12: 00007fa7abdad760",
+" R13: 0000000000000002 R14: 00007fa7abda8760 R15: 0000000000000002",
+" ORIG_RAX: 0000000000000001 CS: 0033 SS: 002b",
+" ...",
"\n Display the stack trace of the active task on CPU 0 and 1:\n",
" %s> bt -c 0,1",
" PID: 0 TASK: ffffffff81a8d020 CPU: 0 COMMAND: \"swapper\"",
diff --git a/kernel.c b/kernel.c
index d0921cf567d9..411e9da1e54f 100644
--- a/kernel.c
+++ b/kernel.c
@@ -2503,7 +2503,7 @@ cmd_bt(void)
if (kt->flags & USE_OPT_BT)
bt->flags |= BT_OPT_BACK_TRACE;
- while ((c = getopt(argcnt, args, "D:fFI:S:c:aAloreEgstTdxR:Ovp")) != EOF) {
+ while ((c = getopt(argcnt, args, "D:fFI:S:c:n:aAloreEgstTdxR:Ovp")) != EOF) {
switch (c)
{
case 'f':
@@ -2672,6 +2672,13 @@ cmd_bt(void)
active++;
break;
+ case 'n':
+ if (machine_type("X86_64") && STREQ(optarg, "idle"))
+ bt->flags |= BT_SKIP_IDLE;
+ else
+ option_not_supported(c);
+ break;
+
case 'r':
bt->flags |= BT_RAW;
break;
@@ -3092,6 +3099,10 @@ back_trace(struct bt_info *bt)
} else
machdep->get_stack_frame(bt, &eip, &esp);
+ /* skip idle task stack */
+ if (bt->flags & BT_SKIP_IDLE)
+ return;
+
if (bt->flags & BT_KSTACKP) {
bt->stkptr = esp;
return;
diff --git a/x86_64.c b/x86_64.c
index ecaefd2f46a8..cfafbcc4dabe 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -4918,6 +4918,9 @@ x86_64_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp)
if (bt->flags & BT_DUMPFILE_SEARCH)
return x86_64_get_dumpfile_stack_frame(bt, pcp, spp);
+ if (bt->flags & BT_SKIP_IDLE)
+ bt->flags &= ~BT_SKIP_IDLE;
+
if (pcp)
*pcp = x86_64_get_pc(bt);
if (spp)
@@ -4960,6 +4963,9 @@ x86_64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *rip, ulong *rsp)
estack = -1;
panic = FALSE;
+ if (bt_in->flags & BT_SKIP_IDLE)
+ bt_in->flags &= ~BT_SKIP_IDLE;
+
panic_task = tt->panic_task == bt->task ? TRUE : FALSE;
if (panic_task && bt->machdep) {
@@ -5098,6 +5104,8 @@ next_sysrq:
if (!panic_task && STREQ(sym, "crash_nmi_callback")) {
*rip = *up;
*rsp = bt->stackbase + ((char *)(up) - bt->stackbuf);
+ if ((bt->flags & BT_SKIP_IDLE) && is_idle_thread(bt->task))
+ bt_in->flags |= BT_SKIP_IDLE;
return;
}
--
2.30.2

79
SOURCES/0008-Remove-ptype-command-from-ps-t-option-to-reduce-memo.patch

@ -1,79 +0,0 @@
From bbd5a5c1f5db3bde04628e75396155260333e53e Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
Date: Wed, 19 Jan 2022 16:24:49 +0900
Subject: [PATCH 08/11] Remove ptype command from "ps -t" option to reduce
memory and time
With some vmlinux e.g. RHEL9 ones, the first execution of the gdb ptype
command heavily consumes memory and time. The "ps -t" option uses it in
start_time_timespec(), and it can be replaced with the crash macros.
This can reduce about 1.4 GB memory and 6 seconds time comsumption in
the following test:
$ echo "ps -t" | time crash vmlinux vmcore
Without the patch:
11.60user 0.43system 0:11.94elapsed 100%CPU (0avgtext+0avgdata 1837964maxresident)k
0inputs+400outputs (0major+413636minor)pagefaults 0swaps
With the patch:
5.40user 0.16system 0:05.46elapsed 101%CPU (0avgtext+0avgdata 417896maxresident)k
0inputs+384outputs (0major+41528minor)pagefaults 0swaps
Although the ptype command and similar ones cannot be fully removed,
but removing some of them will make the use of crash safer, especially
for an automatic crash reporter.
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
task.c | 25 +++++--------------------
1 file changed, 5 insertions(+), 20 deletions(-)
diff --git a/task.c b/task.c
index 263a8344dd94..a79ed0d96fb5 100644
--- a/task.c
+++ b/task.c
@@ -4662,8 +4662,6 @@ show_task_times(struct task_context *tcp, ulong flags)
static int
start_time_timespec(void)
{
- char buf[BUFSIZE];
-
switch(tt->flags & (TIMESPEC | NO_TIMESPEC | START_TIME_NSECS))
{
case TIMESPEC:
@@ -4677,24 +4675,11 @@ start_time_timespec(void)
tt->flags |= NO_TIMESPEC;
- open_tmpfile();
- sprintf(buf, "ptype struct task_struct");
- if (!gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR)) {
- close_tmpfile();
- return FALSE;
- }
-
- rewind(pc->tmpfile);
- while (fgets(buf, BUFSIZE, pc->tmpfile)) {
- if (strstr(buf, "start_time;")) {
- if (strstr(buf, "struct timespec")) {
- tt->flags &= ~NO_TIMESPEC;
- tt->flags |= TIMESPEC;
- }
- }
- }
-
- close_tmpfile();
+ if (VALID_MEMBER(task_struct_start_time) &&
+ STREQ(MEMBER_TYPE_NAME("task_struct", "start_time"), "timespec")) {
+ tt->flags &= ~NO_TIMESPEC;
+ tt->flags |= TIMESPEC;
+ }
if ((tt->flags & NO_TIMESPEC) && (SIZE(task_struct_start_time) == 8)) {
tt->flags &= ~NO_TIMESPEC;
--
2.20.1

96
SOURCES/0008-bt-arm64-add-support-for-bt-n-idle.patch

@ -0,0 +1,96 @@
From 0f162febebc4d11a165dd40cee00f3b0ba691a52 Mon Sep 17 00:00:00 2001
From: Qi Zheng <zhengqi.arch@bytedance.com>
Date: Tue, 24 May 2022 20:25:54 +0800
Subject: [PATCH 08/18] bt: arm64: add support for 'bt -n idle'
The '-n idle' option of bt command can help us filter the
stack of the idle process when debugging the dumpfiles
captured by kdump.
This patch supports this feature on ARM64.
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
arm64.c | 19 ++++++++++++++++---
help.c | 2 +-
kernel.c | 3 ++-
3 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/arm64.c b/arm64.c
index 65f6cdf69fa6..0f615cf52bef 100644
--- a/arm64.c
+++ b/arm64.c
@@ -3681,6 +3681,12 @@ arm64_get_dumpfile_stackframe(struct bt_info *bt, struct arm64_stackframe *frame
{
struct machine_specific *ms = machdep->machspec;
struct arm64_pt_regs *ptregs;
+ bool skip = false;
+
+ if (bt->flags & BT_SKIP_IDLE) {
+ skip = true;
+ bt->flags &= ~BT_SKIP_IDLE;
+ }
if (!ms->panic_task_regs ||
(!ms->panic_task_regs[bt->tc->processor].sp &&
@@ -3713,8 +3719,11 @@ try_kernel:
}
if (arm64_in_kdump_text(bt, frame) ||
- arm64_in_kdump_text_on_irq_stack(bt))
+ arm64_in_kdump_text_on_irq_stack(bt)) {
bt->flags |= BT_KDUMP_ADJUST;
+ if (skip && is_idle_thread(bt->task))
+ bt->flags |= BT_SKIP_IDLE;
+ }
return TRUE;
}
@@ -3738,10 +3747,14 @@ arm64_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp)
int ret;
struct arm64_stackframe stackframe = { 0 };
- if (DUMPFILE() && is_task_active(bt->task))
+ if (DUMPFILE() && is_task_active(bt->task)) {
ret = arm64_get_dumpfile_stackframe(bt, &stackframe);
- else
+ } else {
+ if (bt->flags & BT_SKIP_IDLE)
+ bt->flags &= ~BT_SKIP_IDLE;
+
ret = arm64_get_stackframe(bt, &stackframe);
+ }
if (!ret)
error(WARNING,
diff --git a/help.c b/help.c
index e1bbc5abe029..99214c1590fa 100644
--- a/help.c
+++ b/help.c
@@ -1915,7 +1915,7 @@ char *help_bt[] = {
" -a displays the stack traces of the active task on each CPU.",
" (only applicable to crash dumps)",
" -A same as -a, but also displays vector registers (S390X only).",
-" -n idle filter the stack of idle tasks (x86_64).",
+" -n idle filter the stack of idle tasks (x86_64, arm64).",
" (only applicable to crash dumps)",
" -p display the stack trace of the panic task only.",
" (only applicable to crash dumps)",
diff --git a/kernel.c b/kernel.c
index 411e9da1e54f..a521ef30cdb0 100644
--- a/kernel.c
+++ b/kernel.c
@@ -2673,7 +2673,8 @@ cmd_bt(void)
break;
case 'n':
- if (machine_type("X86_64") && STREQ(optarg, "idle"))
+ if ((machine_type("X86_64") || machine_type("ARM64")) &&
+ STREQ(optarg, "idle"))
bt->flags |= BT_SKIP_IDLE;
else
option_not_supported(c);
--
2.30.2

150
SOURCES/0009-Improve-the-ps-performance-for-vmcores-with-large-nu.patch

@ -1,150 +0,0 @@
From d52cccfaa96ed6f61ff9d53da88715296e31db80 Mon Sep 17 00:00:00 2001
From: Tao Liu <ltao@redhat.com>
Date: Fri, 21 Jan 2022 13:43:09 +0800
Subject: [PATCH 09/11] Improve the ps performance for vmcores with large
number of threads
Previously, the ps command will iterate over all threads which
have the same tgid, to accumulate their rss value, in order to
get a thread/process's final rss value as part of the final output.
For non-live systems, the rss accumulation values are identical for
threads which have the same tgid, so there is no need to do the
iteration and accumulation repeatly, thus a lot of readmem calls are
skipped. Otherwise it will be the performance bottleneck if the
vmcores have a large number of threads.
In this patch, the rss accumulation value will be stored in a cache,
next time a thread with the same tgid will take it directly without
the iteration.
For example, we can monitor the performance issue when a vmcore has
~65k processes, most of which are threads for several specific
processes. Without the patch, it will take ~7h for ps command
to finish. With the patch, ps command will finish in 1min.
Signed-off-by: Tao Liu <ltao@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
defs.h | 1 +
memory.c | 70 +++++++++++++++++++++++++++++++-------------------------
task.c | 1 +
3 files changed, 41 insertions(+), 31 deletions(-)
diff --git a/defs.h b/defs.h
index 41b6cbc6cc85..77e76f27cddb 100644
--- a/defs.h
+++ b/defs.h
@@ -830,6 +830,7 @@ struct task_context { /* context stored for each task */
struct tgid_context { /* tgid and task stored for each task */
ulong tgid;
ulong task;
+ long rss_cache;
};
struct task_table { /* kernel/local task table data */
diff --git a/memory.c b/memory.c
index 5af45fd7d834..e80c59ea4534 100644
--- a/memory.c
+++ b/memory.c
@@ -4665,7 +4665,7 @@ void
get_task_mem_usage(ulong task, struct task_mem_usage *tm)
{
struct task_context *tc;
- long rss = 0;
+ long rss = 0, rss_cache = 0;
BZERO(tm, sizeof(struct task_mem_usage));
@@ -4730,38 +4730,46 @@ get_task_mem_usage(ulong task, struct task_mem_usage *tm)
(last->tgid == (last + 1)->tgid))
last++;
- while (first <= last)
- {
- /* count 0 -> filepages */
- if (!readmem(first->task +
- OFFSET(task_struct_rss_stat) +
- OFFSET(task_rss_stat_count), KVADDR,
- &sync_rss,
- sizeof(int),
- "task_struct rss_stat MM_FILEPAGES",
- RETURN_ON_ERROR))
- continue;
-
- rss += sync_rss;
-
- /* count 1 -> anonpages */
- if (!readmem(first->task +
- OFFSET(task_struct_rss_stat) +
- OFFSET(task_rss_stat_count) +
- sizeof(int),
- KVADDR, &sync_rss,
- sizeof(int),
- "task_struct rss_stat MM_ANONPAGES",
- RETURN_ON_ERROR))
- continue;
-
- rss += sync_rss;
-
- if (first == last)
- break;
- first++;
+ /*
+ * Using rss cache for dumpfile is more beneficial than live debug
+ * because its value never changes in dumpfile.
+ */
+ if (ACTIVE() || last->rss_cache == UNINITIALIZED) {
+ while (first <= last)
+ {
+ /* count 0 -> filepages */
+ if (!readmem(first->task +
+ OFFSET(task_struct_rss_stat) +
+ OFFSET(task_rss_stat_count), KVADDR,
+ &sync_rss,
+ sizeof(int),
+ "task_struct rss_stat MM_FILEPAGES",
+ RETURN_ON_ERROR))
+ continue;
+
+ rss_cache += sync_rss;
+
+ /* count 1 -> anonpages */
+ if (!readmem(first->task +
+ OFFSET(task_struct_rss_stat) +
+ OFFSET(task_rss_stat_count) +
+ sizeof(int),
+ KVADDR, &sync_rss,
+ sizeof(int),
+ "task_struct rss_stat MM_ANONPAGES",
+ RETURN_ON_ERROR))
+ continue;
+
+ rss_cache += sync_rss;
+
+ if (first == last)
+ break;
+ first++;
+ }
+ last->rss_cache = rss_cache;
}
+ rss += last->rss_cache;
tt->last_tgid = last;
}
}
diff --git a/task.c b/task.c
index a79ed0d96fb5..864c838637ee 100644
--- a/task.c
+++ b/task.c
@@ -2947,6 +2947,7 @@ add_context(ulong task, char *tp)
tg = tt->tgid_array + tt->running_tasks;
tg->tgid = *tgid_addr;
tg->task = task;
+ tg->rss_cache = UNINITIALIZED;
if (do_verify && !verify_task(tc, do_verify)) {
error(INFO, "invalid task address: %lx\n", tc->task);
--
2.20.1