Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
6.7 KiB

commit 361f050e3148c6188afb45942e06d4a509852b86
Author: Dave Anderson <anderson@redhat.com>
Date: Mon Jan 7 13:56:15 2019 -0500
Fix for the "dev -[dD]" options in kernels containing Linux 5.0-rc1
commit 7ff4f8035695984c513598e2d49c8277d5d234ca, titled "block:
remove dead queue members", in which the number of I/Os issued to
a disk driver are no longer stored in the request_queue structure.
Without the patch, the options indicate "dev: -d option not supported
or applicable on this architecture or kernel". With the patch, the
"DRV" column is not shown.
(m.mizuma@jp.fujitsu.com)
diff --git a/defs.h b/defs.h
index a3cb5a4..9ebdde6 100644
--- a/defs.h
+++ b/defs.h
@@ -2043,6 +2043,8 @@ struct offset_table {
long pci_bus_self;
long device_kobj;
long kobject_name;
+ long hd_struct_dkstats;
+ long disk_stats_in_flight;
};
struct size_table { /* stash of commonly-used sizes */
diff --git a/dev.c b/dev.c
index 7ce2422..24efea2 100644
--- a/dev.c
+++ b/dev.c
@@ -3974,7 +3974,7 @@ struct iter {
* this function reads request_list.count[2], and the first argument
* is the address of request_queue.
*/
- void (*get_diskio)(unsigned long , struct diskio *);
+ void (*get_diskio)(unsigned long , unsigned long, struct diskio *);
/*
* check if device.type == &disk_type
@@ -4187,24 +4187,55 @@ get_mq_diskio(unsigned long q, unsigned long *mq_count)
}
}
+static void
+get_one_diskio_from_dkstats(unsigned long dkstats, unsigned long *count)
+{
+ int cpu;
+ unsigned long dkstats_addr;
+ unsigned long in_flight[2];
+
+ for (cpu = 0; cpu < kt->cpus; cpu++) {
+ if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) {
+ dkstats_addr = dkstats + kt->__per_cpu_offset[cpu];
+ readmem(dkstats_addr + OFFSET(disk_stats_in_flight),
+ KVADDR, in_flight, sizeof(long) * 2,
+ "disk_stats.in_flight", FAULT_ON_ERROR);
+ count[0] += in_flight[0];
+ count[1] += in_flight[1];
+ }
+ }
+}
+
+
/* read request_queue.rq.count[2] */
static void
-get_diskio_1(unsigned long rq, struct diskio *io)
+get_diskio_1(unsigned long rq, unsigned long gendisk, struct diskio *io)
{
int count[2];
- unsigned long mq_count[2] = { 0 };
+ unsigned long io_counts[2] = { 0 };
+ unsigned long dkstats;
if (!use_mq_interface(rq)) {
- readmem(rq + OFFSET(request_queue_rq) +
- OFFSET(request_list_count), KVADDR, count,
- sizeof(int) * 2, "request_list.count", FAULT_ON_ERROR);
+ if (VALID_MEMBER(request_queue_rq)) {
+ readmem(rq + OFFSET(request_queue_rq) +
+ OFFSET(request_list_count), KVADDR, count,
+ sizeof(int) * 2, "request_list.count", FAULT_ON_ERROR);
+
+ io->read = count[0];
+ io->write = count[1];
+ } else {
+ readmem(gendisk + OFFSET(gendisk_part0) +
+ OFFSET(hd_struct_dkstats), KVADDR, &dkstats,
+ sizeof(ulong), "gendisk.part0.dkstats", FAULT_ON_ERROR);
+ get_one_diskio_from_dkstats(dkstats, io_counts);
- io->read = count[0];
- io->write = count[1];
+ io->read = io_counts[0];
+ io->write = io_counts[1];
+ }
} else {
- get_mq_diskio(rq, mq_count);
- io->read = mq_count[0];
- io->write = mq_count[1];
+ get_mq_diskio(rq, io_counts);
+ io->read = io_counts[0];
+ io->write = io_counts[1];
}
}
@@ -4250,9 +4281,6 @@ init_iter(struct iter *i)
i->get_in_flight = get_in_flight_1;
} else if (SIZE(rq_in_flight) == sizeof(int) * 2) {
i->get_in_flight = get_in_flight_2;
- } else {
- option_not_supported('d');
- return;
}
i->get_diskio = get_diskio_1;
@@ -4354,7 +4382,7 @@ display_one_diskio(struct iter *i, unsigned long gendisk, ulong flags)
sizeof(ulong), "gen_disk.queue", FAULT_ON_ERROR);
readmem(gendisk + OFFSET(gendisk_major), KVADDR, &major, sizeof(int),
"gen_disk.major", FAULT_ON_ERROR);
- i->get_diskio(queue_addr, &io);
+ i->get_diskio(queue_addr, gendisk, &io);
if ((flags & DIOF_NONZERO)
&& (io.read + io.write == 0))
@@ -4379,11 +4407,14 @@ display_one_diskio(struct iter *i, unsigned long gendisk, ulong flags)
(char *)(unsigned long)io.write),
space(MINSPACE));
- if (!use_mq_interface(queue_addr)) {
- in_flight = i->get_in_flight(queue_addr);
- fprintf(fp, "%5u\n", in_flight);
+ if (VALID_MEMBER(request_queue_in_flight)) {
+ if (!use_mq_interface(queue_addr)) {
+ in_flight = i->get_in_flight(queue_addr);
+ fprintf(fp, "%5u\n", in_flight);
+ } else
+ fprintf(fp, "%s\n", "N/A(MQ)");
} else
- fprintf(fp, "%s\n", "N/A(MQ)");
+ fprintf(fp, "\n");
}
static void
@@ -4418,7 +4449,7 @@ display_all_diskio(ulong flags)
i.sync_count ? mkstring(buf4, 5, RJUST, "SYNC") :
mkstring(buf4, 5, RJUST, "WRITE"),
space(MINSPACE),
- mkstring(buf5, 5, RJUST, "DRV"));
+ VALID_MEMBER(request_queue_in_flight) ? mkstring(buf5, 5, RJUST, "DRV") : "");
while ((gendisk = i.next_disk(&i)) != 0)
display_one_diskio(&i, gendisk, flags);
@@ -4446,6 +4477,7 @@ void diskio_init(void)
MEMBER_OFFSET_INIT(gendisk_part0, "gendisk", "part0");
MEMBER_OFFSET_INIT(gendisk_queue, "gendisk", "queue");
MEMBER_OFFSET_INIT(hd_struct_dev, "hd_struct", "__dev");
+ MEMBER_OFFSET_INIT(hd_struct_dkstats, "hd_struct", "dkstats");
MEMBER_OFFSET_INIT(klist_k_list, "klist", "k_list");
MEMBER_OFFSET_INIT(klist_node_n_klist, "klist_node", "n_klist");
MEMBER_OFFSET_INIT(klist_node_n_node, "klist_node", "n_node");
@@ -4476,6 +4508,7 @@ void diskio_init(void)
MEMBER_SIZE_INIT(rq_in_flight, "request_queue", "in_flight");
MEMBER_SIZE_INIT(class_private_devices, "class_private",
"class_devices");
+ MEMBER_OFFSET_INIT(disk_stats_in_flight, "disk_stats", "in_flight");
dt->flags |= DISKIO_INIT;
}
diff --git a/help.c b/help.c
index aadd2ed..1593e82 100644
--- a/help.c
+++ b/help.c
@@ -3218,7 +3218,7 @@ char *help_dev[] = {
" WRITE: I/O requests that are writes (older kernels)",
" DRV: I/O requests that are in-flight in the device driver.",
" If the device driver uses blk-mq interface, this field",
-" shows N/A(MQ).",
+" shows N/A(MQ). If not available, this column is not shown.",
" -D same as -d, but filter out disks with no in-progress I/O requests.",
"\nEXAMPLES",
" Display character and block device data:\n",
diff --git a/symbols.c b/symbols.c
index ef6f934..5f77e27 100644
--- a/symbols.c
+++ b/symbols.c
@@ -10021,6 +10021,10 @@ dump_offset_table(char *spec, ulong makestruct)
OFFSET(gendisk_queue));
fprintf(fp, " hd_struct_dev: %ld\n",
OFFSET(hd_struct_dev));
+ fprintf(fp, " hd_struct_dkstats: %ld\n",
+ OFFSET(hd_struct_dkstats));
+ fprintf(fp, " disk_stats_in_flight: %ld\n",
+ OFFSET(disk_stats_in_flight));
fprintf(fp, " klist_k_list: %ld\n",
OFFSET(klist_k_list));
fprintf(fp, " klist_node_n_klist: %ld\n",