USB-SATA 桥接芯片的 UAS 兼容性问题排查
通过 USB 外接硬盘时,如果遇到磁盘看起来一直很忙,但实际吞吐很低,问题不一定出在文件系统或硬盘本体上。一次比较典型的场景是:USB-SATA 桥接芯片声称支持 UAS,但它的固件实现不稳定,Linux 自动启用 UAS 后反而触发命令超时、USB 设备重置,最终表现成系统层面的 I/O 卡顿。
这篇文章记录一次这类问题的现象、原因和处理方式。
问题现象#
故障最直观的表现是:外接硬盘几乎不可用,但监控上又看不出正常的高吞吐。
常见现象包括:
iostat中磁盘%util长时间接近或等于100%;- 实际
r/s、w/s、rkB/s、wkB/s并不高; await、svctm或应用侧读写延迟异常升高;- 文件复制、解压、数据库读写、备份任务间歇性卡住;
- 偶尔出现
Input/output error; dmesg或journalctl -k中反复出现 UAS abort、SCSI timeout、USB reset。
可以先用下面这些命令观察:
iostat -xz 1
dmesg -T | grep -Ei 'uas|usb|reset|abort|I/O error|blk_update_request'
journalctl -k -b | grep -Ei 'uas|usb|reset|abort|I/O error'
比较典型的内核日志类似这样:
uas_eh_abort_handler ...
scsi host... uas_eh_device_reset_handler
usb ... reset SuperSpeed USB device number ...
blk_update_request: I/O error, dev sdX, sector ...
如果这些日志和外接硬盘卡顿时间点高度重合,就要怀疑 USB 存储协议层的问题。
背景:UAS 和 BOT 是什么#
USB 外接硬盘通常不是硬盘直接接入系统,而是经过一个 USB-SATA 桥接芯片。Linux 看到的是一个 USB Mass Storage 设备。
这类设备常见有两种工作模式:
- BOT:Bulk-Only Transport,传统 USB 存储传输方式,兼容性好,协议相对简单;
- UAS / UASP:USB Attached SCSI,支持更现代的 SCSI 命令队列,理论上并发能力和性能更好。
Linux 内核会根据 USB 设备上报的能力选择驱动。如果设备声明自己支持 UAS,系统通常会优先使用 uas 驱动,而不是传统的 usb-storage BOT 模式。
问题在于,并不是所有桥接芯片的 UAS 固件实现都可靠。部分 JMicron、Realtek、ASMedia 早期型号或某些硬盘盒固件,在真实负载下会出现命令超时、异常复位、队列阻塞等问题。
为什么会表现为“忙但不快”#
这类问题容易误导排查方向,因为表面上看磁盘很忙:%util 很高,任务卡住,应用阻塞。
但它的本质不是磁盘正在高效工作,而是 I/O 请求卡在队列里等超时、重试、reset。
简化一下链路:
应用读写
-> 文件系统 / 块设备层
-> SCSI 命令
-> uas 驱动
-> USB-SATA 桥接芯片
-> SATA 硬盘
当 UAS 这层出现兼容性问题时,请求可能已经提交给内核块层,但桥接芯片没有稳定完成命令。于是内核不断等待、abort、reset,应用侧就看到延迟飙升,监控侧则看到磁盘一直处于繁忙状态。
这也是为什么它和真正的磁盘性能瓶颈不太一样:吞吐并不高,但延迟非常差。
确认当前设备是否使用 UAS#
先查看 USB 设备:
lsusb
输出中会看到类似:
Bus 002 Device 004: ID 152d:0578 JMicron Technology Corp. / JMicron USA Technology Corp. JMS567 SATA 6Gb/s bridge
其中 152d:0578 就是 VendorID:ProductID。
再确认这个磁盘绑定的驱动。可以看内核日志:
dmesg -T | grep -Ei 'uas|usb-storage|scsi'
如果看到类似下面的内容,说明设备正在使用 UAS:
usbcore: registered new interface driver uas
scsi host... uas
也可以通过 lsusb -t 查看驱动绑定情况:
lsusb -t
如果某个 USB 存储设备下面显示 Driver=uas,就说明它当前走的是 UAS。
解决方法:对问题设备禁用 UAS#
处理思路不是全局禁用 USB 存储,而是只对有问题的 VendorID:ProductID 加 quirks,让它不要走 UAS,降级为传统 BOT 模式。
假设 lsusb 查到的问题设备是:
ID 152d:0578
那么可以写入 modprobe 配置:
sudo sh -c 'echo "options usb-storage quirks=152d:0578:u" > /etc/modprobe.d/usb-storage-uas-quirks.conf'
这里的 u 表示对该设备禁用 UAS。
然后更新 initramfs 并重启:
sudo update-initramfs -u
sudo reboot
重启后再次检查:
lsusb -t
目标设备如果从:
Driver=uas
变为:
Driver=usb-storage
就说明配置已经生效。
不同发行版的注意点#
Debian、Ubuntu 通常使用:
sudo update-initramfs -u
RHEL、CentOS、Rocky Linux、AlmaLinux 这类系统可能需要使用:
sudo dracut -f
Arch Linux 常见是:
sudo mkinitcpio -P
如果设备不是启动盘,有些情况下重新插拔设备或重新加载模块也可能生效。但对于稳定处理,尤其是服务器或长期运行环境,更新 initramfs 后重启更直接,也更容易验证状态。
性能影响大吗#
对机械硬盘来说,BOT 和 UAS 的性能差异通常不明显。机械盘自身随机读写能力、寻道延迟和盘片吞吐往往才是主要瓶颈。
UAS 的优势更多体现在命令队列和并发能力上,对 SSD 或高负载并发场景更有价值。但如果桥接芯片 UAS 实现不稳定,理论性能没有意义,稳定完成 I/O 才是第一优先级。
所以对于机械硬盘外接盒,降级到 BOT 后通常不会损失可感知性能,反而能明显改善稳定性。
回滚方法#
如果后续更换了硬盘盒、升级了桥接芯片固件,或者确认不是 UAS 问题,可以删除配置并重新生成 initramfs:
sudo rm /etc/modprobe.d/usb-storage-uas-quirks.conf
sudo update-initramfs -u
sudo reboot
重启后再用 lsusb -t 确认设备是否重新绑定到 uas。
排查经验总结#
遇到 USB 外接硬盘异常卡顿时,不要只盯着文件系统和硬盘坏道。下面这些信号同时出现时,应该优先检查 UAS 兼容性:
- 外接 USB 硬盘
%util长期 100%,但吞吐很低; - 应用读写卡顿,偶尔出现
I/O error; - 内核日志反复出现
uas_eh_abort_handler、SCSI timeout、USB reset; lsusb -t显示目标设备正在使用Driver=uas;- 换线、换 USB 口、换供电后问题仍然存在。
最终解决方案是对具体问题设备禁用 UAS,让它走 usb-storage BOT 模式。对于机械硬盘外接盒,这通常是一个稳定性收益远大于性能损失的选择。