![关闭/打开设备电源后将绑定点安装到错误的 NVMe 设备](https://linux22.com/image/222825/%E5%85%B3%E9%97%AD%2F%E6%89%93%E5%BC%80%E8%AE%BE%E5%A4%87%E7%94%B5%E6%BA%90%E5%90%8E%E5%B0%86%E7%BB%91%E5%AE%9A%E7%82%B9%E5%AE%89%E8%A3%85%E5%88%B0%E9%94%99%E8%AF%AF%E7%9A%84%20NVMe%20%E8%AE%BE%E5%A4%87.png)
我正在开发一个全闪存存储应用程序。我发现挂载绑定在 NVMe 设备电源关闭/打开时有奇怪的行为。发行版:SUSE Linux Enterprise Server 15 SP4 5.14.21-150400.24.46-默认
将分区 /dev/nvme10n1p1 挂载到 /mnt/10n1p1
# mount --bind /dev/nvme10n1p1 /mnt/10n1p1
# lsblk /mnt/10n1p1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme10n1p1 259:11 0 3.6T 0 part
# stat /dev/nvme10n1p1
File: /dev/nvme10n1p1
Size: 0 Blocks: 0 IO Block: 4096 block special file
Device: 5h/5d Inode: 23620 Links: 1 Device type: 103,b
# stat /mnt/10n1
File: /mnt/10n1
Size: 0 Blocks: 0 IO Block: 4096 block special file
Device: 5h/5d Inode: 23620 Links: 1 Device type: 103,b
短时间内关闭/打开 NVME 设备以模拟热插拔或电涌。
# ls -lat /sys/block | grep "nvme10n1"
.../0000:be:00.0/nvme/nvme2/nvme10n1
# lspci -vmms 0000:be:00.0
...PhySlot: 168
# date && echo 0|sudo tee /sys/bus/pci/slots/${PHYSLOT}/power
# sleep 5
# date && echo 1|sudo tee /sys/bus/pci/slots/${PHYSLOT}/power
断电/通电后,挂载绑定点到刚刚通电的新驱动器。
# lsblk /mnt/10n1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme30n2 259:11 0 3.6T 0 disk
└─nvme30n2p1 259:51 0 3.6T 0 part
# stat /dev/nvme30n2
File: /dev/nvme30n2
Size: 0 Blocks: 0 IO Block: 4096 block special file
Device: 5h/5d Inode: 24836 Links: 1 Device type: 103,b
经过预先测试,我发现mount bind甚至可以在原驱动器断电后短时间内指向另一个上电的驱动器。
# mount --bind /dev/nvme0n1p1 /mnt/0n1
# lsblk 0n1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme0n1p1 259:44 0 3.6T 0 part
# nvme id-ctrl /dev/nvme0n1 | grep sn
sn: : PHLJ043200234P0DGN
# nvme id-ctrl /dev/nvme1n1 | grep sn
sn: : PHLJ043105AU4P0DGN
# PHYSLOT_0=195
# PHYSLOT_1=194
# date && echo 0|sudo tee /sys/bus/pci/slots/${PHYSLOT_1}/power
# sleep 5
# date && echo 0|sudo tee /sys/bus/pci/slots/${PHYSLOT_0}/power
# sleep 5
# date && echo 1|sudo tee /sys/bus/pci/slots/${PHYSLOT_1}/power
# sleep 5
# date && echo 1|sudo tee /sys/bus/pci/slots/${PHYSLOT_0}/power
# lsblk /mnt/0n1
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
nvme31n2p1 259:44 0 3.6T 0 part
# nvme id-ctrl /dev/nvme31n2 | grep sn
sn : PHLJ043105AU4P0DGN
# nvme id-ctrl /dev/nvme32n2 | grep sn
sn : PHLJ043200234P0DGN
我注意到,在断电/开机后,安装点的 inode 编号与新驱动器设备的 inode 编号不同,但是安装点的 inode 和新驱动设备 inode 共享相同的次要编号。我认为这就是原始安装点可以访问新驱动器设备从而导致数据损坏的原因。我的猜测是安装点保留了对断电驱动器索引的引用,这导致索引节点没有被破坏。然后新驱动器上电并获取与原始驱动器相同的回收次要编号。我不确定这种行为是否是预期的,或者它是否是安装绑定的限制或错误。
答案1
事实证明这是一个 Linux 内核bdev
生命周期错误,并在 5.15 版本中修复。
相关补丁链接这里。