Blame SOURCES/0001-Fix-for-dev-command-on-Linux-5.11-and-later.patch

3ce5e9
From f623cad20b092002d627a03451ea256add2e53d0 Mon Sep 17 00:00:00 2001
3ce5e9
From: Kazuhito Hagio <k-hagio-ab@nec.com>
3ce5e9
Date: Wed, 15 Jun 2022 10:50:13 +0900
3ce5e9
Subject: [PATCH 01/28] Fix for "dev" command on Linux 5.11 and later
3ce5e9
3ce5e9
The following kernel commits eventually removed the bdev_map array in
3ce5e9
Linux v5.11 kernel:
3ce5e9
3ce5e9
  e418de3abcda ("block: switch gendisk lookup to a simple xarray")
3ce5e9
  22ae8ce8b892 ("block: simplify bdev/disk lookup in blkdev_get")
3ce5e9
3ce5e9
Without the patch, the "dev" command fails to dump block device data
3ce5e9
with the following error:
3ce5e9
3ce5e9
  crash> dev
3ce5e9
  ...
3ce5e9
  dev: blkdevs or all_bdevs: symbols do not exist
3ce5e9
3ce5e9
To get block device's gendisk, search blockdev_superblock.s_inodes
3ce5e9
instead of bdev_map.
3ce5e9
3ce5e9
Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
3ce5e9
Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
3ce5e9
---
3ce5e9
 dev.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
3ce5e9
 1 file changed, 72 insertions(+), 5 deletions(-)
3ce5e9
3ce5e9
diff --git a/dev.c b/dev.c
3ce5e9
index db97f8aebdc2..75d30bd022a1 100644
3ce5e9
--- a/dev.c
3ce5e9
+++ b/dev.c
3ce5e9
@@ -24,6 +24,7 @@ static void dump_blkdevs_v2(ulong);
3ce5e9
 static void dump_blkdevs_v3(ulong);
3ce5e9
 static ulong search_cdev_map_probes(char *, int, int, ulong *);
3ce5e9
 static ulong search_bdev_map_probes(char *, int, int, ulong *);
3ce5e9
+static ulong search_blockdev_inodes(int, ulong *);
3ce5e9
 static void do_pci(void); 
3ce5e9
 static void do_pci2(void);
3ce5e9
 static void do_io(void);
3ce5e9
@@ -493,9 +494,10 @@ dump_blkdevs(ulong flags)
3ce5e9
                 ulong ops;
3ce5e9
         } blkdevs[MAX_DEV], *bp;
3ce5e9
 
