收起左侧

记录一次 fnOS 高 IO 等待的排查:从 discard 风暴到硬件 TRIM 兼容问题

0
回复
43
查看
[ 复制链接 ]

0

主题

0

回帖

0

牛值

江湖小虾

工控机 SSD 的 TRIM 缺陷引发 fnOS 高 IO 等待的排查与解决

设备硬件环境

项目 详情
NAS 系统 飞牛私有云 fnOS
内核版本 6.18.18-trim
CPU 双核 x86_64
系统盘 (SSD) SSD64G(59GB SATA SSD,工控机自带杂牌盘)
数据盘 (HDD) 465.8GB 机械硬盘
存储布局 /vol1(Btrfs)位于 SSD,承载系统及 Docker;/vol2(Btrfs)位于 HDD

磁盘具体分配情况(lsblk -o NAME,TYPE,SIZE,ROTA,MOUNTPOINT 摘要):

NAME                TYPE   SIZE ROTA MOUNTPOINT
sda                 disk 465.8G   1 
**─sda1              part 465.8G   1 
  **─md1             raid1 465.6G  1 
    **─trim_...-0    lvm   465.6G  1 /vol2
sdb                 disk    59G   0 
**─sdb1              part    94M   0 /boot/efi
**─sdb2              part  31.9G   0 /
**─sdb3              part    27G   0 
  **─md0             linear   27G  0 
    **─trim_...-0    lvm      27G  0 /vol1

一句话结论

工控机自带的 SSD(型号 SSD64G)固件存在 TRIM 指令处理缺陷,飞牛系统默认开启的在线 discard 触发了硬件错误,内核反复重试导致 IO 等待飙高。

下面详细记录排查过程和解决方法。

问题现象

近期发现 NAS 操作响应变慢,Web 界面偶尔卡顿。用 top 观察,CPU iowait 经常在 50%~90% 之间波动。使用 iostat -x 1 5 进一步查看,发现系统盘 sdb 及其映射设备存在大量 discard 操作:

iostat -x 1 5

典型输出:

Device   ...   d/s     dkB/s      %util
dm-0     ...  32.00  2097152.00   99.60
md0      ...  32.00  2097152.00   99.60
sdb      ...  32.00  2097152.00   92.40
  • d/s 每秒约 30 次 discard 请求
  • dkB/s 接近 2GB/s
  • %util 打满到 90%+
  • CPU %iowait 在 60%~80%

而机械盘 sdad/s 为 0,问题明显集中在 SSD 上。重启后暂时缓解,但一天左右又会复发。

排查过程:从软件到硬件

1. 检查挂载选项

mount | grep vol1

输出包含 discard=async,表明飞牛对 SSD 上的 Btrfs 默认开启了在线丢弃。这本身是合理的设计——SSD 开启在线 TRIM 有助于性能维护。但在我的设备上,这恰恰触发了问题。

2. 尝试关闭在线 discard

先后试了三种方法:

  • 修改 /etc/fstab 添加 nodiscard:IO 风暴停止,但 fstrim 也失败了,说明 nodiscard 把 TRIM 通道全关了。
  • discard_max_bytes 设为 0:风暴停止,但 fstrim 仍然失败,且重启前无法恢复。
  • 修改 /etc/mountmgr/mount_info.json:文件中根本没有 discard 字段,飞牛是动态追加的。

三种方法都能停掉风暴,但 fstrim 始终报错,这提示问题可能不在软件配置层面。

3. 内核日志发现真相

查看内核日志:

sudo dmesg | tail -30

发现了关键错误:

ata2.00: failed command: DATA SET MANAGEMENT
sd 1:0:0:0: [sdb] tag#11 Sense Key : Medium Error [current]
sd 1:0:0:0: [sdb] tag#11 Add. Sense: Address mark not found for data field
I/O error, dev sdb, sector 92387328 op 0x3:(DISCARD) flags 0x800

