DM 统计信息

设备映射器支持收集 DM 设备用户定义区域上的 I/O 统计信息。如果未定义区域,则不收集任何统计信息,因此不会有任何性能影响。目前仅支持基于 bio 的 DM 设备。

每个用户定义的区域都指定了起始扇区、长度和步长。将针对指定范围内的每个步长区域收集单独的统计信息。

区域中每个步长区域的 I/O 统计计数器格式与 /sys/block/*/stat/proc/diskstats 相同 (参见:I/O 统计字段)。但提供了两个额外的计数器(12 和 13):读写总耗时。当使用 histogram 参数时,会报告代表延迟直方图的第 14 个参数。所有这些计数器都可以通过 dmsetup 向相应的 DM 设备发送 @stats_print 消息来访问。

报告的时间以毫秒为单位,粒度取决于内核时钟周期。当使用 precise_timestamps 选项时,报告的时间以纳秒为单位。

每个区域都有一个对应的唯一标识符,我们称之为 region_id,它在区域创建时分配。查询区域统计信息、删除区域等操作时必须提供 region_id。唯一的 region_id 允许多个用户空间程序请求和处理同一 DM 设备的统计信息,而不会相互干扰数据。

DM 统计信息的创建将通过 kmalloc 分配内存,或回退到使用 vmalloc 空间。DM 统计信息最多可以分配总系统内存的 1/4。管理员可以通过读取以下文件查看内存使用情况:

/sys/module/dm_mod/parameters/stats_current_allocated_bytes

消息

@stats_create <range> <step> [<number_of_optional_arguments> <optional_arguments>...] [<program_id> [<aux_data>]]

创建一个新区域并返回 region_id。

<range>
“-”

整个设备

“<start_sector>+<length>”

以 <start_sector> 开始,长度为 <length> 个 512 字节扇区的范围。

<step>
“<area_size>”

该范围被细分为多个区域,每个区域包含 <area_size> 个扇区。

“/<number_of_areas>”

该范围被细分为指定数量的区域。

<number_of_optional_arguments>

可选参数的数量

<optional_arguments>

支持以下可选参数

precise_timestamps

使用纳秒分辨率的精确计时器,而不是“jiffies”变量。使用此参数时,结果时间以纳秒而不是毫秒为单位。精确时间戳的获取速度比基于 jiffies 的时间戳稍慢。

histogram:n1,n2,n3,n4,...

收集延迟直方图。数字 n1、n2 等表示直方图的边界时间。如果未使用 precise_timestamps,时间以毫秒为单位,否则以纳秒为单位。对于每个范围,内核将报告在此范围内完成的请求数量。例如,如果使用“histogram:10,20,30”,内核将报告四个数字 a:b:c:d。a 是完成时间为 0-10 毫秒的请求数量,b 是完成时间为 10-20 毫秒的请求数量,c 是完成时间为 20-30 毫秒的请求数量,d 是完成时间超过 30 毫秒的请求数量。

<program_id>

一个可选参数。一个唯一标识该范围的用户空间所有者的名称。这会将范围进行分组,以便用户空间程序可以识别它们创建的范围,并忽略其他程序创建的范围。内核会在 @stats_list 消息的输出中返回此字符串,但不会将其用于其他任何目的。如果省略可选参数的数量,则 program id 必须不是数字,否则它将被解释为可选参数的数量。

<aux_data>

一个可选参数。一个提供对创建该范围的客户端程序有用的辅助数据的单词。内核会在 @stats_list 消息的输出中返回此字符串,但不会使用此值做任何事情。

@stats_delete <region_id>

删除具有指定 ID 的区域。

<region_id>

从 @stats_create 返回的 region_id

@stats_clear <region_id>

清除除进行中的 I/O 计数器之外的所有计数器。

<region_id>

从 @stats_create 返回的 region_id

@stats_list [<program_id>]

列出所有已通过 @stats_create 注册的区域。

<program_id>

一个可选参数。如果指定此参数,则只返回匹配的区域。如果未指定,则返回所有区域。

输出格式
<region_id>: <start_sector>+<length> <step> <program_id> <aux_data>

precise_timestamps histogram:n1,n2,n3,...

字符串“precise_timestamps”和“histogram”仅在创建区域时指定了它们的情况下才会打印。

@stats_print <region_id> [<starting_line> <number_of_lines>]

打印区域中每个步长区域的计数器。

<region_id>

从 @stats_create 返回的 region_id

<starting_line>

输出中起始行的索引。如果省略,则返回所有行。

<number_of_lines>

输出中包含的行数。如果省略,则返回所有行。

区域中每个步长区域的输出格式

<start_sector>+<length>

计数器

前 11 个计数器与 /sys/block/*/stat 或 /proc/diskstats 的含义相同。

详细信息请参阅I/O 统计字段

  1. 完成的读取次数

  2. 合并的读取次数

  3. 读取的扇区数量

  4. 读取所花费的毫秒数

  5. 完成的写入次数

  6. 合并的写入次数

  7. 写入的扇区数量

  8. 写入所花费的毫秒数

  9. 当前正在进行的 I/O 数量

  10. 执行 I/O 所花费的毫秒数

  11. 执行 I/O 所花费的加权毫秒数

附加计数器

  1. 读取总耗时(毫秒)

  2. 写入总耗时(毫秒)

@stats_print_clear <region_id> [<starting_line> <number_of_lines>]

原子性地打印然后清除除进行中的 I/O 计数器之外的所有计数器。当使用统计信息的客户端不想丢失任何统计信息(即在打印和清除之间更新的统计信息)时,此功能很有用。

<region_id>

从 @stats_create 返回的 region_id

<starting_line>

输出中起始行的索引。如果省略,则打印并清除所有行。

<number_of_lines>

要处理的行数。如果省略,则打印并清除所有行。

@stats_set_aux <region_id> <aux_data>

为指定区域存储辅助数据 aux_data。

<region_id>

从 @stats_create 返回的 region_id

<aux_data>

此字符串标识对创建该范围的客户端程序有用的数据。内核会在 @stats_list 消息的输出中返回此字符串,但不会使用此值做任何事情。

示例

将 DM 设备“vol”细分为 100 个部分,并开始收集它们的统计信息

dmsetup message vol 0 @stats_create - /100

将辅助数据字符串设置为“foo bar baz”(每个空格的转义符也必须转义,否则 shell 会将其消耗掉)

dmsetup message vol 0 @stats_set_aux 0 foo\\ bar\\ baz

列出统计信息

dmsetup message vol 0 @stats_list

打印统计信息

dmsetup message vol 0 @stats_print 0

删除统计信息

dmsetup message vol 0 @stats_delete 0