----- Original Message -----
Hi, Dave
At 01/21/2012 04:24 AM, Dave Anderson Wrote:
>
>
> ----- Original Message -----
>> Hi, Dave
>>
>> When we investigate the problems of disk I/O, we want to get the disk's
>> gendisk address and request queue's address easily, and the requests num
>> is also important.
>>
>> Tha attached patch introduce a new command diskio to display such information.
>>
>> Thanks
>> Wen Congyang
>
> Hello Wen,
>
> I built and tested this patch, and it certainly contains some useful
> information. However, I do have a several suggestions.
>
> First, there's no need to make it a unique command. It would be
> far more appropriate to make it a "dev" command option, which for
> example, already shows gendisk structure addresses for each of the
> block devices.
>
> So please move all of your functions from kernel.c to dev.c.
> Then, for example, use "dev -d", and have cmd_dev() call your
> command like this:
>
> while ((c = getopt(argcnt, args, "dpi")) != EOF) {
> switch(c)
> {
> case 'd':
> diskio_option();
> return;
> ...
>
> Since all of the new offset_table and size_table entries are only
> used by this command, you can avoid unnecessarily initializing
> everything in kernel_init() by doing something like this:
>
> static void
> diskio_option(void)
> {
> if (INVALID_MEMBER(class_devices)) {
> MEMBER_OFFSET_INIT(class_devices, "class", "class_devices");
> if (INVALID_MEMBER(class_devices))
> MEMBER_OFFSET_INIT(class_devices, "class", "devices");
> MEMBER_OFFSET_INIT(class_p, "class", "p");
> MEMBER_OFFSET_INIT(class_private_devices, "class_private",
> "class_devices");
> MEMBER_OFFSET_INIT(device_knode_class, "device",
"knode_class");
> MEMBER_OFFSET_INIT(device_node, "device", "node");
> MEMBER_OFFSET_INIT(device_type, "device", "type");
> MEMBER_OFFSET_INIT(gendisk_dev, "gendisk", "dev");
> if (INVALID_MEMBER(gendisk_dev))
> MEMBER_OFFSET_INIT(gendisk_dev, "gendisk", "__dev");
> MEMBER_OFFSET_INIT(gendisk_kobj, "gendisk", "kobj");
> 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(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");
> MEMBER_OFFSET_INIT(kobject_entry, "kobject", "entry");
> MEMBER_OFFSET_INIT(kset_list, "kset", "list");
> MEMBER_OFFSET_INIT(request_list_count, "request_list",
"count");
> MEMBER_OFFSET_INIT(request_queue_in_flight, "request_queue",
> "in_flight");
> MEMBER_OFFSET_INIT(request_queue_rq, "request_queue", "rq");
> MEMBER_OFFSET_INIT(subsys_private_klist_devices,
> "subsys_private",
> "klist_devices");
> MEMBER_OFFSET_INIT(subsystem_kset, "subsystem", "kset");
> STRUCT_SIZE_INIT(subsystem, "subsystem");
> STRUCT_SIZE_INIT(class_private, "class_private");
> MEMBER_SIZE_INIT(rq_in_flight, "request_queue", "in_flight");
> MEMBER_SIZE_INIT(class_private_devices, "class_private",
> "class_devices");
> }
>
> display_all_diskio();
> }
>
> Secondly, the whole READ/WRITE issue is confusing to the uninitiated
> (like myself). After speaking with Jeff Moyer, we believe the output
> of your command could be clarified.
>
> Your help page indicates:
>
> +" This command dumps I/O statistics of all disks:",
> +" TOTAL: The total requests that have not been ended",
> +" READ: The total read requests that have not been ended",
> +" WRITE: The total write requests that have not been ended",
> +" DRV: The total requests that have been in the driver, but not
end",
> +"",
> +" Note: some kernel does not contain read/write requests, and the
command",
> +" will output '-----'"
> +"\nEXAMPLES",
> +" %s> diskio",
> +" MAJOR GENDISK NAME RUQUEST QUEUE TOTAL READ WRITE
DRV",
> +" 008 0xe00000010773ea80 sda 0x3000000109c9fbf0 12 0 12
0",
> +" 008 0xe00000010773e680 sdb 0x3000000109c9f8a0 2 2 0
0",
> +" 008 0xe000000107781d80 sdc 0x300000010c268050 6 0 6
6",
> +" 008 0xe00000010773e080 sdd 0x300000010c26bbf0 0 0 0
0",
> +" 008 0xe00000010773dc80 sde 0x300000010c3dd780 0 0 0
0",
> +NULL
>
> As Jeff explained to me, this is how it works:
>
> (1) In older kernels, this enum did not exist:
>
> enum {
> BLK_RW_ASYNC = 0,
> BLK_RW_SYNC = 1,
> };
>
> and in that case, the request_list.count[2] values are the
> READ/WRITE values, as you show in the help page example above.
>
> (2) In newer kernels, the enum does exist, and the meaning of the
> request_list.count[2] values are ASYNC/SYNC requests. In that
> case, you show "-----" under the READ and WRITE columns, which
> I found *very* confusing.
>
> What Jeff Moyer suggested is that -- in the case of new kernels -- you
> should alternatively show the counts with ASYNC and SYNC columns like
> this:
>
> MAJOR GENDISK NAME REQUEST QUEUE TOTAL ASYNC SYNC DRV",
> ...
>
> And the READ/WRITE vs. ASYNC/SYNC output display difference should be
> referenced in the help page output.
>
> Third, a minor nit -- note that you misspelled it as "RUQUEST" both in
> the command and in the help page. Also, it appears that you used an IA64 as
> the example, given the GENDISK addresses. But aren't the REQUEST QUEUE
> addresses below beginning with "0x300..." user-space addresses for IA64?
>
> +" MAJOR GENDISK NAME RUQUEST QUEUE TOTAL READ WRITE
DRV",
> +" 008 0xe00000010773ea80 sda 0x3000000109c9fbf0 12 0 12
0",
> +" 008 0xe00000010773e680 sdb 0x3000000109c9f8a0 2 2 0
0",
> +" 008 0xe000000107781d80 sdc 0x300000010c268050 6 0 6
6",
> +" 008 0xe00000010773e080 sdd 0x300000010c26bbf0 0 0 0
0",
> +" 008 0xe00000010773dc80 sde 0x300000010c3dd780 0 0 0
0",
>
> In any case, can you change it to use either x86_64 or x86 as an
> example?
>
> Fourth, in testing this with a 2.6.25 kernel, the command hangs:
>
> crash> dev -d
> MAJOR GENDISK NAME REQUEST QUEUE TOTAL READ WRITE DRV
> 2 0xffff81012d8a5000 fd0 0xffff81012dc053c0 0 0 0 0
> 22 0xffff81012dc6b000 hdc 0xffff81012d8ae340 0 0 0 0
> 8 0xffff81012dd71000 sda 0xffff81012d8af040 0 0 0 0
> < hangs here forever >
>
> I'm not absolutely sure, but if I hit CTRL-C under gdb, it seems that it's
> spinning in next_disk_list() in that "goto again" loop?
>
> Fifth, I tried it on a much older RHEL3 kernel, which shows:
>
> crash> dev -d
> dev: invalid request_queue.in_flight's size
> crash>
>
> It's not really invalid size, but it's more the case that you
> don't support that old a kernel version. In that case, instead
> of doing this:
>
> error(FATAL, "invalid request_queue.in_flight's size\n");
>
> you should do this instead:
>
> option_not_supported('d');
>
> And finally, whenever adding fields to the offset_table or size_table,
> please display their values in dump_offset_table() for the "help -o"
> command.
I have updated the patch.
Thanks
Wen Congyang
Hello Wen,
This second patch looks good -- I did make a few small changes.
I re-worded the help page:
crash> help dev
NAME
dev - device data
SYNOPSIS
dev [-i | -p | -d]
DESCRIPTION
If no argument is entered, this command dumps character and block
device data.
-i display I/O port usage; on 2.4 kernels, also display I/O memory usage.
-p display PCI device data.
-d display disk I/O statistics:
TOTAL: total number of allocated I/O requests that are in-progress
SYNC: I/O requests that are synchronous
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
EXAMPLES
...
I reformatted the output to allow for larger disk name strings,
such as "cciss/c0d0" in this example:
crash> dev -d
MAJOR GENDISK NAME REQUEST QUEUE TOTAL READ WRITE DRV
104 0xffff81007e422800 cciss/c0d0 0xffff81007f6d4048 1 0 1 1
253 0xffff81007e89fa00 dm-0 0xffff81007f6d4c98 0 0 0 0
253 0xffff81007eace200 dm-1 0xffff81007f6d4670 0 0 0 0
9 0xffff81007eb43400 md0 0xffff81007d397928 0 0 0 0
crash>
And I created a dev_table.flags DISKIO_INIT bit instead of using
the static "initialized" variable.
Queued for crash-6.0.3.
Thanks,
Dave