识别使用不同逻辑扇区大小创建的 GPT 分区表

识别使用不同逻辑扇区大小创建的 GPT 分区表

我有一个 3TB 驱动器,我使用 GPT 对其进行了分区:

$ sudo sgdisk -p /dev/sdg
Disk /dev/sdg: 5860533168 sectors, 2.7 TiB
Logical sector size: 512 bytes
Disk identifier (GUID): 2BC92531-AFE3-407F-AC81-ACB0CDF41295
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 5860533134
Partitions will be aligned on 2048-sector boundaries
Total free space is 2932 sectors (1.4 MiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048           10239   4.0 MiB     8300
   2           10240      5860532216   2.7 TiB     8300

然而,当我通过 USB 适配器连接它时,它报告逻辑扇区大小为 4096,并且内核不再识别分区表(因为它正在扇区 1 处查找 GPT,该扇区现在位于偏移量 4096 而不是 512):

$ sudo sgdisk -p /dev/sdg
Creating new GPT entries.
Disk /dev/sdg: 732566646 sectors, 2.7 TiB
Logical sector size: 4096 bytes
Disk identifier (GUID): 2DE535B3-96B0-4BE0-879C-F0E353341DF7
Partition table holds up to 128 entries
First usable sector is 6, last usable sector is 732566640
Partitions will be aligned on 256-sector boundaries
Total free space is 732566635 sectors (2.7 TiB)

Number  Start (sector)    End (sector)  Size       Code  Name

有没有办法强制Linux识别偏移量512处的GPT?或者,有没有办法创建两个 GPT 标头,一个在 512,一个在 4096,或者它们会重叠吗?

编辑:我找到了一些解决方法,但都不是很好:

  1. 我可以使用环回设备对磁盘进行分区:

    $ losetup /dev/loop0 /dev/sdg
    

    环回设备的扇区大小始终为 512,因此这允许我按照自己的需要对设备进行分区。但是,内核无法识别环回设备上的分区表,因此我必须创建另一个环回设备并手动指定分区大小和偏移量:

    $ losetup /dev/loop1 /dev/sdg -o $((10240*512)) --sizelimit $(((5860532216-10240)*512))
    

    我可以编写一个脚本来自动执行此操作,但如果能够自动执行此操作就更好了。

  2. 我可以运行 nbd-server 和 nbd-client; NBD 设备默认有 512 字节扇区,并且 NBD 设备是可分区的。但是,NBD 文档警告不要在同一系统上运行 nbd 服务器和客户端;测试时,内核中的 nbd 客户端挂起,我不得不终止服务器。

  3. 我可以使用相同的设置运行 istgt(用户空间 iSCSI 目标)。这为系统提供了另一个具有 512 字节扇区的 SCSI 设备。然而,在测试时,这失败了,并导致 ext4 代码中出现内核 NULL 指针取消引用。

  4. 我还没有研究过 devmapper,但它可能有用。

答案1

我找到了一个解决方案:一个名为 kpartx 的程序,它是一个用户空间程序,使用 devmapper 从环回设备创建分区,效果很好:

$ loop_device=`losetup --show -f /dev/sdg`
$ kpartx -a $loop_device
$ ls /dev/mapper
total 0
crw------- 1 root root  10, 236 Mar  2 17:59 control
brw-rw---- 1 root disk 252,   0 Mar  2 18:30 loop0p1
brw-rw---- 1 root disk 252,   1 Mar  2 18:30 loop0p2
$
$ # delete device
$ kpartx -d $loop_device
$ losetup -d $loop_device

这基本上完成了我在选项 1 中计划做的事情,但更加干净。

答案2

在 Linux 上,如果设置了内核模块max_part的参数,则循环设备是可分区的。loop如果loop是内置的(不是模块),您可以传递loop.max_part=31内核命令行参数。

因此,在配置loop驱动程序以获取可分区块设备之后,只需执行以下操作即可:

losetup --show -f /dev/sda

要为每个分区获取一些/dev/loopXp1...设备。/dev/loopXp2

自从您发布问题以来,随着内核中这方面的发展,有一些注释:

  • 从 4.14 开始,还可以为循环设备指定除 512 之外的逻辑块大小(losetup -b 4096例如)。创建循环设备后还可以更改其块大小。

  • 从 4.11 开始,nbd 设备的逻辑块大小设置为传递给 nbd-client(-b选项)的块大小。由于默认块大小是(并​​且曾经是)1024,这意味着 nbd 设备现在的默认逻辑扇区大小为 1024,而不是之前的 512(从向后兼容性的角度来看非常糟糕)。

相关内容