如何防止磁盘 I/O 超时导致磁盘断开连接和 SMR 磁盘数据损坏?

如何防止磁盘 I/O 超时导致磁盘断开连接和 SMR 磁盘数据损坏?

我有这些希捷磁盘(ST5000LM000 - 请注意它们是 SMR),当我将它们置于繁重的写入工作负载下时,I/O 利用率将达到 100%,吞吐量基本上为零。将磁盘插入使用mpt3sas驱动程序的 SAS 控制器(磁盘显示为 scsi 设备)。我尝试更改调度noop程序,将 ncq 设置为 1,并将设备超时增加到 1 小时。我什至尝试了一个完全不同的磁盘控制器(它使用megaraid驱动程序),它没有改变任何东西。每个驱动器都有一个 XFS 分区。

唯一有帮助的事情似乎是减少我的脚本写出文件的并发性,以便磁盘 I/O 永远不会落后太多,以至于滚雪球效应会使事情陷入停顿。

我认为echo 1 > /sys/block/sdl/device/queue_depth应该防止并发磁盘操作,但我通常会看到大约 150 个正在进行的操作cat /sys/block/sdl/stat

这是一个大问题,因为如果我在这种情况开始发生时不终止加载脚本,最终 I/O 操作会超时导致磁盘断开连接,这有时会导致进程陷入可怕的D状态,并且我经常会得到损坏的数据。

我可以更改内核设置以防止陷入这种糟糕的状态吗? 看来我应该做点什么,因为如果我足够早地杀死它,它总是可以在任何 i/o 操作超时并断开磁盘连接之前被捕获。

kern.log从磁盘实际断开连接时起

[401217.833235] sd 0:0:6:0: device_block, handle(0x0010)
[401218.583675] mpt3sas_cm0: log_info(0x31110e03): originator(PL), code(0x11), sub_code(0x0e03)
[401218.833518] sd 0:0:6:0: device_unblock and setting to running, handle(0x0010)
[401222.584105] sd 0:0:6:0: device_block, handle(0x0010)
[401230.581727] sd 0:0:6:0: device_unblock and setting to running, handle(0x0010)
[401230.586627] scsi_io_completion: 6 callbacks suppressed
[401230.586641] sd 0:0:6:0: [sdg] tag#0 FAILED Result: hostbyte=DID_NO_CONNECT driverbyte=DRIVER_OK
[401230.586656] sd 0:0:6:0: [sdg] tag#0 CDB: Read(16) 88 00 00 00 00 01 3b e5 74 18 00 00 02 00 00 00
[401230.586661] XFS (sdg): metadata I/O error: block 0x800007b8 ("xfs_trans_read_buf_map") error 5 numblks 32
[401230.586670] XFS (sdg): xfs_imap_to_bp: xfs_trans_read_buf() returned error -5.
[401230.597537] blk_update_request: 6 callbacks suppressed
[401230.597540] blk_update_request: I/O error, dev sdg, sector 5299860504

磁盘带宽基本上降至零 磁盘带宽基本上降至零 平均 I/O 请求时间猛增 平均 I/O 请求时间猛增 磁盘 I/O 保持 100% 利用率 磁盘 I/O 保持在 100% 利用率 运行中 I/O 请求保持在 150 左右 运行中 I/O 请求保持在 150 左右 (请注意,在上面的图像中,它最终恢复了,因为我在写入吞吐量显着下降时取消了加载脚本)

发行版/内核

$ lsb_release -d
Description:    Ubuntu 16.04.6 LTS
$ uname -r
4.15.0-62-generic

fdisk -l

Disk /dev/sdl: 4.6 TiB, 5000981078016 bytes, 9767541168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes

xfs_信息

meta-data=/dev/sdl               isize=512    agcount=5, agsize=268435455 blks
         =                       sectsz=4096  attr=2, projid32bit=1
         =                       crc=1        finobt=1 spinodes=0
