[PATCH 0/6] bt fixes and cleanup for ppc64
by Hari Bathini
This patch series fixes a couple of issues with bt on ppc64 and also
does some code cleanup.
Patch #1 fixes the broken '-S' option on ppc64. The next patch changes
h/w interrupt stack allocation to dynamic as this field remains unused
in most cases. The next patch renames ppc64_paca_init() function to
ppc64_paca_percpu_offset_init() to reflect what the function actually
does. Patch#4 adds support to process backtrace when the stack pointer
is in an emergency SP. The next patch adds support to print emergency
stack data. And the last patch ensures a variable is used instead of
machdep->machspec to optimize code and improve readability.
Hari Bathini (6):
ppc64: fix bt for '-S' case
ppc64: dynamically allocate h/w interrupt stack
ppc64: rename ppc64_paca_init to ppc64_paca_percpu_offset_init
ppc64: handle backtrace when CPU is in an emerency stack
ppc64: print emergency stacks info with 'mach -e'
ppc64: use a variable for machdep->machspec
defs.h | 14 +-
help.c | 31 ++++
ppc64.c | 528 +++++++++++++++++++++++++++++++++++++++-----------------
3 files changed, 417 insertions(+), 156 deletions(-)
--
2.35.3
2 years, 4 months
[ [PATCH]] arm64: Fix for st->_stext_vmlinux not initialized when set VA_BITS_ACTUAL
by Qianli Zhao
From: Qianli Zhao <qianli.zhao(a)horizon.ai>
Setting st->_stext_vmlinux to UNINITIALIZED to search for "_stext" from the vmlinux
Without the patch, if we do not enable kaslr, will get the wrong
MODULES/VMALLOC ranges, cause parsing dump failure
Signed-off-by: Qianli Zhao <qianli.zhao(a)horizon.ai>
---
arm64.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arm64.c b/arm64.c
index 0f615cf..4458a66 100644
--- a/arm64.c
+++ b/arm64.c
@@ -149,6 +149,9 @@ arm64_init(int when)
ms = machdep->machspec;
+ if (ms->VA_BITS_ACTUAL)
+ st->_stext_vmlinux = UNINITIALIZED;
+
if (!ms->kimage_voffset && STREQ(pc->live_memsrc, "/dev/crash"))
ioctl(pc->mfd, DEV_CRASH_ARCH_DATA, &ms->kimage_voffset);
--
2.17.1
2 years, 4 months
[PATCH crash-gcore 0/2] Fixes for 32-bit ARM
by Vincent Whitchurch
This series fixes some build warnings seen when building gcore for analysis of
32-bit ARM dumps on a 64-bit x86 host. Without the fixes, gcore.so sometimes
segfaults due to stack corruption due to the type mismatches.
Thank you.
Vincent Whitchurch (2):
gcore: fix phys addr type
gcore: fix offset types
src/libgcore/gcore_coredump.c | 3 ++-
src/libgcore/gcore_defs.h | 2 +-
src/libgcore/gcore_elf_struct.c | 4 ++--
3 files changed, 5 insertions(+), 4 deletions(-)
--
2.28.0
2 years, 5 months
[PATCH] Extend field length of task attributes
by HAGIO KAZUHITO(萩尾 一仁)
Nowadays, some machines have many CPU cores and memory, and some
distributions have a larger kernel.pid_max parameter, e.g. 7 digits.
This impairs the readability of a few commands, especially "ps" and
"ps -l|-m" options.
Let's extend the field length of the task attributes, PID, CPU, VSZ,
and RSS to improve the readability.
Without the patch:
crash> ps
PID PPID CPU TASK ST %MEM VSZ RSS COMM
...
2802197 2699997 2 ffff916f63c40000 IN 0.0 307212 10688 timer
2802277 1 0 ffff9161a25bb080 IN 0.0 169040 2744 gpg-agent
2806711 3167854 10 ffff9167fc498000 IN 0.0 127208 6508 su
2806719 2806711 1 ffff91633c3a48c0 IN 0.0 29452 6416 bash
2988346 1 5 ffff916f7c629840 IN 2.8 9342476 1917384 qemu-kvm
With the patch:
crash> ps
PID PPID CPU TASK ST %MEM VSZ RSS COMM
...
2802197 2699997 2 ffff916f63c40000 IN 0.0 307212 10688 timer
2802277 1 0 ffff9161a25bb080 IN 0.0 169040 2744 gpg-agent
2806711 3167854 10 ffff9167fc498000 IN 0.0 127208 6508 su
2806719 2806711 1 ffff91633c3a48c0 IN 0.0 29452 6416 bash
2988346 1 5 ffff916f7c629840 IN 2.8 9342476 1917384 qemu-kvm
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
task.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/task.c b/task.c
index 864c838637ee..071c787fbfa5 100644
--- a/task.c
+++ b/task.c
@@ -3828,7 +3828,7 @@ show_ps_data(ulong flag, struct task_context *tc, struct psinfo *psi)
} else
fprintf(fp, " ");
- fprintf(fp, "%5ld %5ld %2s %s %3s",
+ fprintf(fp, "%7ld %7ld %3s %s %3s",
tc->pid, task_to_pid(tc->ptask),
task_cpu(tc->processor, buf2, !VERBOSE),
task_pointer_string(tc, flag & PS_KSTACKP, buf3),
@@ -3838,8 +3838,8 @@ show_ps_data(ulong flag, struct task_context *tc, struct psinfo *psi)
if (strlen(buf1) == 3)
mkstring(buf1, 4, CENTER|RJUST, NULL);
fprintf(fp, "%s ", buf1);
- fprintf(fp, "%7ld ", (tm->total_vm * PAGESIZE())/1024);
- fprintf(fp, "%6ld ", (tm->rss * PAGESIZE())/1024);
+ fprintf(fp, "%8ld ", (tm->total_vm * PAGESIZE())/1024);
+ fprintf(fp, "%8ld ", (tm->rss * PAGESIZE())/1024);
if (is_kernel_thread(tc->task))
fprintf(fp, "[%s]\n", tc->comm);
else
@@ -3856,7 +3856,7 @@ show_ps(ulong flag, struct psinfo *psi)
if (!(flag & ((PS_EXCLUSIVE & ~PS_ACTIVE)|PS_NO_HEADER)))
fprintf(fp,
- " PID PPID CPU %s ST %%MEM VSZ RSS COMM\n",
+ " PID PPID CPU %s ST %%MEM VSZ RSS COMM\n",
flag & PS_KSTACKP ?
mkstring(buf, VADDR_PRLEN, CENTER|RJUST, "KSTACKP") :
mkstring(buf, VADDR_PRLEN, CENTER, "TASK"));
@@ -7713,7 +7713,7 @@ print_task_header(FILE *out, struct task_context *tc, int newline)
char buf[BUFSIZE];
char buf1[BUFSIZE];
- fprintf(out, "%sPID: %-5ld TASK: %s CPU: %-2s COMMAND: \"%s\"\n",
+ fprintf(out, "%sPID: %-7ld TASK: %s CPU: %-3s COMMAND: \"%s\"\n",
newline ? "\n" : "", tc->pid,
mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, MKSTR(tc->task)),
task_cpu(tc->processor, buf, !VERBOSE), tc->comm);
--
2.31.1
2 years, 5 months
Re: [Crash-utility] [PATCH] Fix for "dev" command on Linux 5.11 and later
by lijiang
Hi, Kazu
Thank you for the fix.
On Wed, Jun 15, 2022 at 8:00 PM <crash-utility-request(a)redhat.com> wrote:
> Date: Wed, 15 Jun 2022 01:50:13 +0000
> From: HAGIO KAZUHITO(?????) <k-hagio-ab(a)nec.com>
> To: "lijiang(a)redhat.com" <lijiang(a)redhat.com>,
> "crash-utility(a)redhat.com" <crash-utility(a)redhat.com>
> Subject: [Crash-utility] [PATCH] Fix for "dev" command on Linux 5.11
> and later
> Message-ID: <1655257808-3245-1-git-send-email-k-hagio-ab(a)nec.com>
> Content-Type: text/plain; charset="iso-2022-jp"
>
> The following kernel commits eventually removed the bdev_map array in
> Linux v5.11 kernel:
>
> e418de3abcda ("block: switch gendisk lookup to a simple xarray")
> 22ae8ce8b892 ("block: simplify bdev/disk lookup in blkdev_get")
>
> Without the patch, the "dev" command fails to dump block device data
> with the following error:
>
> crash> dev
> ...
> dev: blkdevs or all_bdevs: symbols do not exist
>
> To get block device's gendisk, search blockdev_superblock.s_inodes
> instead of bdev_map.
>
> Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
> ---
> dev.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 71 insertions(+), 5 deletions(-)
>
> diff --git a/dev.c b/dev.c
> index db97f8aebdc2..238dfe0fbe3c 100644
> --- a/dev.c
> +++ b/dev.c
> @@ -24,6 +24,7 @@ static void dump_blkdevs_v2(ulong);
> static void dump_blkdevs_v3(ulong);
> static ulong search_cdev_map_probes(char *, int, int, ulong *);
> static ulong search_bdev_map_probes(char *, int, int, ulong *);
> +static ulong search_blockdev_inodes(int, ulong *);
>
It could be good to be consistent with the above function name, I would
suggest renaming
the "search_blockdev_inodes()" to "search_sb_inodes()".
static void do_pci(void);
> static void do_pci2(void);
> static void do_io(void);
> @@ -493,9 +494,10 @@ dump_blkdevs(ulong flags)
> ulong ops;
> } blkdevs[MAX_DEV], *bp;
>
> - if (kernel_symbol_exists("major_names") &&
> - kernel_symbol_exists("bdev_map")) {
> - dump_blkdevs_v3(flags);
> + if (kernel_symbol_exists("major_names") &&
> + (kernel_symbol_exists("bdev_map") ||
> + kernel_symbol_exists("blockdev_superblock"))) {
> + dump_blkdevs_v3(flags);
> return;
> }
>
> @@ -717,6 +719,7 @@ dump_blkdevs_v3(ulong flags)
> char buf[BUFSIZE];
> uint major;
> ulong gendisk, addr, fops;
> + int use_bdev_map = kernel_symbol_exists("bdev_map");
>
> if (!(len = get_array_length("major_names", NULL, 0)))
> len = MAX_DEV;
> @@ -745,8 +748,11 @@ dump_blkdevs_v3(ulong flags)
> strncpy(buf, blk_major_name_buf +
> OFFSET(blk_major_name_name), 16);
>
> - fops = search_bdev_map_probes(buf, major == i ? major : i,
> - UNUSED, &gendisk);
> + if (use_bdev_map)
> + fops = search_bdev_map_probes(buf, major == i ?
> major : i,
> + UNUSED, &gendisk);
> + else /* v5.11 and later */
> + fops = search_blockdev_inodes(major, &gendisk);
>
> if (CRASHDEBUG(1))
> fprintf(fp, "blk_major_name: %lx block major: %d
> name: %s gendisk: %lx fops: %lx\n",
> @@ -829,6 +835,66 @@ search_bdev_map_probes(char *name, int major, int
> minor, ulong *gendisk)
> return fops;
> }
>
> +/* For bdev_inode. See block/bdev.c */
> +#define I_BDEV(inode) (inode - SIZE(block_device))
> +
>
Good understanding, this is equivalent to the contain_of().
+static ulong
> +search_blockdev_inodes(int major, ulong *gendisk)
> +{
> + struct list_data list_data, *ld;
> + ulong addr, bd_sb, disk, fops = 0;
> + int i, inode_count, gendisk_major;
> + char *gendisk_buf;
> +
> + ld = &list_data;
> + BZERO(ld, sizeof(struct list_data));
> +
> + get_symbol_data("blockdev_superblock", sizeof(void *), &bd_sb);
> +
> + addr = bd_sb + OFFSET(super_block_s_inodes);
> + if (!readmem(addr, KVADDR, &ld->start, sizeof(ulong),
> + "blockdev_superblock.s_inodes", QUIET|RETURN_ON_ERROR))
> + return 0;
> +
> + if (empty_list(ld->start))
> + return 0;
> +
> + ld->flags |= LIST_ALLOCATE;
> + ld->end = bd_sb + OFFSET(super_block_s_inodes);
> + ld->list_head_offset = OFFSET(inode_i_sb_list);
> +
> + inode_count = do_list(ld);
> +
> + gendisk_buf = GETBUF(SIZE(gendisk));
> +
> + for (i = 0; i < inode_count; i++) {
> + addr = I_BDEV(ld->list_ptr[i]) +
> OFFSET(block_device_bd_disk);
> + if (!readmem(addr, KVADDR, &disk, sizeof(ulong),
> + "block_device.bd_disk", QUIET|RETURN_ON_ERROR))
> + continue;
> +
> + if (!disk)
> + continue;
> +
> + if (!readmem(disk, KVADDR, gendisk_buf, SIZE(gendisk),
> + "gendisk buffer", QUIET|RETURN_ON_ERROR))
> + continue;
> +
> + gendisk_major = INT(gendisk_buf + OFFSET(gendisk_major));
> + if (gendisk_major != major)
> + continue;
> +
> + fops = ULONG(gendisk_buf + OFFSET(gendisk_fops));
> + if (fops) {
> + *gendisk = disk;
> + break;
> + }
> + }
> +
>
Because the ld->flags is set to LIST_ALLOCATE, here need to free it as
below:
FREEBUF(ld->list_ptr);
Thanks.
Lianbo
+ FREEBUF(gendisk_buf);
> + return fops;
> +}
> +
> void
> dump_dev_table(void)
> {
> --
> 2.31.1
>
2 years, 5 months
[PATCH] Fix for "dev" command on Linux 5.11 and later
by HAGIO KAZUHITO(萩尾 一仁)
The following kernel commits eventually removed the bdev_map array in
Linux v5.11 kernel:
e418de3abcda ("block: switch gendisk lookup to a simple xarray")
22ae8ce8b892 ("block: simplify bdev/disk lookup in blkdev_get")
Without the patch, the "dev" command fails to dump block device data
with the following error:
crash> dev
...
dev: blkdevs or all_bdevs: symbols do not exist
To get block device's gendisk, search blockdev_superblock.s_inodes
instead of bdev_map.
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
dev.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 71 insertions(+), 5 deletions(-)
diff --git a/dev.c b/dev.c
index db97f8aebdc2..238dfe0fbe3c 100644
--- a/dev.c
+++ b/dev.c
@@ -24,6 +24,7 @@ static void dump_blkdevs_v2(ulong);
static void dump_blkdevs_v3(ulong);
static ulong search_cdev_map_probes(char *, int, int, ulong *);
static ulong search_bdev_map_probes(char *, int, int, ulong *);
+static ulong search_blockdev_inodes(int, ulong *);
static void do_pci(void);
static void do_pci2(void);
static void do_io(void);
@@ -493,9 +494,10 @@ dump_blkdevs(ulong flags)
ulong ops;
} blkdevs[MAX_DEV], *bp;
- if (kernel_symbol_exists("major_names") &&
- kernel_symbol_exists("bdev_map")) {
- dump_blkdevs_v3(flags);
+ if (kernel_symbol_exists("major_names") &&
+ (kernel_symbol_exists("bdev_map") ||
+ kernel_symbol_exists("blockdev_superblock"))) {
+ dump_blkdevs_v3(flags);
return;
}
@@ -717,6 +719,7 @@ dump_blkdevs_v3(ulong flags)
char buf[BUFSIZE];
uint major;
ulong gendisk, addr, fops;
+ int use_bdev_map = kernel_symbol_exists("bdev_map");
if (!(len = get_array_length("major_names", NULL, 0)))
len = MAX_DEV;
@@ -745,8 +748,11 @@ dump_blkdevs_v3(ulong flags)
strncpy(buf, blk_major_name_buf +
OFFSET(blk_major_name_name), 16);
- fops = search_bdev_map_probes(buf, major == i ? major : i,
- UNUSED, &gendisk);
+ if (use_bdev_map)
+ fops = search_bdev_map_probes(buf, major == i ? major : i,
+ UNUSED, &gendisk);
+ else /* v5.11 and later */
+ fops = search_blockdev_inodes(major, &gendisk);
if (CRASHDEBUG(1))
fprintf(fp, "blk_major_name: %lx block major: %d name: %s gendisk: %lx fops: %lx\n",
@@ -829,6 +835,66 @@ search_bdev_map_probes(char *name, int major, int minor, ulong *gendisk)
return fops;
}
+/* For bdev_inode. See block/bdev.c */
+#define I_BDEV(inode) (inode - SIZE(block_device))
+
+static ulong
+search_blockdev_inodes(int major, ulong *gendisk)
+{
+ struct list_data list_data, *ld;
+ ulong addr, bd_sb, disk, fops = 0;
+ int i, inode_count, gendisk_major;
+ char *gendisk_buf;
+
+ ld = &list_data;
+ BZERO(ld, sizeof(struct list_data));
+
+ get_symbol_data("blockdev_superblock", sizeof(void *), &bd_sb);
+
+ addr = bd_sb + OFFSET(super_block_s_inodes);
+ if (!readmem(addr, KVADDR, &ld->start, sizeof(ulong),
+ "blockdev_superblock.s_inodes", QUIET|RETURN_ON_ERROR))
+ return 0;
+
+ if (empty_list(ld->start))
+ return 0;
+
+ ld->flags |= LIST_ALLOCATE;
+ ld->end = bd_sb + OFFSET(super_block_s_inodes);
+ ld->list_head_offset = OFFSET(inode_i_sb_list);
+
+ inode_count = do_list(ld);
+
+ gendisk_buf = GETBUF(SIZE(gendisk));
+
+ for (i = 0; i < inode_count; i++) {
+ addr = I_BDEV(ld->list_ptr[i]) + OFFSET(block_device_bd_disk);
+ if (!readmem(addr, KVADDR, &disk, sizeof(ulong),
+ "block_device.bd_disk", QUIET|RETURN_ON_ERROR))
+ continue;
+
+ if (!disk)
+ continue;
+
+ if (!readmem(disk, KVADDR, gendisk_buf, SIZE(gendisk),
+ "gendisk buffer", QUIET|RETURN_ON_ERROR))
+ continue;
+
+ gendisk_major = INT(gendisk_buf + OFFSET(gendisk_major));
+ if (gendisk_major != major)
+ continue;
+
+ fops = ULONG(gendisk_buf + OFFSET(gendisk_fops));
+ if (fops) {
+ *gendisk = disk;
+ break;
+ }
+ }
+
+ FREEBUF(gendisk_buf);
+ return fops;
+}
+
void
dump_dev_table(void)
{
--
2.31.1
2 years, 5 months
[PATCH 1/2] sbitmapq: Fix for kernels without struct wait_queue_head
by HAGIO KAZUHITO(萩尾 一仁)
The current struct wait_queue_head was renamed by kernel commit
9d9d676f595b ("sched/wait: Standardize internal naming of wait-queue heads")
at Linux 4.13. Without the patch, on earlier kernels the "sbitmapq"
command fails with the following error:
crash> sbitmapq ffff8801790b3b50
depth = 128
busy = 0
bits_per_word = 32
...
sbitmapq: invalid structure member offset: wait_queue_head_head
FILE: sbitmap.c LINE: 344 FUNCTION: sbitmap_queue_show()
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
sbitmap.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/sbitmap.c b/sbitmap.c
index bb2f19e6207b..be5d30a8ea88 100644
--- a/sbitmap.c
+++ b/sbitmap.c
@@ -341,7 +341,10 @@ static void sbitmap_queue_show(const struct sbitmap_queue_context *sqc,
sbq_wait_state_size = SIZE(sbq_wait_state);
wait_cnt_off = OFFSET(sbq_wait_state_wait_cnt);
wait_off = OFFSET(sbq_wait_state_wait);
- list_head_off = OFFSET(wait_queue_head_head);
+ if (VALID_MEMBER(wait_queue_head_head)) /* 4.13 and later */
+ list_head_off = OFFSET(wait_queue_head_head);
+ else
+ list_head_off = OFFSET(__wait_queue_head_task_list);
sbq_wait_state_buf = GETBUF(sbq_wait_state_size);
--
2.31.1
2 years, 5 months
[PATCH] Make "dev -d|-D" options parse sbitmap on Linux 4.18 and later
by HAGIO KAZUHITO(萩尾 一仁)
There have been a few reports that the "dev -d|-D" options displayed
incorrect I/O stats due to racy blk_mq_ctx.rq_* counters. To fix it,
make the options parse sbitmap to count I/O stats on Linux 4.18 and
later kernels, which include RHEL8 ones.
To do this, adjust to the blk_mq_tags structure of Linux 5.10 through
5.15 kernels, which contain kernel commit 222a5ae03cdd ("blk-mq: Use
pointers for blk_mq_tags bitmap tags") and do not contain ae0f1a732f4a
("blk-mq: Stop using pointers for blk_mq_tags bitmap tags").
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
dev.c | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/dev.c b/dev.c
index 0172c83ffaea..1685f9302837 100644
--- a/dev.c
+++ b/dev.c
@@ -4339,6 +4339,10 @@ static void bt_for_each(ulong q, ulong tags, ulong sbq, uint reserved, uint nr_r
static void queue_for_each_hw_ctx(ulong q, ulong *hctx, uint cnt, struct diskio *dio)
{
uint i;
+ int bitmap_tags_is_ptr = 0;
+
+ if (MEMBER_TYPE("blk_mq_tags", "bitmap_tags") == TYPE_CODE_PTR)
+ bitmap_tags_is_ptr = 1;
for (i = 0; i < cnt; i++) {
ulong addr = 0, tags = 0;
@@ -4357,9 +4361,17 @@ static void queue_for_each_hw_ctx(ulong q, ulong *hctx, uint cnt, struct diskio
if (nr_reserved_tags) {
addr = tags + OFFSET(blk_mq_tags_breserved_tags);
+ if (bitmap_tags_is_ptr &&
+ !readmem(addr, KVADDR, &addr, sizeof(ulong),
+ "blk_mq_tags.bitmap_tags", RETURN_ON_ERROR))
+ break;
bt_for_each(q, tags, addr, 1, nr_reserved_tags, dio);
}
addr = tags + OFFSET(blk_mq_tags_bitmap_tags);
+ if (bitmap_tags_is_ptr &&
+ !readmem(addr, KVADDR, &addr, sizeof(ulong),
+ "blk_mq_tags.bitmap_tags", RETURN_ON_ERROR))
+ break;
bt_for_each(q, tags, addr, 0, nr_reserved_tags, dio);
}
}
@@ -4423,14 +4435,23 @@ get_mq_diskio(unsigned long q, unsigned long *mq_count)
unsigned long mctx_addr;
struct diskio tmp = {0};
- if (INVALID_MEMBER(blk_mq_ctx_rq_dispatched) ||
- INVALID_MEMBER(blk_mq_ctx_rq_completed)) {
+ /*
+ * Currently this function does not support old blk-mq implementation
+ * before 12f5b9314545 ("blk-mq: Remove generation seqeunce"), so
+ * filter them out.
+ */
+ if (VALID_MEMBER(request_state)) {
+ if (CRASHDEBUG(1))
+ fprintf(fp, "mq: using sbitmap\n");
get_mq_diskio_from_hw_queues(q, &tmp);
mq_count[0] = tmp.read;
mq_count[1] = tmp.write;
return;
}
+ if (CRASHDEBUG(1))
+ fprintf(fp, "mq: using blk_mq_ctx counters\n");
+
readmem(q + OFFSET(request_queue_queue_ctx), KVADDR, &queue_ctx,
sizeof(ulong), "request_queue.queue_ctx",
FAULT_ON_ERROR);
--
2.31.1
2 years, 5 months
[PATCH 2/2] sbitmapq: Limit kernels without sbitmap again
by Kazuhito Hagio
commit 364b2e413c69 ("sbitmapq: remove struct and member validation
in sbitmapq_init()") lifted the use of the "sbitmapq" command
unconditionally. Without the patch, the command fails with the
following error on kernels without sbitmap:
crash> sbitmapq ffff88015796e550
sbitmapq: invalid structure member offset: sbitmap_queue_sb
FILE: sbitmap.c LINE: 385 FUNCTION: sbitmap_queue_context_load()
Now the command supports Linux 4.9 and later kernels since it was
abstracted out, so it can be limited by the non-existence of the
sbitmap structure.
Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
---
sbitmap.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/sbitmap.c b/sbitmap.c
index be5d30a8ea88..12d6512a1e4d 100644
--- a/sbitmap.c
+++ b/sbitmap.c
@@ -540,6 +540,10 @@ void sbitmapq_init(void)
STRUCT_SIZE_INIT(sbitmap_queue, "sbitmap_queue");
STRUCT_SIZE_INIT(sbq_wait_state, "sbq_wait_state");
+ /* sbitmap was abstracted out by commit 88459642cba4 on Linux 4.9. */
+ if (INVALID_SIZE(sbitmap))
+ command_not_supported();
+
MEMBER_OFFSET_INIT(sbitmap_word_depth, "sbitmap_word", "depth");
MEMBER_OFFSET_INIT(sbitmap_word_word, "sbitmap_word", "word");
MEMBER_OFFSET_INIT(sbitmap_word_cleared, "sbitmap_word", "cleared");
--
2.31.1
2 years, 5 months
Re: [Crash-utility] [PATCH 2/3] sbitmapq: Fix for sbitmap_word without cleared member
by lijiang
Hi, Kazu
On Fri, Jun 10, 2022 at 10:55 AM Kazuhito Hagio <k-hagio-ab(a)nec.com> wrote:
> The sbitmap_word.cleared member was added by kernel commit ea86ea2cdced
> ("sbitmap: ammortize cost of clearing bits") at Linux 5.0. Without the
> patch, on earlier kernels the "sbitmapq" command fails with the
> following error:
>
> crash> sbitmapq ffff8f1a3611cf10
>
> sbitmapq: invalid structure member offset: sbitmap_word_cleared
> FILE: sbitmap.c LINE: 92 FUNCTION: __sbitmap_weight()
>
> Signed-off-by: Kazuhito Hagio <k-hagio-ab(a)nec.com>
> ---
> sbitmap.c | 26 ++++++++++++++++++--------
> 1 file changed, 18 insertions(+), 8 deletions(-)
>
> diff --git a/sbitmap.c b/sbitmap.c
> index 37db21d15219..c8c9f2b6d003 100644
> --- a/sbitmap.c
> +++ b/sbitmap.c
> @@ -89,7 +89,6 @@ static unsigned int __sbitmap_weight(const struct
> sbitmap_context *sc, bool set)
> {
> const ulong sbitmap_word_size = SIZE(sbitmap_word);
> const ulong w_word_off = OFFSET(sbitmap_word_word);
> - const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
>
> unsigned int weight = 0;
> ulong addr = sc->map_addr;
> @@ -111,7 +110,10 @@ static unsigned int __sbitmap_weight(const struct
> sbitmap_context *sc, bool set)
> word = ULONG(sbitmap_word_buf + w_word_off);
> weight += bitmap_weight(word, depth);
> } else {
> - cleared = ULONG(sbitmap_word_buf + w_cleared_off);
> + if (VALID_MEMBER(sbitmap_word_cleared))
> + cleared = ULONG(sbitmap_word_buf +
> OFFSET(sbitmap_word_cleared));
> + else
> + cleared = 0;
> weight += bitmap_weight(cleared, depth);
> }
>
> @@ -130,7 +132,10 @@ static unsigned int sbitmap_weight(const struct
> sbitmap_context *sc)
>
> static unsigned int sbitmap_cleared(const struct sbitmap_context *sc)
> {
> - return __sbitmap_weight(sc, false);
> + if (VALID_MEMBER(sbitmap_word_cleared)) /* 5.0 and later */
> + return __sbitmap_weight(sc, false);
> + else
>
The above "else" can be removed, and the result is the same.
Other changes look good to me, for these three patches:
Acked-by: Lianbo Jiang <lijiang(a)redhat.com>
Thanks.
+ return 0;
> }
>
> static void sbitmap_emit_byte(unsigned int offset, uint8_t byte)
> @@ -149,7 +154,6 @@ static void sbitmap_bitmap_show(const struct
> sbitmap_context *sc)
> {
> const ulong sbitmap_word_size = SIZE(sbitmap_word);
> const ulong w_word_off = OFFSET(sbitmap_word_word);
> - const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
>
> uint8_t byte = 0;
> unsigned int byte_bits = 0;
> @@ -169,7 +173,10 @@ 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);
> + if (VALID_MEMBER(sbitmap_word_cleared))
> + cleared = ULONG(sbitmap_word_buf +
> OFFSET(sbitmap_word_cleared));
> + else
> + cleared = 0;
> word_bits = __map_depth(sc, i);
>
> word &= ~cleared;
> @@ -219,7 +226,6 @@ static void __sbitmap_for_each_set(const struct
> sbitmap_context *sc,
> {
> const ulong sbitmap_word_size = SIZE(sbitmap_word);
> const ulong w_word_off = OFFSET(sbitmap_word_word);
> - const ulong w_cleared_off = OFFSET(sbitmap_word_cleared);
>
> unsigned int index;
> unsigned int nr;
> @@ -245,7 +251,10 @@ static void __sbitmap_for_each_set(const struct
> sbitmap_context *sc,
> }
>
> w_word = ULONG(sbitmap_word_buf + w_word_off);
> - w_cleared = ULONG(sbitmap_word_buf + w_cleared_off);
> + if (VALID_MEMBER(sbitmap_word_cleared))
> + w_cleared = ULONG(sbitmap_word_buf +
> OFFSET(sbitmap_word_cleared));
> + else
> + w_cleared = 0;
>
> depth = min(__map_depth(sc, index) - nr, sc->depth -
> scanned);
>
> @@ -297,7 +306,8 @@ static void sbitmap_queue_show(const struct
> sbitmap_queue_context *sqc,
>
> fprintf(fp, "depth = %u\n", sc->depth);
> fprintf(fp, "busy = %u\n", sbitmap_weight(sc) -
> sbitmap_cleared(sc));
> - fprintf(fp, "cleared = %u\n", sbitmap_cleared(sc));
> + if (VALID_MEMBER(sbitmap_word_cleared)) /* 5.0 and later */
> + fprintf(fp, "cleared = %u\n", sbitmap_cleared(sc));
> fprintf(fp, "bits_per_word = %u\n", 1U << sc->shift);
> fprintf(fp, "map_nr = %u\n", sc->map_nr);
>
> --
> 2.27.0
>
>
2 years, 5 months