dm-dust¶
此目标模拟任意位置的坏扇区行为,并能够在任意时间启用故障模拟。
此目标的行为类似于线性目标。在给定的时间,用户可以向目标发送消息,以开始在特定块上发生读取请求失败(模拟具有坏扇区的硬盘驱动器的行为)。
当启用故障行为时(即:“dmsetup status”的输出显示“fail_read_on_bad_block”时),读取“坏块列表”中的块将失败,并显示 EIO(“输入/输出错误”)。
写入“坏块列表”中的块将导致以下结果:
从“坏块列表”中删除该块。
成功完成写入。
这模拟了具有坏扇区的驱动器的“重新映射扇区”行为。
通常,遇到坏扇区的驱动器很可能会在未知的时间或位置遇到更多坏扇区。使用 dm-dust,用户可以使用 “addbadblock” 和 “removebadblock” 消息在新的位置添加任意坏块,并使用 “enable” 和 “disable” 消息来调整配置的 “坏块” 是否将被视为坏块或绕过的状态。这允许在模拟坏扇区开始出现的 “故障” 事件之前预先写入测试数据和元数据。
表参数¶
<device_path> <offset> <blksz>
- 强制参数
- <device_path>
块设备的路径。
- <offset>
从 device_path 的开头到数据区域的偏移量
- <blksz>
块大小(以字节为单位)
(最小 512,最大 1073741824,必须是 2 的幂)
使用说明¶
首先,找到要使用的设备的大小(以 512 字节扇区为单位)
$ sudo blockdev --getsz /dev/vdb1
33552384
创建 dm-dust 设备:(对于块大小为 512 字节的设备)
$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 512'
(对于块大小为 4096 字节的设备)
$ sudo dmsetup create dust1 --table '0 33552384 dust /dev/vdb1 0 4096'
检查读取行为的状态(“bypass” 表示所有 I/O 将传递到基础设备;“verbose” 表示坏块添加、删除和重新映射将以详细方式记录)
$ sudo dmsetup status dust1
0 33552384 dust 252:17 bypass verbose
$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=128 iflag=direct
128+0 records in
128+0 records out
$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
128+0 records in
128+0 records out
添加和删除坏块¶
在任何时间(即:无论设备是否启用了“坏块”模拟),都可以通过 “addbadblock” 和 “removebadblock” 消息从设备添加或删除坏块
$ sudo dmsetup message dust1 0 addbadblock 60
kernel: device-mapper: dust: badblock added at block 60
$ sudo dmsetup message dust1 0 addbadblock 67
kernel: device-mapper: dust: badblock added at block 67
$ sudo dmsetup message dust1 0 addbadblock 72
kernel: device-mapper: dust: badblock added at block 72
这些坏块将存储在“坏块列表”中。当设备处于“bypass”模式时,读取和写入将成功
$ sudo dmsetup status dust1
0 33552384 dust 252:17 bypass
启用块读取失败¶
要启用 “坏块读取失败” 行为,请发送 “enable” 消息
$ sudo dmsetup message dust1 0 enable
kernel: device-mapper: dust: enabling read failures on bad sectors
$ sudo dmsetup status dust1
0 33552384 dust 252:17 fail_read_on_bad_block
当设备处于 “坏块读取失败” 模式时,尝试读取块将遇到 “输入/输出错误”
$ sudo dd if=/dev/mapper/dust1 of=/dev/null bs=512 count=1 skip=67 iflag=direct
dd: error reading '/dev/mapper/dust1': Input/output error
0+0 records in
0+0 records out
0 bytes copied, 0.00040651 s, 0.0 kB/s
...并且写入坏块将从列表中删除这些块,从而模拟硬盘驱动器的“重新映射”行为
$ sudo dd if=/dev/zero of=/dev/mapper/dust1 bs=512 count=128 oflag=direct
128+0 records in
128+0 records out
kernel: device-mapper: dust: block 60 removed from badblocklist by write
kernel: device-mapper: dust: block 67 removed from badblocklist by write
kernel: device-mapper: dust: block 72 removed from badblocklist by write
kernel: device-mapper: dust: block 87 removed from badblocklist by write
坏块添加/删除错误处理¶
尝试添加列表中已存在的坏块将导致 “无效参数” 错误以及有用的消息
$ sudo dmsetup message dust1 0 addbadblock 88
device-mapper: message ioctl on dust1 failed: Invalid argument
kernel: device-mapper: dust: block 88 already in badblocklist
尝试删除列表中不存在的坏块将导致 “无效参数” 错误以及有用的消息
$ sudo dmsetup message dust1 0 removebadblock 87
device-mapper: message ioctl on dust1 failed: Invalid argument
kernel: device-mapper: dust: block 87 not found in badblocklist
计算坏块列表中坏块的数量¶
要计算设备中配置的坏块数量,请运行以下消息命令
$ sudo dmsetup message dust1 0 countbadblocks
将打印一条消息,其中包含当前在设备上配置的坏块数量
countbadblocks: 895 badblock(s) found
查询特定坏块¶
要查找特定块是否在坏块列表中,请运行以下消息命令
$ sudo dmsetup message dust1 0 queryblock 72
如果该块在列表中,将打印以下消息
dust_query_block: block 72 found in badblocklist
如果该块不在列表中,将打印以下消息
dust_query_block: block 72 not found in badblocklist
“queryblock” 消息命令将在 “enabled” 和 “disabled” 模式下工作,允许验证块是否将被视为 “坏” 块,而无需向设备发出 I/O 或必须 “启用” 坏块模拟。
清除坏块列表¶
要清除坏块列表(而无需为每个块单独运行 “removebadblock” 消息命令),请运行以下消息命令
$ sudo dmsetup message dust1 0 clearbadblocks
清除坏块列表后,将出现以下消息
dust_clear_badblocks: badblocks cleared
如果没有要清除的坏块,将出现以下消息
dust_clear_badblocks: no badblocks found
列出坏块列表¶
要列出坏块列表中的所有坏块(使用坏块列表中包含块 1 和 2 的示例设备),请运行以下消息命令
$ sudo dmsetup message dust1 0 listbadblocks
1
2
如果坏块列表中没有坏块,则命令将执行,且没有输出
$ sudo dmsetup message dust1 0 listbadblocks
消息命令列表¶
以下是可以发送到 dust 设备的消息列表
对块的操作(需要 <blknum> 参数)
addbadblock <blknum>
queryblock <blknum>
removebadblock <blknum>
...其中 <blknum> 是设备范围内的块号(与设备的块大小相对应。)
单个参数消息命令
countbadblocks
clearbadblocks
listbadblocks
disable
enable
quiet
设备移除¶
完成后,通过 “dmsetup remove” 命令删除设备
$ sudo dmsetup remove dust1
静默模式¶
在包含大量坏块的测试运行中,可能需要避免过多的日志记录(来自添加、删除或“重新映射”的坏块)。可以通过发送以下消息启用“静默模式”来实现此目的。
$ sudo dmsetup message dust1 0 quiet
这将抑制来自添加/删除/通过写入操作移除的日志消息。“countbadblocks”或“queryblock”消息命令的日志消息在静默模式下仍会打印。
可以通过运行“dmsetup status”查看静默模式的状态。
$ sudo dmsetup status dust1
0 33552384 dust 252:17 fail_read_on_bad_block quiet
要禁用静默模式,请再次发送“quiet”消息。
$ sudo dmsetup message dust1 0 quiet
$ sudo dmsetup status dust1
0 33552384 dust 252:17 fail_read_on_bad_block verbose
(“verbose”的存在表示正常的日志记录。)
“为什么不...?”¶
scsi_debug 有一个“介质错误”模式,可以在一个指定的扇区(扇区 0x1234,在源代码中硬编码)上使读取失败,但它使用 RAM 作为持久存储,这会大大减少设备的潜在大小。
dm-flakey 会在指定的时间频率上使所有块位置的所有 I/O 失败,而不是在给定的时间点失败。
当硬盘驱动器上出现坏扇区时,设备会对该扇区的读取操作失败,通常会导致 EIO(“I/O 错误”)或 ENODATA(“无数据可用”)的错误代码。但是,对该扇区的写入操作可能会成功,并导致设备控制器不再遇到读取该扇区的错误后(或者在重新分配该扇区后)该扇区变为可读。然而,将来设备上可能会在不同的、不可预测的位置出现坏扇区。
此目标旨在提供一种设备,该设备可以在已知扇区位置,在已知时间,根据大型存储设备(至少数十千兆字节,不占用系统内存)来表现坏扇区的行为。