缓解libata触发NCQ bug的内核参数(cmdline)
首先感謝 @wjz304 dalao
不算RR bug,主要是libata的问题,这里就当记载了 毕竟和突发崩盘、崩阵列的触发条件可能有关 (例如突发崩盘,重建阵列后确认SMART显示健康,也没有C7错误)
原由: 起因是几个月前更换硬盘发现dmesg偶发WRITE/READ FPDMA QUEUED错误 找了不少文章后并未找出确切的触发原因,只知道可能和NCQ有关 当时为了避免夜长梦多就将刚换的硬盘打上noncq,FPDMA QUEUED错误也就没再度出现 (原本为两块ST1000DM003,更换为两块WD20EFRX)
没想到近期测试Hyper Backup备份 对另一组正常运作一年的RAID1阵列高强度读取就触发NCQ bug 造成其中一块被剔除阵列,硬盘显示「严重」状态 (这两块都是HGST 7K1000 2.5”,仅固件不同)
这组阵列之前都会定期SMART检测(快速、完整一个月各一次)和资料清洗 从来没出现过掉盘问题,怀疑是Hyper Backup高强度存取造成的
从dmesg可发现多个FPDMA QUEUED错误
[986753.706557] ata12.00: exception Emask 0x0 SAct 0x7e SErr 0x0 action 0x6 frozen [986753.710727] ata12.00: failed command: READ FPDMA QUEUED [986753.713952] ata12.00: cmd 60/c0:08:b8:13:dc/02:00:50:00:00/40 tag 1 ncq 360448 in res 40/00:01:00:00:00/00:00:00:00:00/00 Emask 0x4 (timeout) [986753.722301] ata12.00: status: { DRDY } // 以下省略
接着mdadm将其剔除(注意md1交换分区并无掉盘警告)
[986834.606420] sd 11:0:0:0: [sdf] tag#4 UNKNOWN(0x2003) Result: hostbyte=0x00 driverbyte=0x06 [986834.611444] sd 11:0:0:0: [sdf] tag#4 CDB: opcode=0x2a 2a 00 00 4c 05 00 00 00 08 00 [986834.615933] blk_update_request: I/O error, dev sdf, sector in range 4980736 + 0-2(12) [986834.620335] write error, md0, sdf1 index [5], sector 4973824 [raid1_end_write_request] [986834.624921] md_error: sdf1 is being to be set faulty [986834.628120] raid1: Disk failure on sdf1, disabling device. Operation continuing on 3 devices [986834.632234] sd 11:0:0:0: [sdf] tag#1 UNKNOWN(0x2003) Result: hostbyte=0x00 driverbyte=0x06 [986834.634988] sd 11:0:0:0: [sdf] tag#1 CDB: opcode=0x2a 2a 00 21 44 8c 80 00 00 08 00 [986834.637359] blk_update_request: I/O error, dev sdf, sector in range 558137344 + 0-2(12) [986834.639445] write error, md3, sdf3 index [5], sector 536898688 [raid1_end_write_request] [986834.641378] md_error: sdf3 is being to be set faulty [986834.642649] raid1: Disk failure on sdf3, disabling device. Operation continuing on 1 devices
从mdstat确认阵列状态:
root@NAS:~# cat /proc/mdstat
Personalities : [raid1]
md3 : active raid1 sdd3[0] sdf3[1](F)
966038208 blocks super 1.2 [2/1] [U_]
// 掉一块的HGST 1T阵列
md2 : active raid1 sde3[3] sdc3[2]
1942790208 blocks super 1.2 [2/2] [UU]
// 正常运作的WD 2T阵列
md1 : active raid1 sdf2[0] sdd2[3] sde2[2] sdc2[1]
2097088 blocks [12/4] [UUUU________]
// 交换空间正常运作,代表并非整块硬盘"被拔下"
md0 : active raid1 sde1[0] sdc1[3] sdd1[2] sdf1[12](F)
2490176 blocks [12/3] [U_UU________]
// 其中一块HGST被剔除的系统分区
另外不确定是否为loader问题(我用的是TCRP)
日誌中心记载I/O错误的信息在1970年,而非实际发生的时间
后来这块HGST检视SMART健康,低格也没发现问题 将所有SATA接口使用noncq选项,手动卸载后就正常重建阵列了 重新执行了一遍Hyper Backup备份(高强度存取)也没有再次触发 我认为实际可能只是NCQ bug被触发,让mdadm将盘剔除
至于为何只有一块盘被剔除? 猜测可能是mdadm RAID1优先读取这块盘,造成这块盘被剔除 不太敢想像有校验盘RAID5/6或混合RAID同时存取时被剔除的情况 md1交换空间则可能是没有过多存取,所以没被剔除(实体6GB RAM)
原因: 触发libata NCQ bug的条件不明,可能和libata本身quirk有关 目前可找到的资料都排除硬盘、线、SATA控制器的锅 Intel、AMD皆有原生SATA接口触发的案例
在和磁盘性能的issue有时便会提及关闭NCQ https://github.com/openzfs/zfs/issues/15270
以机械盘来说触发NCQ bug在dmesg会显示WRITE/READ FPDMA QUEUED错误 固态盘也是会有类似信息,实际为NCQ TRIM触发
实际上也有原厂主机+NAS专用盘触发的回报,使用noncq强制关闭NCQ后性能恢復正常 https://www.reddit.com/r/synology/comments/eri5dg
甚至有新硬盘碰到bug认为是坏盘而退货的用户 当然也没缺胡搞瞎搞,缺乏后续追踪的文章(例如更换SATA数据线、电源线)
解决方法: 通常在存储社群都会推荐改用IT模式LSI/Broadcom SAS HBA 稳定是稳定(毕竟驱动也换成mpt*sas),但换来的自然是电老虎SAS HBA卡 对于低功耗环境下得不偿失,且多佔了一个PCI-E卡槽 部分loader型号也对SAS HBA支持度不佳
要在一般SATA接口下要解决/缓解(mitigate)NCQ bug
首先是libata.force的内核参数noncq,对应到kernel parameter(cmdline):
libata.force=noncq
选择性关闭特定接口的NCQ
libata.force=X.00:noncq,Y.00:noncq,Z.00:noncq…依此类推
(X、Y对应至dmesg内的ata顺序号)
对SSD关闭NCQ TRIM可以使用:
libata.force=noncqtrim(部分SSD可能需要加入trim_zero?)
对SSD使用noncq也有noncqtrim的效果,但会完全关闭NCQ
寻找ata顺序号的方式(例):
root@NAS:~# dmesg | grep -i 'ata[0-9]+.00' [ 12.325844] ata1.00: FORCE: horkage modified (noncq) [ 12.330834] ata2.00: ATA-9: ST2000NM0033-9ZM175, SN03, max UDMA/133 [ 12.337106] ata2.00: 3907029168 sectors, multi 0: LBA48 NCQ (depth 31/32), AA [ 12.344246] ata2.00: SN: TESTTEST [ 12.348548] ata1.00: ATA-8: WDC WD2001FFSX-68JNUN0, 81.00A81, max UDMA/133 [ 12.355429] ata1.00: 3907029168 sectors, multi 0: LBA48 NCQ (not used) [ 12.361959] ata1.00: SN: WD-TESTTESTTEST [ 12.366773] ata1.00: configured for UDMA/133 [ 12.371208] ata2.00: configured for UDMA/133
上述为找寻ata顺序号的方式 ata1已使用libata.force=1.00:noncq关闭NCQ,此时dmesg显示:
ata1.00: FORCE: horkage modified (noncq) ata1.00: 3907029168 sectors, multi 0: LBA48 NCQ (not used) // 即NCQ关闭成功
另一方式不用重开,直接在系统下对/sys/block…的queue_depth写入1 依照上游记载此方式确实可让libata关闭NCQ https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=360f654e7cda850034f3f6252a7a7cff3fa77356
但有硬盘热插拔或不知道盘符(打乱),必须手动寻找并执行的缺点
可在计划任务设定为开机触发
echo 1 > /sys/block/sdN/device/queue_depth ; echo 1 > /sys/block/sdM/device/queue_depth ; echo 1…依此类推
或使用这个script将所有能找到的盘符queue_depth都写入1 https://github.com/openzfs/zfs/issues/15270#issuecomment-1769509416
优点是重建loader不会有忘记加入kernel parameter造成触发NCQ bug,可当双重保险 但对SSD NCQ TRIM来说就不行了,有回报对queue_depth写入1也无效的情况 只得使用libata内核参数强制关闭NCQ TRIM https://bugzilla.kernel.org/show_bug.cgi?id=201693
另外在/var.defaults/lib/diskaction/diskaction.xml也有列出一些SSD、HDD的缓解措施 不过没有和上游libata-core.c同步的样子,除非自有内核有backport这些黑名单
例如我也怀疑NCQ TRIM bug和这篇遇到Micron 1100降级有关 https://xpenology.com/forum/topic/70001-main-and-important-918-fake-error-from-ssd-most-likely-synology-compatibility-need-2tb-working-urgently-help-please/
从libata-core.c可以看到Micron 1100要关闭NCQ TRIM和启用TRIM以后写入0的功能
{ "Micron_1100_*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | ATA_HORKAGE_ZERO_AFTER_TRIM, },
diskaction.xml在消费版本的MX300就有指定关闭TRIM功能,但并未包含Micron 1100
结语: libata有特定NCQ bug,触发时可能造成硬盘性能异常后被阵列剔除 要检测可以在dmesg寻找有无FPDMA QUEUED错误信息
当前并没有确切原因可说明libata和硬件、固件组合有问题,只能关闭NCQ缓解此现象 SSD则有NCQ TRIM bug,除了noncqtrim以外也可能需要trim_zero?(前者noncq可一併关闭,但影响SSD多线程性能) 若特定AMD/ATi晶片组的条件下可能也需要ATA_HORKAGE_NO_NCQ_ON_ATI(不確定kernel parameter syntax)
~~提议可将libata.force=noncq列为kernel cmdline的进阶除错选项~~ (已在loader選項中) 若从个别ata接口关闭则要手动编辑
当然将所有硬盘的NCQ都关闭是最安全的作法 但NCQ是对多线程性能有益的功能,关闭的话会造成性能耗损,不过稳定还是优先于性能吧 个人只有在RAID1的条件下使用过,不确定对RAID5、RAID6与多盘混合RAID的性能影响 可能需要多方验证
目前尚未观察到有其它负面影响 DSM似乎会偶尔提醒硬盘资料库更新后要重开机最佳化的讯息
我在这篇有较为详细的英文说明和dmesg: https://xpenology.com/forum/topic/35882-new-sataahci-cards-with-more-then-4-ports-and-no-sata-multiplexer/?do=findComment&comment=460315
供有需要的用户参考
免责声明: 操作前请先备份,数据无价,任何对硬盘相关的修改都有风险,本人不承担数据遗失的责任
早就加了,没人看
感谢指正和改成documentation 许久未更loader,往回翻没想到RR 24.1.1就有了
我遇到类似的问题,一个组raid1的sata ssd每次重启都报无法访问系统分区,修复完能正常使用,只有开机那会报错failed command: WRITE FPDMA QUEUED,其他时间读写都没报错,尝试引导加入noncq,有效果,开机也不报无法访问系统分区了; 神奇的是我去掉noncq参数,后面反复重启测试也同样不报无法访问分区了