Hello Masayoshi,
I moved the new offset_table entries to the end of the structure to
prevent any pre-existing extension modules from breaking, and I added
their offsets to the dump_offset_table() function for "help -o".
Queued for crash-7.1.6:
  
 Improvement -d option of dev command to display I/O statics
 for the disk which the device driver uses blk-mq interface.
 
 Current dev -d displays always 0 in the all fields for the
 blk-mq disk because blk-mq does not increment/decrement to
 request_list.count[2] on I/O creation and I/O completion.
 
 The following value is used in blk-mq on such situation.
 
 - I/O creation:   blk_mq_ctx.rq_dispatched[2]
 - I/O completion: blk_mq_ctx.rq_completed[2]
 
 So, we can get the counter of in progress I/Os as follows.
 
 in progress I/Os == rq_dispatched - rq_completed
 
 This patch displays the result of above calculation for the
 disk. It judges as the device driver uses blk-mq if the
 request_queue.mq_ops is not NULL.
 
 "DRV" field is displayed as "N/A(MQ)" because the value for
in-flight
 in the device driver is not exists for blk-mq...
 
 Signed-off-by: Masayoshi Mizuma <m.mizuma(a)jp.fujitsu.com>
 ---
  defs.h |  4 +++
  dev.c  | 98
  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
  help.c |  4 ++-
  3 files changed, 96 insertions(+), 10 deletions(-)
 
 diff --git a/defs.h b/defs.h
 index a09fa9a..55c28c5 100755
 --- a/defs.h
 +++ b/defs.h
 @@ -1822,6 +1822,10 @@ struct offset_table {                    /* stash of
 commonly-used offsets */
  	long request_list_count;
  	long request_queue_in_flight;
  	long request_queue_rq;
 +	long request_queue_mq_ops;
 +	long request_queue_queue_ctx;
 +	long blk_mq_ctx_rq_dispatched;
 +	long blk_mq_ctx_rq_completed;
  	long subsys_private_klist_devices;
  	long subsystem_kset;
  	long mount_mnt_parent;
 diff --git a/dev.c b/dev.c
 index c18f40e..e46081e 100644
 --- a/dev.c
 +++ b/dev.c
 @@ -3800,18 +3800,84 @@ again:
  	return i->get_gendisk(klist_node_address);
  }
  
 +static int
 +use_mq_interface(unsigned long q)
 +{
 +	unsigned long mq_ops;
 +
 +	if (!VALID_MEMBER(request_queue_mq_ops))
 +		return 0;
 +
 +	readmem(q + OFFSET(request_queue_mq_ops), KVADDR, &mq_ops,
 +		sizeof(ulong), "request_queue.mq_ops", FAULT_ON_ERROR);
 +
 +	if (mq_ops == 0)
 +		return 0;
 +	else
 +		return 1;
 +}
 +
 +static void
 +get_one_mctx_diskio(unsigned long mctx, struct diskio *io)
 +{
 +	unsigned long dispatch[2];
 +	unsigned long comp[2];
 +
 +	readmem(mctx + OFFSET(blk_mq_ctx_rq_dispatched),
 +		KVADDR, dispatch, sizeof(ulong) * 2, "blk_mq_ctx.rq_dispatched",
 +		FAULT_ON_ERROR);
 +
 +	readmem(mctx + OFFSET(blk_mq_ctx_rq_completed),
 +		KVADDR, comp, sizeof(ulong) * 2, "blk_mq_ctx.rq_completed",
 +		FAULT_ON_ERROR);
 +
 +	io->read = (dispatch[0] - comp[0]);
 +	io->write = (dispatch[1] - comp[1]);
 +}
 +
 +static void
 +get_mq_diskio(unsigned long q, unsigned long *mq_count)
 +{
 +	int cpu;
 +	unsigned long queue_ctx;
 +	unsigned long mctx_addr;
 +	struct diskio tmp;
 +
 +	memset(&tmp, 0x00, sizeof(struct diskio));
 +
 +	readmem(q + OFFSET(request_queue_queue_ctx), KVADDR, &queue_ctx,
 +		sizeof(ulong), "request_queue.queue_ctx",
 +		FAULT_ON_ERROR);
 +
 +	for (cpu = 0; cpu < kt->cpus; cpu++) {
 +		if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) {
 +			mctx_addr = queue_ctx + kt->__per_cpu_offset[cpu];
 +			get_one_mctx_diskio(mctx_addr, &tmp);
 +			mq_count[0] += tmp.read;
 +			mq_count[1] += tmp.write;
 +		}
 +	}
 +}
 +
  /* read request_queue.rq.count[2] */
  static void
  get_diskio_1(unsigned long rq, struct diskio *io)
  {
  	int count[2];
 +	unsigned long mq_count[2] = { 0 };
  
 -	readmem(rq + OFFSET(request_queue_rq) + OFFSET(request_list_count),
 -		KVADDR, count, sizeof(int) * 2, "request_list.count",
 -		FAULT_ON_ERROR);
 +	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);
  
 -	io->read = count[0];
 -	io->write = count[1];
 +		io->read = count[0];
 +		io->write = count[1];
 +	} else {
 +		get_mq_diskio(rq, mq_count);
 +		io->read = mq_count[0];
 +		io->write = mq_count[1];
 +	}
  }
  
  /* request_queue.in_flight contains total requests */
 @@ -3961,9 +4027,8 @@ display_one_diskio(struct iter *i, unsigned long
 gendisk)
  	readmem(gendisk + OFFSET(gendisk_major), KVADDR, &major, sizeof(int),
  		"gen_disk.major", FAULT_ON_ERROR);
  	i->get_diskio(queue_addr, &io);
 -	in_flight = i->get_in_flight(queue_addr);
  
 -	fprintf(fp, "%s%s%s  %s%s%s%s  %s%5d%s%s%s%s%s%5u\n",
 +	fprintf(fp, "%s%s%s  %s%s%s%s  %s%5d%s%s%s%s%s",
  		mkstring(buf0, 5, RJUST|INT_DEC, (char *)(unsigned long)major),
  		space(MINSPACE),
  		mkstring(buf1, VADDR_PRLEN, LJUST|LONG_HEX, (char *)gendisk),
 @@ -3980,8 +4045,13 @@ display_one_diskio(struct iter *i, unsigned long
 gendisk)
  		space(MINSPACE),
  		mkstring(buf5, 5, RJUST|INT_DEC,
  			(char *)(unsigned long)io.write),
 -		space(MINSPACE),
 -		in_flight);
 +		space(MINSPACE));
 +
 +	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)");
  }
  
  static void
 @@ -4056,6 +4126,16 @@ void diskio_init(void)
  		MEMBER_OFFSET_INIT(request_queue_rq, "request_queue", "rq");
  	else
  		MEMBER_OFFSET_INIT(request_queue_rq, "request_queue", "root_rl");
 +	if (MEMBER_EXISTS("request_queue", "mq_ops")) {
 +		MEMBER_OFFSET_INIT(request_queue_mq_ops, "request_queue",
 +			"mq_ops");
 +		ANON_MEMBER_OFFSET_INIT(request_queue_queue_ctx,
 +			"request_queue", "queue_ctx");
 +		MEMBER_OFFSET_INIT(blk_mq_ctx_rq_dispatched, "blk_mq_ctx",
 +			"rq_dispatched");
 +		MEMBER_OFFSET_INIT(blk_mq_ctx_rq_completed, "blk_mq_ctx",
 +			"rq_completed");
 +	}
  	MEMBER_OFFSET_INIT(subsys_private_klist_devices, "subsys_private",
  		"klist_devices");
  	MEMBER_OFFSET_INIT(subsystem_kset, "subsystem", "kset");
 diff --git a/help.c b/help.c
 index 938251f..cfa0516 100644
 --- a/help.c
 +++ b/help.c
 @@ -2684,7 +2684,9 @@ char *help_dev[] = {
  "         ASYNC: I/O requests that are asynchronous",
  "          READ: I/O requests that are reads (older kernels)",
  "         WRITE: I/O requests that are writes (older kernels)",
 -"           DRV: I/O requests that are in-flight in the device driver",
 +"           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).",
  "\nEXAMPLES",
  "  Display character and block device data:\n",
  "    %s> dev",
 --
 1.8.3.1
 
 --
 Crash-utility mailing list
 Crash-utility(a)redhat.com
 
https://www.redhat.com/mailman/listinfo/crash-utility