Fix for irq/tree issues

Upstream commits:
b76e116c50ff ("vmware: Improve output when we fail to read vmware 'vmsn' file")
d17d51a92a3a ("Exclude zero entries from do_maple_tree() return value")
38d35bd1423c ("Fix "irq [-a|-s]" options on Linux 6.5-rc1 and later")
f0b59524624b ("Fix segmentation fault by "tree -s" option with Maple Tree")

Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
This commit is contained in:
Lianbo Jiang 2023-07-13 10:06:35 +08:00
parent b015957717
commit d2b8160311
5 changed files with 425 additions and 0 deletions

View File

@ -0,0 +1,133 @@
From b76e116c50ffc228ebc08eb8de35019320679257 Mon Sep 17 00:00:00 2001
From: Dave Wysochanski <dwysocha@redhat.com>
Date: Thu, 6 Jul 2023 10:53:18 -0400
Subject: [PATCH 1/4] vmware: Improve output when we fail to read vmware 'vmsn'
file
Today if crash fails to read some structure in a vmware 'vmsn' file,
it will throw an "No such file or directory" message. Such a generic
message does not give any clue as to the problem, but instead sounds
like the file may not exist when it does, for example:
$ crash ./vmcore.vmsn ./vmlinux
crash 8.0.3
...
crash: vmw: Failed to read './vmcore.vmsn': [Error 2] No such file or directory
crash: ./vmcore.vmsn: initialization failed
$ ls -l ./vmcore.vmsn
-rwxrwxrwx. 7 myuser mygroup 12128999 Jul 4 07:21 ./vmcore.vmsn
Improve the above error message so we at least know which portion
of the file crash had difficulty reading. After this patch, the
above error looks like:
crash: vmw: Failed to read 'cptgroupdesc' from file './vmcore.vmsn': [Error 2] No such file or directory
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
vmware_guestdump.c | 8 ++++----
vmware_vmss.c | 24 ++++++++++++------------
2 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/vmware_guestdump.c b/vmware_guestdump.c
index cf818e588a60..5be26c8e2e90 100644
--- a/vmware_guestdump.c
+++ b/vmware_guestdump.c
@@ -117,8 +117,8 @@ is_vmware_guestdump(char *filename)
}
if (fread(&hdr, sizeof(struct guestdumpheader), 1, fp) != 1) {
- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n",
- filename, errno, strerror(errno));
+ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n",
+ "guestdumpheader", filename, errno, strerror(errno));
fclose(fp);
return FALSE;
}
@@ -204,8 +204,8 @@ vmware_guestdump_init(char *filename, FILE *ofp)
for (i = 0; i < vmss.num_vcpus; i++) {
if (fread(&vs, sizeof(struct vcpu_state), 1, fp) != 1) {
- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n",
- filename, errno, strerror(errno));
+ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n",
+ "vcpu_state", filename, errno, strerror(errno));
result = FALSE;
goto exit;
}
diff --git a/vmware_vmss.c b/vmware_vmss.c
index f6c5f32ea4c0..8121ab64a99a 100644
--- a/vmware_vmss.c
+++ b/vmware_vmss.c
@@ -39,8 +39,8 @@ is_vmware_vmss(char *filename)
}
if (fread(&hdr, sizeof(cptdumpheader), 1, fp) != 1) {
- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n",
- filename, errno, strerror(errno));
+ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n",
+ "cptdumpheader", filename, errno, strerror(errno));
fclose(fp);
return FALSE;
}
@@ -86,8 +86,8 @@ vmware_vmss_init(char *filename, FILE *ofp)
}
if (fread(&hdr, sizeof(cptdumpheader), 1, fp) != 1) {
- error(INFO, LOGPRX"Failed to read '%s': %s [Error %d] %s\n",
- filename, errno, strerror(errno));
+ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n",
+ "cptdumpheader", filename, errno, strerror(errno));
result = FALSE;
goto exit;
}
@@ -112,8 +112,8 @@ vmware_vmss_init(char *filename, FILE *ofp)
}
if (fread(grps, sizeof(cptgroupdesc), grpsize, fp) != grpsize) {
- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n",
- filename, errno, strerror(errno));
+ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n",
+ "cptgroupdesc", filename, errno, strerror(errno));
result = FALSE;
goto exit;
}
@@ -225,8 +225,8 @@ vmware_vmss_init(char *filename, FILE *ofp)
idx[0] < vmss.num_vcpus) {
int cpu = idx[0];
if (fread(vmss.regs64[cpu], VMW_GPREGS_SIZE, 1, fp) != 1) {
- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n",
- filename, errno, strerror(errno));
+ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n",
+ name, filename, errno, strerror(errno));
break;
}
DEBUG_PARSE_PRINT((ofp, "\n"));
@@ -237,8 +237,8 @@ vmware_vmss_init(char *filename, FILE *ofp)
int cpu = idx[0];
DEBUG_PARSE_PRINT((ofp, "\t=> "));
if (fread(&vmss.regs64[cpu]->cr[0], VMW_CR64_SIZE, 1, fp) != 1) {
- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n",
- filename, errno, strerror(errno));
+ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n",
+ name, filename, errno, strerror(errno));
break;
}
for (j = 0; j < VMW_CR64_SIZE / 8; j++)
@@ -257,8 +257,8 @@ vmware_vmss_init(char *filename, FILE *ofp)
break;
}
if (fread(&idtr, sizeof(idtr), 1, fp) != 1) {
- error(INFO, LOGPRX"Failed to read '%s': [Error %d] %s\n",
- filename, errno, strerror(errno));
+ error(INFO, LOGPRX"Failed to read '%s' from file '%s': [Error %d] %s\n",
+ name, filename, errno, strerror(errno));
break;
}
DEBUG_PARSE_PRINT((ofp, "\n"));
--
2.37.1

