147 lines
4.1 KiB
Diff
147 lines
4.1 KiB
Diff
|
From f623cad20b092002d627a03451ea256add2e53d0 Mon Sep 17 00:00:00 2001
|
||
|
From: Kazuhito Hagio <k-hagio-ab@nec.com>
|
||
|
Date: Wed, 15 Jun 2022 10:50:13 +0900
|
||
|
Subject: [PATCH 01/28] Fix for "dev" command on Linux 5.11 and later
|
||
|
|
||
|
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@nec.com>
|
||
|
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
|
||
|
---
|
||
|
dev.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
||
|
1 file changed, 72 insertions(+), 5 deletions(-)
|
||
|
|
||
|
diff --git a/dev.c b/dev.c
|
||
|
index db97f8aebdc2..75d30bd022a1 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,67 @@ 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(ld->list_ptr);
|
||
|
+ FREEBUF(gendisk_buf);
|
||
|
+ return fops;
|
||
|
+}
|
||
|
+
|
||
|
void
|
||
|
dump_dev_table(void)
|
||
|
{
|
||
|
--
|
||
|
2.37.1
|
||
|
|