Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

缓解libata触发NCQ bug的内核参数(cmdline) #897

Open
ctl26481 opened this issue Apr 27, 2024 · 3 comments
Open

缓解libata触发NCQ bug的内核参数(cmdline) #897

ctl26481 opened this issue Apr 27, 2024 · 3 comments
Labels
documentation Improvements or additions to documentation

Comments

@ctl26481
Copy link

ctl26481 commented Apr 27, 2024

首先感謝 @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

后来这块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
openzfs/zfs#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
openzfs/zfs#15270 (comment)

优点是重建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

供有需要的用户参考

免责声明:
操作前请先备份,数据无价,任何对硬盘相关的修改都有风险,本人不承担数据遗失的责任

@wjz304
Copy link
Contributor

wjz304 commented Apr 27, 2024

image
早就加了,没人看

@RROrg RROrg deleted a comment from github-actions bot Apr 27, 2024
@wjz304 wjz304 added the documentation Improvements or additions to documentation label Apr 27, 2024
@ctl26481
Copy link
Author

感谢指正和改成documentation
许久未更loader,往回翻没想到RR 24.1.1就有了

@gasment
Copy link

gasment commented May 16, 2024

我遇到类似的问题,一个组raid1的sata ssd每次重启都报无法访问系统分区,修复完能正常使用,只有开机那会报错failed command: WRITE FPDMA QUEUED,其他时间读写都没报错,尝试引导加入noncq,有效果,开机也不报无法访问系统分区了;
神奇的是我去掉noncq参数,后面反复重启测试也同样不报无法访问分区了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

3 participants