USB 连接 SATA - 启动时不读取分区表

USB 连接 SATA - 启动时不读取分区表

如果系统在插入 USB 连接的 SATA 磁盘的情况下启动,Linux 显然无法识别该磁盘中的分区。这会导致分区(以及文件系统)不可见,需要重新扫描分区(partprobe、blockdev --rereadpt、等),UAS 模块重新加载,或者拔下驱动器并重新插入。如果有问题的磁盘打算作为引导设备,其中包含 ESP 和根文件系统,那么这些都是不可行的。

做了一些实验。结果:

  1. 在主机在线并加载 UAS 模块的情况下插入磁盘 ->作品
  2. 在主机在线且 UAS 和 usb_storage 模块未加载的情况下插入磁盘 ->作品
  3. 插入磁盘后,从另一个驱动器启动系统 ->失败 未检测到分区。给它足够的时间稳定后,观察到以下情况: UAS 和 usb_storage 模块均已加载; /dev/sda 和 /sys/class/block/sda 存在;有趣的是 lsblk 确实不是列出它,/proc/partitions 也没有。
    1. 从这个状态,卸载并重新加载 UAS 模块 ->作品(lsblk 列出它,/dev/sda{1,2} 已创建,一切“正常”)
    2. 同样从这个状态开始,通过 blockdev --rereadpt -> 重新扫描分区作品
    3. 通过内核命令行预加载和不预加载 UAS 模块的情况下重复测试会产生相同的结果。
  4. 插入磁盘后,尝试从同一磁盘启动系统 ->失败(系统无法启动。已降至救援外壳。)
    1. 一旦落入 shell,尝试blockdev --rereadpt->作品
    2. 通过内核命令行预加载和不预加载 UAS 模块的情况下重复测试会产生相同的结果。

dmesg | grep sd测试用例 #3 执行的输出(在 42 秒处执行了 blockdev --rereadpt)。案例 #4 的输出是相同的。

[   13.831953] sd 6:0:0:0: [sda] Read Capacity(10) failed: Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
[   13.831955] sd 6:0:0:0: [sda] Sense Key : Not Ready [current] 
[   13.831956] sd 6:0:0:0: [sda] Add. Sense: Logical unit is in process of becoming ready
[   13.832435] sd 6:0:0:0: [sda] Test WP failed, assume Write Enabled
[   13.832850] sd 6:0:0:0: [sda] Asking for cache data failed
[   13.832853] sd 6:0:0:0: [sda] Assuming drive cache: write through
[   15.038494] sd 6:0:0:0: [sda] Read Capacity(10) failed: Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
[   15.038497] sd 6:0:0:0: [sda] Sense Key : Not Ready [current] 
[   15.038498] sd 6:0:0:0: [sda] Add. Sense: Logical unit is in process of becoming ready
[   15.039379] sd 6:0:0:0: [sda] Attached SCSI disk
[   42.833001] sd 6:0:0:0: [sda] 1953525168 512-byte logical blocks: (1.00 TB/932 GiB)
[   42.834148] sda: detected capacity change from 0 to 1000204886016
[   42.956764]  sda: sda1 sda2

有什么提示吗?我假设设备需要一些时间才能启动并准备好(从消息中Logical unit is in process of becoming ready),并且可能在设备未准备好、发生故障或获取无效数据时发生分区扫描。我不知道此扫描何时发生,也不知道是哪个子系统引起的。和udev有什么关系吗?还有其他可能的罪魁祸首吗?一开始我以为,也许是按需模块加载导致需要的时候不可用。所以我试图强制加载它 - 显然可以通过在内核命令行上列出模块的名称来完成 - 但无济于事。

rootwaitrootdelay已经过测试。两者都未能解决问题。

我发现很有趣的是,普通的 USB 记忆棒作品达到启动它的预期目的(ESP 和根文件系统)。此外,BIOS 检测到 USB 连接的 SATA 磁盘,找到并启动 UEFI 可执行文件 (GRUB),GRUB 从中读取并引导内核等。

--

问题背景:

我有一根 USB 转 SATA 电缆,用于将 2.5 英寸 HDD 连接到机器。该机器是一个小型家庭服务器,有 4 个内部 SATA 端口,全部用于 RAIDZ 成员磁盘。我打算启动外部驱动器,并在其中安装根文件系统。到目前为止,我已经在 8GB USB 记忆棒中安装了 ESP 和根文件系统,而且它工作得很好......直到它不起作用。我发现 USB 记忆棒可以非常如果承受典型根文件系统承受的工作负载,即使日志日志被重定向到 RAM,并且除了基本进程之外的所有内容都在 LXC 容器中运行,而 LXC 容器的根文件系统位于 ZFS 池中,那么很快就会拉屎。

答案1

经过更多的挖掘后,我找到了解决这个问题的黑客式解决方案。 它远非完美,也没有解决根本原因,但至少可以使系统可启动。

黑客是有一个脚本初始化文件系统它在尝试挂载 root 之前、设备初始化之后以及sleep执行之前的某个时刻执行blockdev --rereadpt

在基于 debian 的系统中,只需将以下文件放入/etc/initramfs-tools/scripts/local-top/rereadpt

#!/bin/sh
PREREQ=""

prereqs()
{
    echo "$PREREQ"
}

case $1 in
# get pre-requisites
prereqs)
    prereqs 
    exit 0
    ;;
esac

sleep 5
blockdev --rereadpt /dev/<yourdisknode>

/dev/sda如果您的站点环境有单个 SCSI 磁盘,或者或任何其他逻辑,您可以使用类似名称/dev/disk/by-id/...,以确保您在正确的驱动器上触发重新扫描。

更新:如果您不想在update-initramfs每次重建图像时执行上述脚本(即使它应该不应该??),您不得省略开头的prereqs和片段case

相关内容