我有一个 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,或者它们会重叠吗?
编辑:我找到了一些解决方法,但都不是很好:
我可以使用环回设备对磁盘进行分区:
$ losetup /dev/loop0 /dev/sdg
环回设备的扇区大小始终为 512,因此这允许我按照自己的需要对设备进行分区。但是,内核无法识别环回设备上的分区表,因此我必须创建另一个环回设备并手动指定分区大小和偏移量:
$ losetup /dev/loop1 /dev/sdg -o $((10240*512)) --sizelimit $(((5860532216-10240)*512))
我可以编写一个脚本来自动执行此操作,但如果能够自动执行此操作就更好了。
我可以运行 nbd-server 和 nbd-client; NBD 设备默认有 512 字节扇区,并且 NBD 设备是可分区的。但是,NBD 文档警告不要在同一系统上运行 nbd 服务器和客户端;测试时,内核中的 nbd 客户端挂起,我不得不终止服务器。
我可以使用相同的设置运行 istgt(用户空间 iSCSI 目标)。这为系统提供了另一个具有 512 字节扇区的 SCSI 设备。然而,在测试时,这失败了,并导致 ext4 代码中出现内核 NULL 指针取消引用。
我还没有研究过 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(从向后兼容性的角度来看非常糟糕)。