通过支持 UASP 的 USB 适配器连接 SATA SSD 时没有 TRIM/DISCARD?

use*_*709 7 linux sata trim uasp

我刚买了一个 SATA SSD 和一个 USB-SATA 适配器。我选择了支持 UASP 的适配器,因为我认为它可以运行 TRIM/DISCARD 命令,而且我认为这对于 SSD 的使用寿命很重要。

\n

当我将适配器连接到基于 Debian 的计算机时,Linux 内核会按预期检测到它并启用与 UAS 协议的通信。这是内核报告的内容:

\n
[23886.083296] usb 2-1: new SuperSpeed Gen 1 USB device number 6 using xhci_hcd\n[23886.104497] usb 2-1: New USB device found, idVendor=174c, idProduct=55aa, bcdDevice= 1.00\n[23886.104508] usb 2-1: New USB device strings: Mfr=2, Product=3, SerialNumber=1\n[23886.104513] usb 2-1: Product: 00SSD1\n[23886.104518] usb 2-1: Manufacturer: CT500MX5\n[23886.104522] usb 2-1: SerialNumber: 12345678D9DA\n[23886.110042] scsi host1: uas\n[23886.110883] scsi 1:0:0:0: Direct-Access     CT500MX5 00SSD1           0    PQ: 0 ANSI: 6\n[23886.111967] scsi 1:0:0:0: Attached scsi generic sg1 type 0\n[23886.112698] sd 1:0:0:0: [sdb] 976773168 512-byte logical blocks: (500 GB/466 GiB)\n[23886.112702] sd 1:0:0:0: [sdb] 4096-byte physical blocks\n[23886.112841] sd 1:0:0:0: [sdb] Write Protect is off\n[23886.112846] sd 1:0:0:0: [sdb] Mode Sense: 43 00 00 00\n[23886.113013] sd 1:0:0:0: [sdb] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA\n[23886.113224] sd 1:0:0:0: [sdb] Optimal transfer size 33553920 bytes not a multiple of physical block size (4096 bytes)\n
Run Code Online (Sandbox Code Playgroud)\n

lsusb确认uas驱动程序已使用:

\n
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/7p, 5000M\n    |__ Port 1: Dev 6, If 0, Class=Mass Storage, Driver=uas, 5000M\n
Run Code Online (Sandbox Code Playgroud)\n

但我可以\xe2\x80\x99tblkdiscard在此设备上运行:

\n
# blkdiscard -f /dev/sdb\nblkdiscard: /dev/sdb contains existing partition (dos).\nblkdiscard: Operation forced, data will be lost!\nblkdiscard: /dev/sdb: BLKDISCARD ioctl failed: Operation not supported\n
Run Code Online (Sandbox Code Playgroud)\n

lsblk确认块设备不支持丢弃:

\n
# lsblk -D /dev/sdb\nNAME   DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO\nsdb           0        0B       0B         0\n`-sdb1        0        0B       0B         0\n
Run Code Online (Sandbox Code Playgroud)\n

问题从何而来?我有希望通过此设置运行 TRIM/DISCARD 吗?

\n

use*_*709 11

经过一番阅读(感谢 harrymc 评论中的链接),我想我现在可以更好地理解 \xe2\x80\x99s 正在发生的事情。

\n

首先,认为使用支持 UASP 的 USB-SATA 桥接器和最新的 SATA SSD(支持 TRIMming)显然会支持取消映射的想法是天真的。

\n

事实上,支持 UASP 的 USB-SATA 桥接器有两个主要功能:

\n
    \n
  • 第一个是UAS接口,它是一个USB接口,封装SCSI命令,
  • \n
  • 第二个是将 SCSI 命令转换为 ATA 命令的转换器。
  • \n
\n

SCSI 协议定义的命令集相当大,并非所有 SCSI 设备都支持所有命令。因此,有几个命令可用于取消映射。SCSI-ATA 转换器可能支持其中之一,也许支持其中几个,但也可能不支持。在后一种情况下,无法取消 SSD 的块映射。幸运的是,我的 USB-SATA 桥接器中的 SCSI-ATA 转换器确实支持 UNMAP 命令。

\n

