8

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.

3

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.

2

On Linux, loop devices are partitionable if the max_part parameter of the loop kernel module is set. If the loop is built-in (not a module), you can pass a loop.max_part=31 kernel command line parameter instead.

So after you've configured the loop driver to get partitionable block devices, it should just be a matter of doing:

losetup --show -f /dev/sda

To get some /dev/loopXp1, /dev/loopXp2... devices for each partition.

A few notes as things have evolved on that front in the kernel since you posted your question:

  • since 4.14, it's also possible to specify a logical block size other than 512 for loop devices (losetup -b 4096 for instance). It's also possible to change the block size of a loop device after it has been created.

  • since 4.11, the logical block size of nbd devices is set to the block size passed to nbd-client (-b option). Since the default block size is (and was) 1024, that means nbd devices now get a default logical sector size of 1024 instead of 512 before (pretty bad from a backward compatibility point of view).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.