在Linux VM(Vmware工作站或类似工具)中,如何模拟以前工作的光盘上的故障?
我在生产中遇到光盘发生故障(可能是控制器,电缆或固件问题)的情况。显然这是不可预测或可重现的,我想测试我的监控,以确保它正确警报。
理想情况下,我希望能够模拟写入失败但成功读取的情况,以及完全失败,即scsi接口将错误报告给内核。
有几个层可以模拟磁盘错误。如果您正在测试单个用户空间程序,可能最简单的方法是插入适当的调用(例如write()
)并让它们有时返回错误。 libfiu
故障注入库can do this使用其fiu-run
工具。
另一种方法是使用可以向/从另一个设备传递数据的内核驱动程序,但是沿途注入错误。然后,您可以挂载设备并在任何应用程序中使用它,就像它是一个有故障的磁盘一样。 fsdisk驱动程序就是一个例子。
还有一个故障注入基础结构已合并到Linux内核中,但您可能需要重新配置内核才能启用它。它记录在Documentation/fault-injection/fault-injection.txt中。这对于测试内核代码很有用。
也可以使用SystemTap在内核级别注入错误。见The SCSI fault injection test和Kernel Fault injection using SystemTap。
要添加到mark4o的答案,您还可以使用Linux的Device Mapper生成失败的设备。
Device Mapper's delay device可用于将同一块的读写I / O发送到不同的底层设备(它也可以根据其名称延迟I / O)。 Device Mapper的错误设备可用于在访问特定块时生成永久性错误。通过组合这两者,您可以创建一个设备,其中写入始终失败但读取始终对给定区域成功。
以上是问题Simulate a faulty block device with read errors?中描述的更复杂的示例(有关简单的Device Mapper示例,请参阅https://stackoverflow.com/a/1871029)。
在list of Linux disk fault injection mechanisms Unix和Linux问题上还有一个Special File that causes I/O error。
使用2.6内核使SCSI磁盘消失的一种简单方法是:
echo 1 > /sys/bus/scsi/devices/H:B:T:L/delete
(H:B:T:L是主机,总线,目标,LUN)。为了模拟只读的情况,你必须使用mark4o提到的故障注入方法。
Linux内核提供了一个很好的功能,称为“故障注入”
echo 1 > /sys/block/vdd/vdd2/make-it-fail
要设置一些选项:
mkdir /debug
mount debugfs /debug -t debugfs
cd /debug/fail_make_request
echo 10 > interval # interval
echo 100 > probability # 100% probability
echo -1 > times # how many times: -1 means no limit
还可以使用磁盘提供的方法进行媒体错误测试。 SCSI具有WRITE LONG命令,可通过使用无效ECC写入数据来破坏块。 SATA和NVMe也有类似的命令。
对于最常见的情况(SATA),您可以使用hdparm和--make-bad-sector来使用该命令,您可以将sg_write_long用于SCSI,对于NVMe,您可以将nvme-cli与write-uncor选项一起使用。
这些命令相对于其他注入方法的最大优点是它们的行为与驱动器一样,具有完全延迟的影响,并且还通过重新分配对该扇区进行写入时的恢复。这还包括驱动器中出现的错误计数器。
缺点是,如果对同一驱动器执行此操作太多,则其错误计数器将上升,SMART可能会将磁盘标记为错误,或者您可能耗尽其重新分配表。因此,请将其用于手动测试,但如果您在自动化测试中运行它,请不要经常这样做。
您可以使用scsi_debug
内核模块来模拟RAM磁盘,它支持使用opts
和every_nth
选项的所有SCSI错误。
请检查这个http://sg.danny.cz/sg/sdebug26.html
关于扇区4656的中等错误的示例:
[fge@Gris-Laptop ~]$ sudo modprobe scsi_debug opts=2 every_nth=1
[fge@Gris-Laptop ~]$ sudo dd if=/dev/sdb of=/dev/null
dd: error reading ‘/dev/sdb’: Input/output error
4656+0 records in
4656+0 records out
2383872 bytes (2.4 MB) copied, 0.021299 s, 112 MB/s
[fge@Gris-Laptop ~]$ dmesg|tail
[11201.454332] blk_update_request: critical medium error, dev sdb, sector 4656
[11201.456292] sd 5:0:0:0: [sdb] FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
[11201.456299] sd 5:0:0:0: [sdb] Sense Key : Medium Error [current]
[11201.456303] sd 5:0:0:0: [sdb] Add. Sense: Unrecovered read error
[11201.456308] sd 5:0:0:0: [sdb] CDB: Read(10) 28 00 00 00 12 30 00 00 08 00
[11201.456312] blk_update_request: critical medium error, dev sdb, sector 4656
您可以通过sysfs在运行时更改opts
和every_nth
选项:
echo 2 | sudo tee /sys/bus/pseudo/drivers/scsi_debug/opts
echo 1 | sudo tee /sys/bus/pseudo/drivers/scsi_debug/opts
您还可以使用低级SCSI实用程序(sg3-utils)来停止驱动器。它仍将响应查询,因此其状态仍将“正在运行”,但读取和写入将失败,直到它再次启动。我已经通过这种方式使用mdadm测试了RAID驱动器的移除和恢复。
sg_start --stop /dev/sdb