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@xxxxxxxxxxxxx> --- 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@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility