Recognizing GPT partition table created with different logical sector size

diskgptkernelpartition

I have a 3TB drive which I have partitioned using 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

However, when I connect it via a USB adapter, it reports a logical sector size of 4096 and the kernel no longer recognizes the partition table (since it's looking for the GPT at sector 1, which is now at offset 4096 instead of 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

Is there any way to force Linux to recognize the GPT at offset 512? Alternatively, is there a way to create two GPT headers, one at 512 and one at 4096, or will they overlap?

EDIT: I have found a few workarounds, none of which are very good:

  1. I can use a loopback device to partition the disk:

    $ losetup /dev/loop0 /dev/sdg
    

    Loopback devices always have a sector size of 512, so this allows me to partition the device how I want. However, the kernel does not recognize partition tables on loopback devices, so I have to create another loopback device and manually specify the partition size and offset:

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

    I can write a script to automate this, but it would be nice to be able to do it automatically.

  2. I can run nbd-server and nbd-client; NBD devices have 512-byte sectors by default, and NBD devices are partitionable. However, the NBD documentation warns against running the nbd server and client on the same system; When testing, the in-kernel nbd client hung and I had to kill the server.

  3. I can run istgt (user-space iSCSI target), using the same setup. This presents another SCSI device to the system with 512-byte sectors. However, when testing, this failed and caused a kernel NULL pointer dereference in the ext4 code.

  4. I haven't investigated devmapper yet, but it might work.

Best Answer

I found a solution: A program called kpartx, which is a userspace program that uses devmapper to create partitions from loopback devices, which works great:

$ 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

This essentially does what I was planning to do in option 1, but much more cleanly.