View File

@ -0,0 +1,33 @@
From d17d51a92a3a1c1cce1e646c38fe52ca99406cf9 Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
Date: Fri, 7 Jul 2023 15:17:18 +0900
Subject: [PATCH 2/4] Exclude zero entries from do_maple_tree() return value
While the return value of do_radix_tree() and do_xarray() does not
contain NULL entries, do_maple_tree()'s one contains NULL entries.
Make this behavior consistent with the previous tree functions to make
replacement easier, especially for the following patch.
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
maple_tree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/maple_tree.c b/maple_tree.c
index 807c17f7dfa0..eccd273105a6 100644
--- a/maple_tree.c
+++ b/maple_tree.c
@@ -287,7 +287,7 @@ static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth,
static struct req_entry **e = NULL;
struct tree_data *td = ops->is_td ? (struct tree_data *)ops->private : NULL;
- if (ops->entry)
+ if (ops->entry && entry)
ops->entry(entry, entry, path, max, ops->private);
if (!td)
--
2.37.1

View File

@ -0,0 +1,198 @@
From 38d35bd1423ccafd0b8be0744155ce59ef3034ff Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
Date: Wed, 12 Jul 2023 17:55:29 +0900
Subject: [PATCH 3/4] Fix "irq [-a|-s]" options on Linux 6.5-rc1 and later
Kernel commit 721255b982 ("genirq: Use a maple tree for interrupt
descriptor management"), which is contained in Linux 6.5-rc1 and later
kernels, replaced irq_desc_tree with a maple tree sparse_irqs.
Without the patch, "irq [-a|-s]" options fail with an error, e.g. the
following on x86_64, on kernels configured with CONFIG_SPARSE_IRQ=y.
crash> irq
irq: x86_64_dump_irq: irq_desc[] or irq_desc_tree do not exist?
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
defs.h | 2 ++
ia64.c | 3 ++-
kernel.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++---
symbols.c | 1 +
x86_64.c | 9 ++++++---
5 files changed, 59 insertions(+), 7 deletions(-)
diff --git a/defs.h b/defs.h
index 26afe232cc3e..358f365585cf 100644
--- a/defs.h
+++ b/defs.h
@@ -676,6 +676,7 @@ struct new_utsname {
#define IRQ_DESC_TREE_XARRAY (0x80ULL)
#define KMOD_PAX (0x100ULL)
#define KMOD_MEMORY (0x200ULL)
+#define IRQ_DESC_TREE_MAPLE (0x400ULL)
#define XEN() (kt->flags & ARCH_XEN)
#define OPENVZ() (kt->flags & ARCH_OPENVZ)
@@ -2222,6 +2223,7 @@ struct offset_table { /* stash of commonly-used offsets */
long module_mem;
long module_memory_base;
long module_memory_size;
+ long irq_data_irq;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/ia64.c b/ia64.c
index 2e1d15fe6042..d3e0a3b01869 100644
--- a/ia64.c
+++ b/ia64.c
@@ -791,7 +791,8 @@ ia64_back_trace_cmd(struct bt_info *bt)
static void
ia64_dump_irq(int irq)
{
- if (symbol_exists("irq_desc") || symbol_exists("_irq_desc") ||
+ if (kernel_symbol_exists("sparse_irqs") ||
+ symbol_exists("irq_desc") || symbol_exists("_irq_desc") ||
kernel_symbol_exists("irq_desc_ptrs")) {
machdep->dump_irq = generic_dump_irq;
return(generic_dump_irq(irq));
diff --git a/kernel.c b/kernel.c
index 0fc77c19f12a..546eed95eebd 100644
--- a/kernel.c
+++ b/kernel.c
@@ -541,7 +541,10 @@ kernel_init()
MEMBER_OFFSET_INIT(irqaction_dev_id, "irqaction", "dev_id");
MEMBER_OFFSET_INIT(irqaction_next, "irqaction", "next");
- if (kernel_symbol_exists("irq_desc_tree")) {
+ /* 6.5 and later: CONFIG_SPARSE_IRQ */
+ if (kernel_symbol_exists("sparse_irqs"))
+ kt->flags2 |= IRQ_DESC_TREE_MAPLE;
+ else if (kernel_symbol_exists("irq_desc_tree")) {
get_symbol_type("irq_desc_tree", NULL, &req);
if (STREQ(req.type_tag_name, "xarray")) {
kt->flags2 |= IRQ_DESC_TREE_XARRAY;
@@ -554,6 +557,7 @@ kernel_init()
}
STRUCT_SIZE_INIT(irq_data, "irq_data");
if (VALID_STRUCT(irq_data)) {
+ MEMBER_OFFSET_INIT(irq_data_irq, "irq_data", "irq");
MEMBER_OFFSET_INIT(irq_data_chip, "irq_data", "chip");
MEMBER_OFFSET_INIT(irq_data_affinity, "irq_data", "affinity");
MEMBER_OFFSET_INIT(irq_desc_irq_data, "irq_desc", "irq_data");
@@ -6180,6 +6184,8 @@ dump_kernel_table(int verbose)
fprintf(fp, "%sIRQ_DESC_TREE_RADIX", others++ ? "|" : "");
if (kt->flags2 & IRQ_DESC_TREE_XARRAY)
fprintf(fp, "%sIRQ_DESC_TREE_XARRAY", others++ ? "|" : "");
+ if (kt->flags2 & IRQ_DESC_TREE_MAPLE)
+ fprintf(fp, "%sIRQ_DESC_TREE_MAPLE", others++ ? "|" : "");
if (kt->flags2 & KMOD_PAX)
fprintf(fp, "%sKMOD_PAX", others++ ? "|" : "");
if (kt->flags2 & KMOD_MEMORY)
@@ -6652,6 +6658,45 @@ get_irq_desc_addr(int irq)
readmem(ptr, KVADDR, &addr,
sizeof(void *), "irq_desc_ptrs entry",
FAULT_ON_ERROR);
+ } else if (kt->flags2 & IRQ_DESC_TREE_MAPLE) {
+ unsigned int i;
+
+ if (kt->highest_irq && (irq > kt->highest_irq))
+ return addr;
+
+ cnt = do_maple_tree(symbol_value("sparse_irqs"), MAPLE_TREE_COUNT, NULL);
+
+ len = sizeof(struct list_pair) * (cnt+1);
+ lp = (struct list_pair *)GETBUF(len);
+ lp[0].index = cnt; /* maxcount */
+
+ cnt = do_maple_tree(symbol_value("sparse_irqs"), MAPLE_TREE_GATHER, lp);
+
+ /*
+ * NOTE: We cannot use lp.index like Radix Tree or XArray because
+ * it's not an absolute index and just counter in Maple Tree.
+ */
+ if (kt->highest_irq == 0) {
+ readmem((ulong)lp[cnt-1].value +
+ OFFSET(irq_desc_irq_data) + OFFSET(irq_data_irq),
+ KVADDR, &kt->highest_irq, sizeof(int), "irq_data.irq",
+ FAULT_ON_ERROR);
+ }
+
+ for (c = 0; c < cnt; c++) {
+ readmem((ulong)lp[c].value +
+ OFFSET(irq_desc_irq_data) + OFFSET(irq_data_irq),
+ KVADDR, &i, sizeof(int), "irq_data.irq", FAULT_ON_ERROR);
+ if (i == irq) {
+ if (CRASHDEBUG(1))
+ fprintf(fp, "index: %d value: %lx\n",
+ i, (ulong)lp[c].value);
+ addr = (ulong)lp[c].value;
+ break;
+ }
+ }
+ FREEBUF(lp);
+
} else if (kt->flags2 & (IRQ_DESC_TREE_RADIX|IRQ_DESC_TREE_XARRAY)) {
if (kt->highest_irq && (irq > kt->highest_irq))
return addr;
@@ -6700,8 +6745,8 @@ get_irq_desc_addr(int irq)
FREEBUF(lp);
} else {
error(FATAL,
- "neither irq_desc, _irq_desc, irq_desc_ptrs "
- "or irq_desc_tree symbols exist\n");
+ "neither irq_desc, _irq_desc, irq_desc_ptrs, "
+ "irq_desc_tree or sparse_irqs symbols exist\n");
}
return addr;
diff --git a/symbols.c b/symbols.c
index 82529a6785c9..876be7aea90e 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10375,6 +10375,7 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(irq_desc_t_kstat_irqs));
fprintf(fp, " irq_desc_t_affinity: %ld\n",
OFFSET(irq_desc_t_affinity));
+ fprintf(fp, " irq_data_irq: %ld\n", OFFSET(irq_data_irq));
fprintf(fp, " irq_data_chip: %ld\n",
OFFSET(irq_data_chip));
fprintf(fp, " irq_data_affinity: %ld\n",
diff --git a/x86_64.c b/x86_64.c
index 87e87ae6e1e8..42ade4817ad9 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -5391,7 +5391,8 @@ get_x86_64_frame(struct bt_info *bt, ulong *getpc, ulong *getsp)
static void
x86_64_dump_irq(int irq)
{
- if (symbol_exists("irq_desc") ||
+ if (kernel_symbol_exists("sparse_irqs") ||
+ symbol_exists("irq_desc") ||
kernel_symbol_exists("irq_desc_ptrs") ||
kernel_symbol_exists("irq_desc_tree")) {
machdep->dump_irq = generic_dump_irq;
@@ -5405,7 +5406,8 @@ x86_64_dump_irq(int irq)
static void
x86_64_get_irq_affinity(int irq)
{
- if (symbol_exists("irq_desc") ||
+ if (kernel_symbol_exists("sparse_irqs") ||
+ symbol_exists("irq_desc") ||
kernel_symbol_exists("irq_desc_ptrs") ||
kernel_symbol_exists("irq_desc_tree")) {
machdep->get_irq_affinity = generic_get_irq_affinity;
@@ -5419,7 +5421,8 @@ x86_64_get_irq_affinity(int irq)
static void
x86_64_show_interrupts(int irq, ulong *cpus)
{
- if (symbol_exists("irq_desc") ||
+ if (kernel_symbol_exists("sparse_irqs") ||
+ symbol_exists("irq_desc") ||
kernel_symbol_exists("irq_desc_ptrs") ||
kernel_symbol_exists("irq_desc_tree")) {
machdep->show_interrupts = generic_show_interrupts;
--
2.37.1

View File

@ -0,0 +1,53 @@
From f0b59524624b83d634b3fa8ab4ab3acf9ccce9df Mon Sep 17 00:00:00 2001
From: Kazuhito Hagio <k-hagio-ab@nec.com>
Date: Mon, 10 Jul 2023 15:05:36 +0900
Subject: [PATCH 4/4] Fix segmentation fault by "tree -s" option with Maple
Tree
Without the patch, do_mt_entry() can call dump_struct_members_for_tree()
with a NULL entry, and parse_for_member_extended() will cause a
segmentation fault during strncpy().
This is caused by "tree -t maple -s struct.member.member" style multiple
level member access:
crash> tree -t maple -s irq_desc.irq_data.irq sparse_irqs
ffff936980188400
irq_data.irq = 0,
ffff93698018be00
irq_data.irq = 1,
...
ffff936980f38e00
irq_data.irq = 19,
Segmentation fault (core dumped)
(gdb) bt
#0 0x00007faaf8e51635 in __strncpy_avx2 () from /lib64/libc.so.6
#1 0x00000000005e5927 in parse_for_member_extended (dm=dm@entry=0x7ffcb9e6d860, ...
#2 0x0000000000603c45 in dump_struct_member (s=s@entry=0x128cde0 <shared_bufs+1024> ...
#3 0x0000000000513cf5 in dump_struct_members_for_tree (td=td@entry=0x7ffcb9e6eeb0, ...
#4 0x0000000000651f15 in do_mt_entry (entry=0, min=min@entry=20, max=max@entry=119, ...
...
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
maple_tree.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/maple_tree.c b/maple_tree.c
index eccd273105a6..8c804d0cb80d 100644
--- a/maple_tree.c
+++ b/maple_tree.c
@@ -313,7 +313,7 @@ static void do_mt_entry(ulong entry, ulong min, ulong max, uint depth,
fprintf(fp, " index: %ld position: %s/%u\n",
++(*global_index), path, index);
- if (td->structname) {
+ if (td->structname && entry) {
if (td->flags & TREE_STRUCT_RADIX_10)
print_radix = 10;
else if (td->flags & TREE_STRUCT_RADIX_16)
--
2.37.1

View File

@ -35,6 +35,10 @@ Patch14: 0013-Support-module-memory-layout-change-on-Linux-6.4.patch
Patch15: 0014-Fix-failure-of-gathering-task-table-on-Linux-6.5-rc1.patch
Patch16: 0015-Fix-compilation-error-due-to-new-strlcpy-function-th.patch
Patch17: 0016-Fix-irq-a-option-on-Linux-6.0-and-later.patch
Patch18: 0017-vmware-Improve-output-when-we-fail-to-read-vmware-vm.patch
Patch19: 0018-Exclude-zero-entries-from-do_maple_tree-return-value.patch
Patch20: 0019-Fix-irq-a-s-options-on-Linux-6.5-rc1-and-later.patch
Patch21: 0020-Fix-segmentation-fault-by-tree-s-option-with-Maple-T.patch
%description
The core analysis suite is a self-contained tool that can be used to
@ -72,6 +76,10 @@ offered by Mission Critical Linux, or the LKCD kernel patch.
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%build