由于 SCSI 命令集的丰富性,驱动程序必须知道设备支持哪些功能。这是通过设备向驱动程序提供的一些信息页面(称为 VPD(重要产品数据)页面)来完成的。\xe2\x80\x9cfirst\xe2\x80\x9d 页面是 \xe2\x80\x9cSupported VPD Pages\xe2\x80\x9d 页面,列出了设备支持的页面。

\n

通常,驱动程序会查询 \xe2\x80\x9cfirst\xe2\x80\x9d 页面,然后查询感兴趣的页面(如果支持)。至于取消映射的能力,有趣的页面是 \xe2\x80\x9cLogical block Provisioning\xe2\x80\x9d 页面。

\n

使用 Linux,可以查询 \xe2\x80\x9cSupported VPD 页面\xe2\x80\x9d 和 \xe2\x80\x9cLogical block Provisioning\xe2\x80\x9d 页面,如下所示:

\n
# sg_vpd -p sv /dev/sdb\nSupported VPD pages VPD page:\n  Supported VPD pages [sv]\n  Unit serial number [sn]\n  Device identification [di]\n  Block limits (SBC) [bl]\n  Block device characteristics (SBC) [bdc]\n  Logical block provisioning (SBC) [lbpv]\n# sg_vpd -p lbpv /dev/sdb\nLogical block provisioning VPD page (SBC):\n  Unmap command supported (LBPU): 1\n  Write same (16) with unmap bit supported (LBPWS): 0\n  Write same (10) with unmap bit supported (LBPWS10): 0\n  Logical block provisioning read zeros (LBPRZ): 0\n  Anchored LBAs supported (ANC_SUP): 0\n  Threshold exponent: 0 [threshold sets not supported]\n  Descriptor present (DP): 0\n  Minimum percentage: 0 [not reported]\n  Provisioning type: 0 (not known or fully provisioned)\n  Threshold percentage: 0 [percentages not supported]\n
Run Code Online (Sandbox Code Playgroud)\n

在这里,我们可以看到\xe2\x80\x9cmy\xe2\x80\x9d SCSI-ATA 转换器支持unmap 命令,但不支持带有unmap 位的Write same (16) 或Write same (10) 命令。

\n

通常,驱动程序会读取这些页面并相应地配置设备。不幸的是,显然历史上曾出现过损坏的 USB 设备在查询某些 VPD 页面时锁定或变砖的情况。因此,Linux 内核的开发人员默认决定不查询 USB 连接的 SCSI 设备的 VPD 页面,也不设置 UNMAP 等高级功能。

\n

/sys/block/sdb/device/scsi_disk/1:0:0:0/provisioning_mode好消息是,仍然可以使用特殊文件(路径可能会有所不同)从用户空间设置这些功能。当我插入适配器时,它读取 \xe2\x80\x9cfull\xe2\x80\x9d,但我可以将其设置为 \xe2\x80\x9cunmap\xe2\x80\x9d,因为我的设备支持 unmap 命令。其他支持的值是 \xe2\x80\x9cwritesame_16\xe2\x80\x9d、\xe2\x80\x9cwritesame_10\xe2\x80\x9d、\xe2\x80\x9cwritesame_zero\xe2\x80\x9d 和 \xe2\x80\x9cdisabled \xe2\x80\x9d。

\n

可以更进一步,设置 udev 规则来自动配置该设备:

\n
ACTION=="add|change", ATTRS{idVendor}=="174c", ATTRS{idProduct}=="55aa", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"\n
Run Code Online (Sandbox Code Playgroud)\n

(idVendor、idProduct和provisioning_mode取决于USB-SATA桥)

\n

无论如何,我不建议这样做,因为错误可能会破坏您的设备,甚至尝试强行读取 VPD 页面sg_vpd

\n

我也不知道设置该discard_max_bytes设置有多么有用,正如一篇很棒的在 Raspberry Pi 上的外部 SSD 上启用 TRIM文章所建议的那样。

\n

又是一些好消息,有一个补丁可以在某些情况下绕过 USB 连接的 SCSI 设备的限制,在某些情况下这样做看起来是安全的,而且我想它应该可以为大多数最新的支持 UASP 的 USB-SATA 桥做到这一点。我还没有尝试过;它显然还没有\xe2\x80\x99t进入linux 6.0-rc4;我不知道\xe2\x80\x99是否有计划在不久的将来请求其合并。

\n