data     =                       bsize=4096   blocks=1220942646, imaxpct=5
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
log      =internal               bsize=4096   blocks=521728, version=2
         =                       sectsz=4096  sunit=1 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0

答案1

我更改了以下内核参数,SMR 磁盘在高写入负载下不再断开连接。有时,在大量 I/O 下,写入性能会变得非常慢(例如个位数 MB/秒的写入速度),但磁盘至少不会再断开连接。

DEVICE=sdX # insert your device name here
echo 3600 > /sys/block/$DEVICE/device/timeout
echo 3600 > /sys/block/$DEVICE/device/eh_timeout
echo noop > /sys/block/$DEVICE/queue/scheduler
echo 1 > /sys/block/$DEVICE/device/queue_depth
echo 4 > /sys/block/$DEVICE/queue/nr_requests

我没有单独测试每一项,所以我不确定是否需要设置每一项,但这种组合确实对我有用。

答案2

与在 SMR 驱动器上使用 XFS 或 ext4 相比,我在使用 F2FS 方面获得了良好的体验。我的 ext4 在我的 SMR 驱动器上表现出与您上面描述的类似的行为,迫使我研究 Linux 中的 SMR 解决方案。我也遇到过你描述的超时问题。我也在使用Ubuntu,但是后来的Ubuntu 18.04.3 LTS版本。

首先,我绝不会推荐 SMR 驱动器用于具有高随机读/写操作的服务器。您希望避免使用 SMR 的用例示例是具有高读/写吞吐量的数据库和 NAS 应用程序。我的用例是 NAS 的外部备份,这没问题,因为它对时间要求不高,而且大多是连续的。

首先要做的是获取 F2FS 文件系统,在 18.04 下该文件系统非常简单:

sudo apt install f2fs-tools

使用gparted删除 SMR 驱动器中的所有分区,然后使用gparted创建跨整个驱动器的 F2FS 分区。

我的驱动器(东芝)预格式化了 2 个分区,以便在 MS-Windows 操作系统计算机上使用。如果我保留较小的第一个分区,那么无论我安装什么文件系统,写入速度都很糟糕。我强烈怀疑第一个分区是驱动器的非 SMR 部分分配用于其日志和其他元数据的地方。我的经验表明,创建的文件系统能够访问该区域以从中受益非常重要。

不幸的是,gparted 似乎没有一个地方可以让我设置选项来正确创建适合块分区 SMR 驱动器的文件系统。记下分区标识信息后,我退出gparted并手动运行 mkfs 命令,这次添加了魔法:

sudo mkfs.f2fs -fm /dev/XXXX

XXXX您之前在 中确定的分区在哪里gparted。该 -m 选项非常重要,因为它告诉 F2FS 使用 SMR 驱动器的阻塞区域功能。没有它,我的经验表明你将在木瓦地狱中苦苦挣扎。

完成此操作(并安装后),写入驱动器相当一致。我的写入速度大多在 117MB/s 到 105MB/s 之间。偶尔有几秒钟,写入速度会降至 70-80MB/s。

我怀疑 SMR 驱动器必须通过重写驱动器上有木瓦重叠的区域来迎头赶上。幸运的是,这种情况并不经常发生,尽管我承认我(尚未)还没有利用硬盘驱动器上的一半可用空间。当这种情况发生时,我预计叠瓦写入会更频繁地发生,因此备份将花费更长的时间。然而,现在,它在避免盘片的叠瓦区域方面做得非常好,我很难找到许多表现出减速的例子。它似乎还利用设备的未封装区域来存储其元数据(日志),这避免了您所描述的大规模减速。

我还注意到,在读取完成且命令提示符返回后,F2FS 需要大约 10 秒的时间来刷新剩余数据。在此期间请勿卸载设备或拔掉电源插头,以免数据丢失,这一点很重要。如果您使用的是 shell 脚本,请记住这一点。

我想你会同意我使用 F2FS 的写入速率远远超过你使用 xfs 演示的写入速率。此外,我不需要更改任何超时即可实现这一点。

相关内容