【问题标题】:How can I simulate a failed disk during testing?如何在测试期间模拟故障磁盘?
【发布时间】:2010-11-24 14:15:50
【问题描述】:

在 Linux 虚拟机(Vmware 工作站或类似工作站)中,如何在以前工作的磁盘上模拟故障?

我在生产中遇到光盘出现故障的情况(可能是控制器、电缆或固件问题)。显然这是不可预测或不可重现的,我想测试我的监控以确保它正确地发出警报。

理想情况下,我希望能够模拟写入失败但读取成功以及完全失败的情况,即 scsi 接口将错误报告回内核。

【问题讨论】:

    标签: linux testing io disk scsi


    【解决方案1】:

    有几个层可以模拟磁盘错误。如果您正在测试单个用户空间程序,可能最简单的方法是插入适当的调用(例如write())并让它们有时返回错误。 libfiu 故障注入库can do this 使用其fiu-run 工具。

    另一种方法是使用内核驱动程序,该驱动程序可以将数据传入/传出另一个设备,但在此过程中会注入错误。然后,您可以挂载该设备并从任何应用程序使用它,就好像它是一个有故障的磁盘一样。 fsdisk 驱动程序就是一个例子。

    还有一个错误注入基础架构已合并到 Linux 内核中,尽管您可能需要重新配置内核才能启用它。它记录在Documentation/fault-injection/fault-injection.txt 中。这对于测试内核代码很有用。

    也可以使用SystemTap 在内核级别注入错误。请参阅The SCSI fault injection testKernel Fault injection using SystemTap

    【讨论】:

      【解决方案2】:

      要添加到 mark4o 的答案,您还可以使用 Linux 的设备映射器来生成故障设备。

      Device Mapper's delay device 可用于将同一块的读写 I/O 发送到不同的底层设备(顾名思义,它还可以延迟该 I/O)。 Device Mapper 的错误设备可用于在访问特定块时生成永久错误。通过将两者结合起来,您可以创建一个设备,对于给定的区域,写入始终失败但读取始终成功。

      以上是问题Simulate a faulty block device with read errors? 中描述的更复杂的示例(有关简单的设备映射器示例,请参见https://stackoverflow.com/a/1871029)。

      Special File that causes I/O error Unix & Linux 问题上还有一个list of Linux disk fault injection mechanisms

      【讨论】:

        【解决方案3】:

        使用 2.6 内核使 SCSI 磁盘消失的简单方法是:

        echo 1 > /sys/bus/scsi/devices/H:B:T:L/delete
        

        (H:B:T:L 是主机、总线、目标、LUN)。不过,要模拟只读情况,您必须使用 mark4o 提到的故障注入方法。

        【讨论】:

          【解决方案4】:

          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
          

          https://lxadm.com/Using_fault_injection

          【讨论】:

            【解决方案5】:

            您可以使用scsi_debug 内核模块来模拟RAM 磁盘,它支持所有带有optsevery_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 在运行时更改 optsevery_nth 选项:

            echo 2 | sudo tee /sys/bus/pseudo/drivers/scsi_debug/opts
            echo 1 | sudo tee /sys/bus/pseudo/drivers/scsi_debug/opts
            

            【讨论】:

            • 您是否有一个链接可以显示如何为其余的 opts 选项产生错误?
            • @nick_g 对不起,我不知道,你在看哪个选项?
            • 我试图为 opts 的这些选项中的每一个产生一个错误: 4 - 忽略导致超时的“nth”命令。 8 - 导致“第 n 个”读取或写入命令产生 RECOVERED_ERROR。 0x10 - 导致“第 n 个”读写命令产生一个 ABORTED_COMMAND(ack/nak 超时),这是一个 SAS 传输错误。 0x20 - 导致“第 n 个”读写命令产生 ABORTED_COMMAND(逻辑块保护检查失败),名义上是 DIF(保护信息)错误
            【解决方案6】:

            也可以使用磁盘提供的方法进行媒体错误测试。 SCSI 有一个 WRITE LONG 命令,可用于通过使用无效 ECC 写入数据来破坏块。 SATA 和 NVMe 也有类似的命令。

            对于最常见的情况 (SATA),您可以使用带有 --make-bad-sector 的 hdparm 来使用该命令,对于 SCSI,您可以使用 sg_write_long,对于 NVMe,您可以使用带有 write-uncor 选项的 nvme-cli .

            与其他注入方法相比,这些命令的最大优势在于它们的行为也像驱动器一样,具有完整的延迟影响以及通过重新分配写入该扇区时的恢复。这还包括驱动器中的错误计数器。

            缺点是,如果您对同一个驱动器执行过多此操作,其错误计数器会上升,SMART 可能会将磁盘标记为坏盘,或者您可能会耗尽其重新分配表。因此,请务必将其用于手动测试,但如果您在自动测试中运行它,请不要经常这样做。

            【讨论】:

              【解决方案7】:

              您还可以使用低级 SCSI 实用程序 (sg3-utils) 来停止驱动器。它仍然会响应 Inquiry,因此它的状态仍然是“正在运行”,但读取和写入将失败,直到它再次启动。我已经以这种方式使用 mdadm 测试了 RAID 驱动器的移除和恢复。

              sg_start --stop /dev/sdb
              

              【讨论】:

                猜你喜欢
                • 2012-02-11
                • 2013-10-08
                • 2010-10-03
                • 2021-10-20
                • 2020-03-15
                • 2018-02-27
                • 1970-01-01
                • 2014-07-19
                • 1970-01-01
                相关资源
                最近更新 更多