/dev/disk/by-id/scsi-* 中的磁盘驱动器序列号反转

/dev/disk/by-id/scsi-* 中的磁盘驱动器序列号反转

我正在使用带有 USB 外部驱动器的 Ubuntu 20.04,遇到了一个相当奇怪的错误。我这里有一堆用于硬盘驱动器的 USB 外壳(或者更确切地说是作为外部驱动器出售的):

  • 三星便携式 SSD T5(mSATA 转 USB,内部带有 UASP)

    向内核报告的 S/N(按照dmesg& lsusb -v):12345688ACF4

    (这是 USB 上的伪磁盘序列,与标签和 SMART 数据不同。)

  • 三星便携式 SSD T7(NVMe 转 USB,内部带有 UASP)

    (通过 USB 报告正确的磁盘序列;与 SMART 数据和磁盘标签相同。)

  • StarTech USB 3.1 gen2 SATA 硬盘盒,带 UASP

    (通过 USB 报告正确的磁盘序列;与 SMART 数据和磁盘标签相同。)

  • 带 UASP 的 Ewent EW7017 USB 转 SATA 加密狗

    (报告 USB 上的虚假磁盘序列000000004BA8,它总是一样的。)

  • WD Elements USB 硬盘驱动器(无 UASP)

    (报告 USB 上的伪磁盘序列。)

所有这些基本上都是单磁盘到 USB 外壳。

他们通过 USB 向内核报告的序列号有时是错误的,但这似乎是他们的硬件问题。这不是我们能解决的问题,我的问题是关于其他事情的。

添加驱动器时,将为其创建一个方便的链接/dev/disk/by-id/

/dev/disk/by-id/
├── dm-name-dm_crypt-0 -> ../../dm-0
[...]
├── scsi-SSamsung_Portable_SSD_T5_4FCA88654321 -> ../../sdb
├── scsi-SSamsung_Portable_SSD_T5_4FCA88654321-part1 -> ../../sdb1
[...]

这真的很酷,因为它让我确信我在正确的驱动器上工作,而不是危险的假设sdb是正确的驱动器。

但如您所见,该字符串scsi-SSamsung_Portable_SSD_T5_4FCA88654321包含两个错误:

  1. 制造商名称前面带有S
  2. 序列号被反转;12345688ACF4变成了4FCA88654321

T7 驱动器也发生了同样的情况。

StarTech 外壳没有序列恢复功能:

├── scsi-STOSHIBA_MQ01ABB200_1234ABCD -> ../../sdb

Ewent 也一样:

├── scsi-SWDC_WD20_NPVX-00EA4T0_000000004BA8 -> ../../sdb

西部数据非 UASP 硬盘不存在以下两个问题:

└── usb-WD_Elements_1048_1234ABCD-0:0 -> ../../sdb

另外,有时它是一个i前缀,而不是一个S,这取决于制造商。

这是为什么?哪个软件导致了这些错误?

我也在使用更专业的热插拔存储机箱,这个机箱与这些驱动器配合得很好。因此,这似乎完全是通过 USB 或 UASP 来实现的。

