模拟一个有读取错误的坏块设备?

17
我正在寻找一种更简单的方法来测试我的应用程序,针对故障块设备进行测试,当读取某些块时会生成i/o读取错误。使用已知有坏块的物理硬盘很麻烦,如果有软件解决方案的话我想找到一个。
我找到了Linux Disk Failure Simulation Driver,它允许创建一个接口,可以配置为在读取某些块范围时生成错误,但它适用于2.4 Linux内核,且未更新至2.6。
最理想的情况是,losetup和loop驱动程序还允许您将其配置为在尝试从给定的一组块中读取时返回读取错误。

1
除了答案之外,还可以在“特殊文件引起I/O错误Unix和Linux问题”的列表中查看Linux磁盘故障注入机制 - Anon
4个回答

30

你需要的不是回环设备,而是设备映射器。

使用dmsetup创建一个由“error”目标支持的设备,它将显示在/dev/mapper/<name>中。

设备映射程序演示文稿(PDF)的第7页上有你需要的内容:

dmsetup create bad_disk << EOF
  0 8       linear /dev/sdb1 0
  8 1       error
  9 204791 linear /dev/sdb1 9
EOF
或者省略部分,并将“error”目标设为块0-8(而不是)的设备,以创建一个纯错误磁盘。

另请参阅《RHEL 5逻辑卷管理器管理》中来自“设备映射器”附录的The Device Mapper


还有一个flakey目标 - 由linearerror组合而成,有时会成功。 还有一个delay,用于引入测试用的故意延迟。


完美地工作了 - 正是我所需要的。谢谢! - SteveG
上面的PDF文件没有解释(至少我没有理解)“dmsetup create”命令行语法。手册解释说:dmsetup create dev_name dev_mapper_table。第二个参数(dev_mapper_table)是一个文本文件,描述了块如何映射。dmsetup手册简洁,没有解释这个表的语法。这里有一个链接可以解释它... [链接](https://access.redhat.com/knowledge/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Logical_Volume_Manager_Administration/device_mapper.html#dm-mappings) - Roger Heathcote
重启计算机后,磁盘上的“错误”会自行解决吗? - Maksim
@Maksim:即使不重启,您仍然可以直接从/dev/sdb1读取。但是,除非您将dmsetup命令或等效配置放入启动文件中,否则这个虚拟设备(它提供了一个注入错误视图的/dev/sdb1)在重新启动后将无法继续存在。 - Peter Cordes
@PeterCordes 我的意思是:如果我强制导致磁盘出现问题,该如何撤销操作?重新启动机器/虚拟机是否可以通过将我的卷设置为ReadWrite来修复“错误”? - Maksim
@Maksim:这不会导致磁盘损坏。要做到这一点,您需要使用hdparm --make-bad-sector,这实际上会影响您的硬件。(手册警告说那非常危险。)使用设备映射器创建新的虚拟块设备不会在底层设备上创建错误。 - Peter Cordes

5

1
虽然链接可以用于进一步阅读,但我认为你应该明确地在这里提供一个具体的答案。 - U. Windl
它还取决于你使用的内核:例如,在SLES11 SP4内核中,该功能未被编译。 - U. Windl

4
使用nbd是与块设备玩耍的最简单方法。

git://github.com/yoe/nbd.git下载用户空间源代码,并修改nbd-server.c以在您希望失败的任何区域上读取或写入失败,或以可控制的随机模式失败,或者基本上您想要的任何内容。


0
我想对Peter Cordes的回答进行详细说明。
在bash中,使用loopback设备设置一个ext4镜像,然后将一个名为binary.bin的文件写入其中。
imageName=faulty.img
mountDir=$(pwd)/mount

sudo umount $mountDir ## make sure nothing is mounted here

dd if=/dev/zero of=$imageName bs=1M count=10
mkfs.ext4 $imageName
loopdev=$(sudo losetup -P -f --show $imageName); echo $loopdev
mkdir $mountDir
sudo mount $loopdev $mountDir
sudo chown -R $USER:$USER mount

echo "2ed99f0039724cd194858869e9debac4" | xxd -r -p > $mountDir/binary.bin

sudo umount $mountDir

Python3中(因为Bash处理二进制数据有困难),搜索binary.bin中的魔术二进制数据。
import binascii

with open("faulty.img", "rb") as fd:
    s = fd.read()
    
search = binascii.unhexlify("2ed99f0039724cd194858869e9debac4")

beg=0
find = s.find(search, beg); beg = find+1; print(find)

start_sector = find//512; print(start_sector)

然后在bash中挂载有故障的块设备

start_sector=## copy value from variable start_sector in python
next_sector=$(($start_sector+1))
size=$(($(wc -c $imageName|cut -d ' ' -f1)/512))
len=$(($size-$next_sector))

echo -e "0\t$start_sector\tlinear\t$loopdev\t0" > fault_config
echo -e "$start_sector\t1\terror" >> fault_config
echo -e "$next_sector\t$len\tlinear\t$loopdev\t$next_sector" >> fault_config

cat fault_config | sudo dmsetup create bad_drive
sudo mount /dev/mapper/bad_drive $mountDir

最终,我们可以通过读取文件来测试故障块设备。
cat $mountDir/binary.bin

出现错误的代码:

cat: /path/to/your/mount/binary.bin: Input/output error

测试完成后进行清理

sudo umount $mountDir
sudo dmsetup remove bad_drive
sudo losetup -d $loopdev
rm fault_config $imageName

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接