[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