0

I'm testing a Python script intended for use on Raspberry Pi systems for reformatting and copying partition info and partition data. To get the information from the first device (often a USB memory stick), I use:

sfdisk -d /dev/sda >sda_data.txt

Then, to copy the same table to the destination drive, I use:

sfdisk /dev/sdb <sda_data.txt

Overall, it works as expected, but what if I use it on a smaller disk? For instance, say sda1 is a msdos format boot partition and sda2 is an extfs partition filling the rest of the drive. Say the total data (other than boot commands and data) is about 10GB on /dev/sda2 and /dev/sda is 64GB.

My data is small enough that when I copy the files from the 64GB device to a smaller 32GB device, there will be enough room on the smaller device at /dev/sdb for it to store all the data on a smaller device. So if sda is 64GB and sdb is 32GB, I can still copy all the data I have on sda to sdb.

The problem or question lies with the partition of the smaller sdb.

When I read in the partition information from sda, it includes partition sizes and the 2nd partition, sda2, will be a lot bigger than it's new counterpart, sdb2. When I use the info dump in sda_data.txt on sdb, my experience is that sfdisk allows for the smaller device size on sdb and doesn't try to make too large a partition - it creates a partition on sdb2 that automatically goes to the end of the smaller device.

This is my experience. Is this standard behavior? Will sfdisk always resize that last partition to the smaller device? In other words, can I rely on sfdisk creating that smaller partition on the smaller device? (This is assuming no partition is starting after the end of sdb and would be entirely outside of the space on that device. For the purposes of this discussion, we can assume that the last partition may need to be reduced, but that it will still be able to fit on sdb - it just won't be full size.)

Tango
  • 353
  • I don't know the answer, but it seems like something you could do some easy experiments to find out, using disk-image files instead of physical devices. Create two files with truncate or dd, one 2GB in size, one 1GB. Partition the 2GB file similarly to how you partitioned your 64GB device (i.e. one small partition and one larger partition taking up the rest of the space). Then use sfdisk to clone the partition table to the 1GB file. Examine the cloned partition table, to see if sfdisk automatically corrected the partition size or not. If not, it won't be safe to use until you edit it. – cas Jul 19 '23 at 10:51
  • @cas I've found things vary on some nix commands depending on environment or even from distro to distro. Every now and then I've found something undocumented in a nix command and started using it only to find the behavior changed on another distro. Right now I'm testing with a USB memory stick as the source device (on a Raspberry Pi) and copying the table to a larger USB stick and a smaller one as well as to a smaller microSD. It seems to be resizing for the smaller devices - but I want to be sure this is expected and not something that may show up in some versions and not others. – Tango Jul 19 '23 at 16:08

1 Answers1

1

The dump option is more suitable to exactly replicate a given partitioning.

I can't tell you how reliable it is to use sfdisk with a recipe where the partitioning does not match the device size.

But you can easily create a more lenient sfdisk script either from scratch or based on a dump.

For example if I got the following dump from sfdisk

label: gpt
label-id: 01234567-89AB-CDEF-0123-456789ABCDEF
device: /dev/sda
unit: sectors
first-lba: 34
last-lba: 7814037134
sector-size: 512

/dev/sda1 : start= 34, size= 32734, type=E3C9E316-0B5C-4DB8-817D-F92DF00215AE, uuid=01234567-89AB-CDEF-0123-456789ABCDEF, name="Microsoft reserved partition" /dev/sda2 : start= 32768, size= 629145600, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=01234567-89AB-CDEF-0123-456789ABCDEF, name="something" /dev/sda3 : start= 629178368, size= 1300070400, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=01234567-89AB-CDEF-0123-456789ABCDEF, name="something else" /dev/sda4 : start= 1996365824, size= 5817669632, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=01234567-89AB-CDEF-0123-456789ABCDEF, name="root"

You can create a more flexible partitioning by removing especially the device path, start sector and one of the size arguments.

label: gpt

size= 32734, type=E3C9E316-0B5C-4DB8-817D-F92DF00215AE, name="Microsoft reserved partition" size= 629145600, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, name="something" size= 1300070400, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, name="something else" type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, name="root"

This will create four partitions where sfdisk will automatically calculate the preferred start positions, expand the last partition to fill the remaining space (because it has no required size) and create new UUIDs for the partitions. If you want the partitions to have the same UUIDs as before just keep the uuid argument from the dump.

Relevant parts from the manpage:

The recommended way is not to specify start offsets at all and specify partition size in MiB, GiB (or so). In this case sfdisk aligns all partitions to block-device I/O limits (or when I/O limits are too small then to megabyte boundary to keep disk layout portable).

The default value of size indicates "as much as possible"; i.e., until the next partition or end-of-device.

In general it is feasible to hand write sfdisk scripts. For your boot + root setup (note: what filesystem a partition will get doesn't really matter for sfdisk) you should be fine with something simple like:

label: gpt

size=5GiB, type=linux, name="boot", bootable type=linux, name="root"