[Crash-utility] [PATCH] dev: Fix display disk I/O statistics for 4.20
Dave Anderson
anderson at redhat.com
Mon Jan 7 19:02:24 UTC 2019
----- Original Message -----
> Fix for the "dev -d|-D" command on Linux 4.20 and later kernels.
> In Linux 4.20, in_flight member in struct request_queue is disappeared.
> And also struct request_list is removed. So, dev -d|-D doesn't work.
>
> Unfortunately, it seems that there is no alternative information
> which shows the number of I/Os issued to disk driver. So this patch
> gets DRV column removed if in_flight member in struct request_queue
> isn't valid.
>
> Without the patch, the command fails with the error message
> "dev: -d option not supported or applicable on this architecture
> or kernel".
>
> Signed-off-by: Masayoshi Mizuma <m.mizuma at jp.fujitsu.com>
Hi Masa,
I appreciate the quick response to my offlist request. I also added a line
to the "dev" help page, and queued the patch for crash-7.2.5:
https://github.com/crash-utility/crash/commit/361f050e3148c6188afb45942e06d4a509852b86
Thanks again,
Dave
> ---
> defs.h | 2 ++
> dev.c | 73 ++++++++++++++++++++++++++++++++++++++++---------------
> symbols.c | 4 +++
> 3 files changed, 59 insertions(+), 20 deletions(-)
>
> diff --git a/defs.h b/defs.h
> index a3cb5a4..9ebdde6 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -2064,6 +2064,8 @@ struct offset_table { /* stash of
> commonly-used offsets */
> long xarray_xa_head;
> long xa_node_slots;
> long xa_node_shift;
> + 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/symbols.c b/symbols.c
> index ef6f934..5f77e27 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -10101,6 +10101,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",
> --
> 2.18.1
>
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
>
More information about the Crash-utility
mailing list