3ce5e9
-	if (kernel_symbol_exists("major_names") && 
3ce5e9
-	    kernel_symbol_exists("bdev_map")) {
3ce5e9
-                dump_blkdevs_v3(flags);
3ce5e9
+	if (kernel_symbol_exists("major_names") &&
3ce5e9
+	    (kernel_symbol_exists("bdev_map") ||
3ce5e9
+	     kernel_symbol_exists("blockdev_superblock"))) {
3ce5e9
+		dump_blkdevs_v3(flags);
3ce5e9
 		return;
3ce5e9
 	}
3ce5e9
 
3ce5e9
@@ -717,6 +719,7 @@ dump_blkdevs_v3(ulong flags)
3ce5e9
 	char buf[BUFSIZE];
3ce5e9
 	uint major;
3ce5e9
 	ulong gendisk, addr, fops;
3ce5e9
+	int use_bdev_map = kernel_symbol_exists("bdev_map");
3ce5e9
 	
3ce5e9
 	if (!(len = get_array_length("major_names", NULL, 0)))
3ce5e9
 		len = MAX_DEV;
3ce5e9
@@ -745,8 +748,11 @@ dump_blkdevs_v3(ulong flags)
3ce5e9
 		strncpy(buf, blk_major_name_buf +  
3ce5e9
 			OFFSET(blk_major_name_name), 16);
3ce5e9
 
3ce5e9
-		fops = search_bdev_map_probes(buf, major == i ? major : i, 
3ce5e9
-			UNUSED, &gendisk);
3ce5e9
+		if (use_bdev_map)
3ce5e9
+			fops = search_bdev_map_probes(buf, major == i ? major : i,
3ce5e9
+				UNUSED, &gendisk);
3ce5e9
+		else /* v5.11 and later */
3ce5e9
+			fops = search_blockdev_inodes(major, &gendisk);
3ce5e9
 
3ce5e9
 		if (CRASHDEBUG(1))
3ce5e9
 			fprintf(fp, "blk_major_name: %lx block major: %d name: %s gendisk: %lx fops: %lx\n", 
3ce5e9
@@ -829,6 +835,67 @@ search_bdev_map_probes(char *name, int major, int minor, ulong *gendisk)
3ce5e9
 	return fops;
3ce5e9
 }
3ce5e9
 
3ce5e9
+/* For bdev_inode.  See block/bdev.c */
3ce5e9
+#define I_BDEV(inode) (inode - SIZE(block_device))
3ce5e9
+
3ce5e9
+static ulong
3ce5e9
+search_blockdev_inodes(int major, ulong *gendisk)
3ce5e9
+{
3ce5e9
+	struct list_data list_data, *ld;
3ce5e9
+	ulong addr, bd_sb, disk, fops = 0;
3ce5e9
+	int i, inode_count, gendisk_major;
3ce5e9
+	char *gendisk_buf;
3ce5e9
+
3ce5e9
+	ld = &list_data;
3ce5e9
+	BZERO(ld, sizeof(struct list_data));
3ce5e9
+
3ce5e9
+	get_symbol_data("blockdev_superblock", sizeof(void *), &bd_sb);
3ce5e9
+
3ce5e9
+	addr = bd_sb + OFFSET(super_block_s_inodes);
3ce5e9
+	if (!readmem(addr, KVADDR, &ld->start, sizeof(ulong),
3ce5e9
+	    "blockdev_superblock.s_inodes", QUIET|RETURN_ON_ERROR))
3ce5e9
+		return 0;
3ce5e9
+
3ce5e9
+	if (empty_list(ld->start))
3ce5e9
+		return 0;
3ce5e9
+
3ce5e9
+	ld->flags |= LIST_ALLOCATE;
3ce5e9
+	ld->end = bd_sb + OFFSET(super_block_s_inodes);
3ce5e9
+	ld->list_head_offset = OFFSET(inode_i_sb_list);
3ce5e9
+
3ce5e9
+	inode_count = do_list(ld);
3ce5e9
+
3ce5e9
+	gendisk_buf = GETBUF(SIZE(gendisk));
3ce5e9
+
3ce5e9
+	for (i = 0; i < inode_count; i++) {
3ce5e9
+		addr = I_BDEV(ld->list_ptr[i]) + OFFSET(block_device_bd_disk);
3ce5e9
+		if (!readmem(addr, KVADDR, &disk, sizeof(ulong),
3ce5e9
+		    "block_device.bd_disk", QUIET|RETURN_ON_ERROR))
3ce5e9
+			continue;
3ce5e9
+
3ce5e9
+		if (!disk)
3ce5e9
+			continue;
3ce5e9
+
3ce5e9
+		if (!readmem(disk, KVADDR, gendisk_buf, SIZE(gendisk),
3ce5e9
+		    "gendisk buffer", QUIET|RETURN_ON_ERROR))
3ce5e9
+			continue;
3ce5e9
+
3ce5e9
+		gendisk_major = INT(gendisk_buf + OFFSET(gendisk_major));
3ce5e9
+		if (gendisk_major != major)
3ce5e9
+			continue;
3ce5e9
+
3ce5e9
+		fops = ULONG(gendisk_buf + OFFSET(gendisk_fops));
3ce5e9
+		if (fops) {
3ce5e9
+			*gendisk = disk;
3ce5e9
+			break;
3ce5e9
+		}
3ce5e9
+	}
3ce5e9
+
3ce5e9
+	FREEBUF(ld->list_ptr);
3ce5e9
+	FREEBUF(gendisk_buf);
3ce5e9
+	return fops;
3ce5e9
+}
3ce5e9
+
3ce5e9
 void
3ce5e9
 dump_dev_table(void)
3ce5e9
 {
3ce5e9
-- 
3ce5e9
2.37.1
3ce5e9