更奇怪的是,当在 Debian Linux 10/Buster 上使用相同的硬件时,它运行良好(ata而不是scsi顺便说一下!是的,UASP 已启用scsi host4: uasdmesg

├── ata-TOSHIBA_MQ01ABB200_1234ABCD -> ../../sdb

那么,这到底是不是 Ubuntu 的一个错误?

答案1

部分答案:

有多种不同的方法可以获取驱动器序列号。(请阅读 ATA、ATAPI 和 USB 存储规范以了解详细信息)。

如果您想要找出符号链接使用了哪种特定方式,您需要深入研究udev,找出用于创建这些链接的命令(非常有可能blkid),找到您的版本blkid,然后阅读它的源代码。

也就是说,造成这种奇怪行为的可能原因是您的机箱中不同的 USB 转 SATA 桥接芯片。

为了验证该芯片是否是罪魁祸首,请将真正的硬盘从封盖中取出,通过 SATA 将其连接到主板,然后查看获得的序列号。

重复首字母(SSamsung)或反转序列之类的错误是这些芯片固件中的典型错误,没有人费心去纠正(或者可能没有人注意到)。


所以我快速查看了一下它在我的系统上做了什么(旧版 Devuan,没有 systemd 的 Debian):udev 规则位于

/lib/udev/rules.d/60-persistent-storage.rules

并且它们调用scsi_id(而不是blkid),这/lib/udev/scsi_id在二进制文件的正常位置中并不常见。

我无法让它从命令行产生输出,但是手册页

scsi_id 通过 SCSI INQUIRY 重要产品数据 (VPD) 页面 0x80 或 0x83 查询 SCSI 设备,并使用结果数据生成一个值,该值在所有正确支持页面 0x80 或页面 0x83 的 SCSI 设备中都是唯一的。

并且它继续

基于页面 0x80 的标识符以字符“S”、SCSI 供应商、SCSI 产品(型号)和页面 0x80 返回的序列号为前缀。

所以这就解释了你的S,它实际上并不是第一个字母的重复。

据我所知,重要产品页面并不是在 Linux 的大多数其他部分获取制造商和序列信息的方式,因此如果您的序列逆转是硬盘或 USB-SATA 桥中的实际固件错误,我不会感到惊讶。

您可以通过安装来检查sg3_utils直接发行将 INQUIRY 命令(带有--page)发送到您的设备(尝试在外壳内外进行)。

我没有安装各种发行版,所以我不知道 udev 在 Ubuntu Focal 或带有 systemd 的 Debian 上有何不同。

答案2

反向序列号来自 USB 设备/外壳的 SCSI 级 SCSI-ATA 转换层:

# lsusb.py -i | grep 3-4
  3-4               174c:55aa 00 1IF  [USB 3.10,  5000 Mbps,   0mA] (ASMT ASM105x B087078B14DA00062434)
    3-4:1.0           (IF) 08:06:62 4EPs (Mass Storage) uas host7 (sdc)
# hdparm -I /dev/sdc | grep -i 'serial number'
        Serial Number:      B087078B14DA00062434
# sg_vpd -p 0x80 /dev/sdc
Unit serial number VPD page:
  Unit serial number: 43426000AD41B870780B
# sg_vpd -r -p 0x80 /dev/sdc | hexdump -C
00000000  00 80 00 14 34 33 34 32  36 30 30 30 41 44 34 31  |....43426000AD41|
00000010  42 38 37 30 37 38 30 42                           |B870780B|
00000018
# /usr/lib/udev/ata_id -x /dev/sdc | grep -i serial
ID_SERIAL=SPCC_Solid_State_Disk_B087078B14DA00062434
ID_SERIAL_SHORT=B087078B14DA00062434
# /usr/lib/udev/scsi_id -p 0x83 -g -x /dev/sdc | grep -i serial
ID_SERIAL=35000000000000001
ID_SERIAL_SHORT=5000000000000001
ID_SCSI_SERIAL=43426000AD41B870780B
# /usr/lib/udev/scsi_id -g -p 0x80 -x /dev/sdc | grep -i serial
ID_SERIAL=SSPCC_Solid_State_Disk_43426000AD41B870780B
ID_SERIAL_SHORT=43426000AD41B870780B

机箱供应商让机箱固件执行此类逆转的原因可能是,在早期版本的 SCSI 主命令标准中(例如SPC-2 修订版 20PRODUCT SERIAL NUMBER字段需要保存以下值:The least significant ASCII character of the serial number shall appear as the last byte in the Data-In Buffer.

我不确定这句话的正确解释/真实意图是什么,但至少供应商可能或多或少是这么解释的:

  1. B087078B14DA00062434被视为十六进制数,即0x3433343236303030414434314238373037383042
  2. 由于 ASCII 字符占用一个字节,the least significant ASCII character of the serial number因此为0x42/ 4
  3. 然后,他们假设该语句意味着当为请求 VPD 页面的命令读入值时Data-In Buffer,应该从那里一直读取直到“最重要的 ASCII 字符”(即0x34/ B)。

然而,截至SPC 的当前最新版本/草案(例如 SPC-6 修订版 5),要求已更改。现在The PRODUCT SERIAL NUMBER field contains right-aligned ASCII data,以及此类字段shall have any unused bytes at the start of the field (i.e., lowest offset) and the unused bytes shall be filled with ASCII space characters (i.e., code value 20h)。它似乎没有针对“已用字节”的任何方向(在指令意义上)。

因此,对于任何人来说,当用户空间程序(例如sg_vpd在 sg3_utils 和scsi_idsystemd/udev 中)从 VPD 页面输出值时,是否应该“将其反转”都是很困难的。

您看到序列号的顺序正确的原因与您在上面相应的输出中看到序列号的原因相同:源不是 SCSI 单元序列号 VPD 页面。systemd/udev 有其他程序/内置程序来从块设备收集识别信息:

ata_id仅当机箱支持ATA PASSTHROUGHSCSI 命令时才有效(当然,如果后面的驱动器是 ATA 驱动器)。请参阅SAT 标准了解更多信息。

我不知道为什么您的 system(d) / udev 最终会使用scsi_id该设备。根据60-persistent-storage.rulessystemd 的最新版本,我没有看到它被优先于ata_idusb_id内置。检查您拥有的那个,{{/usr,}/lib,/etc}/udev/rules.d/看看它是否不同。我对 Ubuntu 不熟悉,无论如何也不知道为什么。


顺便说一句,当您的外壳不支持 VPD 页面 0x83 时S,会在前面加上scsi_id(我不确定它是否仍然有意义;代码可以追溯到程序被引入 udev 的时候,甚至在合并到 systemd 之前):

不确定i0

另请参阅以下有关启发式方法的更多详细信息:

相关内容