op 0x3:(DISCARD) 明确指示这是 TRIM 指令触发的错误。Sense Key 为 Medium Error,说明 SSD 的固件在处理 DISCARD 命令时直接返回了介质错误。

至此确认:这块工控机自带的 SSD64G 固件存在 TRIM 指令处理缺陷,一收到 DISCARD 命令就报错。 飞牛的 discard=async 让内核不断发送 TRIM 请求,SSD 每次都报错,内核反复重试,最终形成 discard 风暴。

关于这块 SSD

SSD64G 常见于工控机、软路由、部分国产迷你主机自带的 SATA 固态硬盘,多采用慧荣(SM2258XT)或联芸主控搭配低端闪存颗粒。网上也能搜到类似型号在 Linux 下执行 TRIM 时报 Medium Error 的讨论,并非个例。

这类盘的 TRIM 问题属于硬件层面的缺陷,无法通过固件升级或软件配置修复。唯一的根本解决方式是更换一块主流品牌的 SSD。

解决方案:内核参数禁止在线 discard

既然硬件不支持 TRIM,就需要从内核层面阻止 Btrfs 发出任何 discard 请求。Linux 内核提供了 btrfs.discard=0 参数,它会忽略所有挂载选项中的 discard,但不影响用户态 fstrim(正常 SSD 仍可手动回收)。

操作步骤:

  1. 编辑 GRUB 配置文件:

    sudo nano /etc/default/grub
    

    GRUB_CMDLINE_LINUX_DEFAULT 行末尾添加 btrfs.discard=0

    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash btrfs.discard=0"
    
  2. 更新 GRUB 并重启:

    sudo update-grub
    sudo reboot
    
  3. 重启后验证:

    • iostat -x 1 5d/s 归零,%iowait 回到正常水平。
    • mount | grep vol1 仍显示 discard=async(飞牛自动添加),但内核已忽略。
    • 由于硬件缺陷,fstrim 仍会失败。
  4. 禁用系统自带的每周 TRIM 定时器(避免无意义报错):

    sudo systemctl disable --now fstrim.timer
    

效果对比

指标 修复前 修复后
CPU iowait 50%~90% 0%~10%
discard d/s 30+ 0
%util 90%+ 正常
重启后是否失效 会复发 永久生效

其他可能导致 IO 高的情况

如果排查了 discard 问题后 IO 仍然偏高,可以检查:

  • 迅雷 / 网心云插件:有用户反映禁用插件后恢复正常。
  • upload 上传服务:Web 上传后可能触发 iowait 飙升。
  • 相册同步 / USB 外接硬盘:后台同步或易驱线连接可能导致异常 IO。
  • Docker 容器:运行 sudo iotop -o 查看高 IO 进程。

小结与建议

这次问题的核心是工控机自带的杂牌 SSD 固件存在 TRIM 指令处理缺陷,而飞牛默认对 SSD 开启在线 discard 恰好触发了这个硬件问题。排查过程中的几点体会:

  1. 高 iowait 时先看 iostatd/s 列,如果异常高,很可能与 discard 有关。
  2. dmesg 中的 op 0x3:(DISCARD) 是判断硬件 TRIM 兼容性的关键线索。
  3. 内核参数 btrfs.discard=0 可以在不破坏 fstrim 能力的前提下关闭在线 discard。
  4. 如果条件允许,更换一块可靠品牌的 SSD 是更彻底的解决方案。

给飞牛团队的建议:能否在挂载 SSD 时先发送测试 discard 请求检测硬件是否支持,再决定是否添加 discard=async?或者提供图形化的在线 TRIM 开关。


免责提醒:本文涉及修改内核启动参数等系统级操作,请确保已备份重要数据,谨慎执行。不同硬件环境、系统版本可能存在差异,文中方法仅供参考。本文内容由 AI 辅助生成,如有不当之处欢迎指正。

收藏
送赞
分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则