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”消息命令在“启用”和“禁用”模式下均可工作,从而无需向设备发出 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
消息命令列表¶
以下是可以发送到 dm-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(“无可用数据”)。但是,对该扇区的写入可能会成功,并且在设备控制器不再遇到读取该扇区错误(或扇区重新分配后)后,该扇区变得可读。然而,设备上未来可能会在不同且不可预测的位置出现坏扇区。
此目标旨在提供一个设备,该设备可以在已知扇区位置、已知时间,基于大型存储设备(至少几十 GB,不占用系统内存)表现出坏扇区的行为。