[PATCH] Fix failure of "dev -d|-D" options on Linux 6.4 and later kernels

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Kernel commit 2df418cf4b72 ("driver core: class: remove subsystem
private pointer from struct class"), which is contained in Linux 6.4 and
later kernels, removed the class.p member for struct subsys_private.  As
a result, the "dev -d|-D" options fail with the following error.

  dev: invalid structure member offset: class_p
       FILE: dev.c  LINE: 4689  FUNCTION: init_iter()

Search the class_kset list for the subsys_private of block class to fix
this.

As a preparation, introduce get_subsys_private() function, which is
abstracted from the same search procedure in init_memory_block().

Signed-off-by: Kazuhito Hagio <k-hagio-ab@xxxxxxx>
---
 defs.h   |  1 +
 dev.c    | 20 +++++++++++++++++---
 memory.c | 35 +++--------------------------------
 tools.c  | 43 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 64 insertions(+), 35 deletions(-)

diff --git a/defs.h b/defs.h
index 211fc9d55d33..21cc760444d1 100644
--- a/defs.h
+++ b/defs.h
@@ -5521,6 +5521,7 @@ struct rb_node *rb_left(struct rb_node *, struct rb_node *);
 struct rb_node *rb_next(struct rb_node *);
 struct rb_node *rb_last(struct rb_root *);
 long percpu_counter_sum_positive(ulong fbc);
+ulong get_subsys_private(char *, char *);
 
 /* 
  *  symbols.c 
diff --git a/dev.c b/dev.c
index 75d30bd022a1..9d38aef9b3db 100644
--- a/dev.c
+++ b/dev.c
@@ -4686,9 +4686,16 @@ init_iter(struct iter *i)
 		} else {
 			/* kernel version > 2.6.27, klist */
 			unsigned long class_private_addr;
-			readmem(block_class_addr + OFFSET(class_p), KVADDR,
-				&class_private_addr, sizeof(class_private_addr),
-				"class.p", FAULT_ON_ERROR);
+
+			if (INVALID_MEMBER(class_p)) /* kernel version >= 6.4 */
+				class_private_addr = get_subsys_private("class_kset", "block");
+			else
+				readmem(block_class_addr + OFFSET(class_p), KVADDR,
+					&class_private_addr, sizeof(class_private_addr),
+					"class.p", FAULT_ON_ERROR);
+
+			if (!class_private_addr)
+				error(FATAL, "cannot determine subsys_private for block.\n");
 
 			if (VALID_STRUCT(class_private)) {
 				/* 2.6.27 < kernel version <= 2.6.37-rc2 */
@@ -4823,6 +4830,13 @@ void diskio_init(void)
 	if (INVALID_MEMBER(class_devices))
 		MEMBER_OFFSET_INIT(class_devices, "class", "devices");
 	MEMBER_OFFSET_INIT(class_p, "class", "p");
+	if (INVALID_MEMBER(class_p)) {
+		MEMBER_OFFSET_INIT(kset_list, "kset", "list");
+		MEMBER_OFFSET_INIT(kset_kobj, "kset", "kobj");
+		MEMBER_OFFSET_INIT(kobject_name, "kobject", "name");
+		MEMBER_OFFSET_INIT(kobject_entry, "kobject", "entry");
+		MEMBER_OFFSET_INIT(subsys_private_subsys, "subsys_private", "subsys");
+	}
 	MEMBER_OFFSET_INIT(class_private_devices, "class_private",
 		"class_devices");
 	MEMBER_OFFSET_INIT(device_knode_class, "device", "knode_class");
diff --git a/memory.c b/memory.c
index 0568f18eb9b7..953fc380c03c 100644
--- a/memory.c
+++ b/memory.c
@@ -17865,38 +17865,9 @@ init_memory_block(int *klistcnt, ulong **klistbuf)
 	 * v6.3-rc1
 	 * d2bf38c088e0 driver core: remove private pointer from struct bus_type
 	 */
-	if (INVALID_MEMBER(bus_type_p)) {
-		int i, cnt;
-		char buf[32];
-		ulong bus_kset, list, name;
-
-		BZERO(ld, sizeof(struct list_data));
-
-		get_symbol_data("bus_kset", sizeof(ulong), &bus_kset);
-		readmem(bus_kset + OFFSET(kset_list), KVADDR, &list,
-			sizeof(ulong), "bus_kset.list", FAULT_ON_ERROR);
-
-		ld->flags |= LIST_ALLOCATE;
-		ld->start = list;
-		ld->end = bus_kset + OFFSET(kset_list);
-		ld->list_head_offset = OFFSET(kobject_entry);
-
-		cnt = do_list(ld);
-		for (i = 0; i < cnt; i++) {
-			readmem(ld->list_ptr[i] + OFFSET(kobject_name), KVADDR, &name,
-				sizeof(ulong), "kobject.name", FAULT_ON_ERROR);
-			read_string(name, buf, sizeof(buf)-1);
-			if (CRASHDEBUG(1))
-				fprintf(fp, "kobject: %lx name: %s\n", ld->list_ptr[i], buf);
-			if (STREQ(buf, "memory")) {
-				/* entry is subsys_private.subsys.kobj. See bus_to_subsys(). */
-				private = ld->list_ptr[i] - OFFSET(kset_kobj)
-						- OFFSET(subsys_private_subsys);
-				break;
-			}
-		}
-		FREEBUF(ld->list_ptr);
-	} else {
+	if (INVALID_MEMBER(bus_type_p))
+		private = get_subsys_private("bus_kset", "memory");
+	else {
 		ulong memory_subsys = symbol_value("memory_subsys");
 		readmem(memory_subsys + OFFSET(bus_type_p), KVADDR, &private,
 			sizeof(void *), "memory_subsys.private", FAULT_ON_ERROR);
diff --git a/tools.c b/tools.c
index c2cfa7e280bc..392a79707e61 100644
--- a/tools.c
+++ b/tools.c
@@ -6963,3 +6963,46 @@ percpu_counter_sum_positive(ulong fbc)
 
 	return (ret < 0) ? 0 : ret;
 }
+
+ulong
+get_subsys_private(char *kset_name, char *target_name)
+{
+	ulong kset_addr, kset_list, name_addr, private = 0;
+	struct list_data list_data, *ld;
+	char buf[32];
+	int i, cnt;
+
+	if (!symbol_exists(kset_name))
+		return 0;
+
+	ld = &list_data;
+	BZERO(ld, sizeof(struct list_data));
+
+	get_symbol_data(kset_name, sizeof(ulong), &kset_addr);
+	readmem(kset_addr + OFFSET(kset_list), KVADDR, &kset_list,
+		sizeof(ulong), "kset.list", FAULT_ON_ERROR);
+
+	ld->flags |= LIST_ALLOCATE;
+	ld->start = kset_list;
+	ld->end = kset_addr + OFFSET(kset_list);
+	ld->list_head_offset = OFFSET(kobject_entry);
+
+	cnt = do_list(ld);
+
+	for (i = 0; i < cnt; i++) {
+		readmem(ld->list_ptr[i] + OFFSET(kobject_name), KVADDR, &name_addr,
+			sizeof(ulong), "kobject.name", FAULT_ON_ERROR);
+		read_string(name_addr, buf, sizeof(buf)-1);
+		if (CRASHDEBUG(1))
+			fprintf(fp, "kobject: %lx name: %s\n", ld->list_ptr[i], buf);
+		if (STREQ(buf, target_name)) {
+			/* entry is subsys_private.subsys.kobj. See bus_to_subsys(). */
+			private = ld->list_ptr[i] - OFFSET(kset_kobj)
+					- OFFSET(subsys_private_subsys);
+			break;
+		}
+	}
+	FREEBUF(ld->list_ptr);
+
+	return private;
+}
-- 
2.31.1

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://listman.redhat.com/mailman/listinfo/crash-utility
Contribution Guidelines: https://github.com/crash-utility/crash/wiki




[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux