Fix for the "dev -[dD]" options on Linux 5.1-rc1 and later
kernels
that contain commit 570d0200123fb4f809aa2f6226e93a458d664d70,
titled "driver core: move device->knode_class to device_private".
Without the patch, the commands fail with the following error message:
dev: invalid structure member offset: device_knode_class
FILE: dev.c LINE: 4046 FUNCTION: match_klist()
Signed-off-by: Kazuhito Hagio <k-hagio(a)ab.jp.nec.com>
---
defs.h | 1 +
dev.c | 34 ++++++++++++++++++++++++++++++++--
symbols.c | 2 ++
3 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index 2466681..db192f3 100644
--- a/defs.h
+++ b/defs.h
@@ -2068,6 +2068,7 @@ struct offset_table { /* stash of
commonly-used offsets */
long disk_stats_in_flight;
long cpu_context_save_r7;
long dentry_d_sb;
+ long device_private_knode_class;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/dev.c b/dev.c
index 24efea2..91b81f3 100644
--- a/dev.c
+++ b/dev.c
@@ -4020,6 +4020,21 @@ get_gendisk_4(unsigned long entry)
OFFSET(gendisk_part0);
}
+/* kernel version >= 5.1 */
+static unsigned long
+get_gendisk_5(unsigned long entry)
+{
+ unsigned long device_address;
+ unsigned long device_private_address;
+
+ device_private_address = entry - OFFSET(device_private_knode_class);
+ readmem(device_private_address + OFFSET(device_private_device),
+ KVADDR, &device_address, sizeof(device_address),
+ "device_private.device", FAULT_ON_ERROR);
+
+ return device_address - OFFSET(hd_struct_dev) - OFFSET(gendisk_part0);
+}
+
/* 2.6.24 < kernel version <= 2.6.27 */
static int
match_list(struct iter *i, unsigned long entry)
@@ -4042,8 +4057,18 @@ match_klist(struct iter *i, unsigned long entry)
{
unsigned long device_address;
unsigned long device_type;
+ unsigned long device_private_address;
- device_address = entry - OFFSET(device_knode_class);
+ if (VALID_MEMBER(device_knode_class))
+ device_address = entry - OFFSET(device_knode_class);
+ else {
+ /* kernel version >= 5.1 */
+ device_private_address = entry -
+ OFFSET(device_private_knode_class);
+ readmem(device_private_address + OFFSET(device_private_device),
+ KVADDR, &device_address, sizeof(device_address),
+ "device_private.device", FAULT_ON_ERROR);
+ }
readmem(device_address + OFFSET(device_type), KVADDR, &device_type,
sizeof(device_type), "device.type", FAULT_ON_ERROR);
if (device_type != i->type_address)
@@ -4348,8 +4373,10 @@ init_iter(struct iter *i)
i->match = match_klist;
if (VALID_MEMBER(gendisk_dev))
i->get_gendisk = get_gendisk_3;
- else
+ else if (VALID_MEMBER(device_knode_class))
i->get_gendisk = get_gendisk_4;
+ else
+ i->get_gendisk = get_gendisk_5;
}
} else {
option_not_supported('d');
@@ -4470,6 +4497,9 @@ void diskio_init(void)
MEMBER_OFFSET_INIT(device_knode_class, "device", "knode_class");
MEMBER_OFFSET_INIT(device_node, "device", "node");
MEMBER_OFFSET_INIT(device_type, "device", "type");
+ MEMBER_OFFSET_INIT(device_private_device, "device_private",
"device");
+ MEMBER_OFFSET_INIT(device_private_knode_class, "device_private",
+ "knode_class");
MEMBER_OFFSET_INIT(gendisk_dev, "gendisk", "dev");
if (INVALID_MEMBER(gendisk_dev))
MEMBER_OFFSET_INIT(gendisk_dev, "gendisk", "__dev");
diff --git a/symbols.c b/symbols.c
index 1ed75fe..da68eda 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10113,6 +10113,8 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(device_private_device));
fprintf(fp, " device_private_knode_bus: %ld\n",
OFFSET(device_private_knode_bus));
+ fprintf(fp, " device_private_knode_class: %ld\n",
+ OFFSET(device_private_knode_class));
fprintf(fp, " gendisk_dev: %ld\n",
OFFSET(gendisk_dev));
fprintf(fp, " gendisk_kobj: %ld\n",
--
2.18.1
--
Crash-utility mailing list
Crash-utility(a)redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility