如何(真正)在 Linux 中禁用 NCQ

Pae*_*els 20 linux drivers kernel sata

我在 VHDL 中实现了我自己的串行 ATA 主机总线适配器 (HBA) 并将其编程到 FPGA 上。FPGA是可以用任何数字电路编程的芯片。它还配备了串行收发器,可为 SATA 或 PCIe 生成高速信号。

此 SATA 控制器支持 SATA 6 Gb/s 线速,并使用 ATA-8 DMA-IN/OUT 命令以高达 32 MiB 的数据块与设备传输数据。该设计已被证明可以以最大速度运行(例如三星 SSD 840 Pro -> 超过 550 MiB/s)。

在对几个 SSD 和 HDD 设备进行了一些测试之后,我购买了一个新的希捷 6 TB Archive HDD ( ST6000AS0002 )。这款硬盘的读取性能高达 190 MiB/s,但写入性能只有 30 到 40 MiB/s!

所以我深入挖掘并测量了传输的帧(是的,FPGA 设计可以实现)。据我所知,希捷硬盘已准备好一次性接收传输的前 32 MiB。此传输以 580 MiB/s 的最大线路速度进行。之后,硬盘将剩余字节停止超过800 毫秒!然后 HDD 准备好接收下一个 32 MiB 并再次停止 800 毫秒。总而言之,1 GiB 传输需要超过 30 秒,相当于大约 35 MiB/s。

我假设这个 HDD 有一个 32 MiB 的写缓存,它在突发周期之间被刷新。小于 32 MiB 的数据传输不会显示此行为。

我的控制器使用 DMA-IN 和 DMA-OUT 命令来传输数据。我没有使用 QUEUED-DMA-IN 和 QUEUED-DMA-OUT 命令,它们由支持 NCQ 的 AHCI 控制器使用。在 FPGA 平台上实现 AHCI 和 NCQ 非常复杂,我的应用层不需要。

我想在我的 Linux PC 上重现这个场景,但 Linux AHCI 驱动程序默认启用了 NCQ。我需要禁用 NCQ,所以我发现这个网站描述了如何禁用 NCQ,但它不起作用。

Linux PC 仍然达到 190 MiB/s 的写入性能。

> dd if=/dev/zero of=/dev/sdb bs=32M count=32
1073741824 bytes (1.1 GB) copied, 5.46148 s, 197 MB/s
Run Code Online (Sandbox Code Playgroud)

我认为上面的文章有一个错误:将NCQ队列深度减少到1并没有禁用NCQ。它只允许操作系统使用一个队列。它仍然可以使用 QUEUED-DMA-** 命令进行传输。我需要真正禁用 NCQ,以便驱动程序向设备发出 DMA-IN/OUT 命令。

所以这里是我的问题:

  1. 如何禁用 NCQ?
  2. 如果 NCQ 队列深度 = 1,Linux 的 AHCI 驱动程序是使用 QUEUED-DMA-** 还是 DMA-** 命令?
  3. 我如何检查 NCQ 是否被禁用,因为在/sys/block/sdX/device/queue_depth中未报告更改dmesg

Pae*_*els 17

感谢@frostschutz,我可以在没有 NCQ 功能的情况下测量 Linux 中的写入性能。内核引导参数libata.force=noncq完全禁用了 NCQ。

关于我的希捷 6TB 写入性能问题,速度没有变化。Linux 仍然达到 180 MiB/s。

但后来我有了另一个想法:
Linux 驱动程序不使用 32 MiB 块的传输。内核缓冲区要小得多,特别是如果启用了 32 个队列的 NCQ(32 个队列 * 32 MiB => 1 GiB AHCI 缓冲区)。

所以我用 256 KiB 传输测试了我的 SATA 控制器,瞧,它有可能达到 185 MiB/s。

所以我猜希捷 ST6000AS0002 固件不能处理大 ATA 突发传输。ATA 标准允许多达 65.536 个逻辑块,相当于 32 MiB。

SMR - 瓦片式磁记录

写入性能不佳的另一种可能是叠瓦式磁记录技术,希捷在这些存档设备中使用了这种技术。显然,我用我的 FPGA 实现触发了一个罕见的效果。

  • 你做过突发操作或随机访问吗?NCQ 对突发操作没有影响,但改进了随机访问。 (2认同)

Sim*_*mon 8

将队列深度设置为 1 ( /sys/block/sd*/device/queue_depth) 会禁用 NCQ,不需要使用内核参数libata.force=noncq(只能在启动时设置)。


提交360f654e7cda850034f3f6252a7a7cff3fa77356

 Date:   Sat Sep 30 19:45:00 2006 +0900

 [PATCH] libata: turn off NCQ if queue depth is adjusted to 1
 
 Turn off NCQ if queue depth is adjusted to 1.
Run Code Online (Sandbox Code Playgroud)

  • 比将读者重定向到补丁更好,告诉我们如何执行此操作:``echo 1 > /sys/block/sdX/device/queue_depth`` (2认同)
  • 这应该是对另一个答案的评论,但我不被允许发表评论。该补丁不是“重定向”,而是引用。 (2认同)
  • 不允许冒充答案的评论。但这实际上是一个有用的答案,需要更多的赞成票,特别是现在您已经添加了_how_来在实时系统上禁用 NCQ。谢谢。 (2认同)