VM disk imaging across machines with different sector sizes
When transferring VM images between machines with different sector sizes (for example, one machine uses 512-byte sectors and another uses 4096-byte sectors), you may need to edit the partition table of the target device using a tool like parted
. This ensures that the start and end positions align with the actual physical positions on the disk. Additionally, you may need to create a BIOS boot partition if it has gone missing.
In some cases, the machine may not boot at all. If this happens, you'll need to mount the partition using the kpartx -a
command and reinstall grub using the grub-install --skip-fs-probe --boot-directory=/mnt/boot /dev/vg0/ubuntu-jammy
command. You might also need to edit the /etc/fstab
file to change the UUID of the root partition. There's much more to be said on this topic, but this provides a basic overview.
Correct partition table on 512-byte sector disk
fdisk -l /dev/vg0/ubuntu-jammy
shows
Disk /dev/vg0/ubuntu-jammy: 20 GiB, 21474836480 bytes, 41943040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 91928C6A-4801-4D6B-AED5-80D89AEB7BC2
Device Start End Sectors Size Type
/dev/vg0/ubuntu-jammy1 2048 4095 2048 1M BIOS boot
/dev/vg0/ubuntu-jammy2 4096 41940991 41936896 20G Linux filesystem
sfdisk -d /dev/vg0/ubuntu-jammy
shows
label: gpt
label-id: 91928C6A-4801-4D6B-AED5-80D89AEB7BC2
device: /dev/vg0/ubuntu-jammy
unit: sectors
first-lba: 34
last-lba: 41943006
sector-size: 512
/dev/vg0/ubuntu-jammy1 : start= 2048, size= 2048, type=21686148-6449-6E6F-744E-656564454649, uuid=34CE0326-8129-490A-8370-78FCAE67E912
/dev/vg0/ubuntu-jammy2 : start= 4096, size= 41936896, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=372F3800-D9B1-4C0A-9EC2-739E8367A3AA
Wrong partition table on 4K sector disk
After transferring the VM image, e.g using dd
you'll end up with a partition table which is incorrect. This is because the partition table still thinks it is on a 512-byte sector disk.
fdisk -l /dev/vg1/ubuntu-jammy
shows
GPT PMBR size mismatch (41943039 != 5242879) will be corrected by write.
Disk /dev/vg1/ubuntu-jammy: 20 GiB, 21474836480 bytes, 5242880 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x00000000
Device Boot Start End Sectors Size Id Type
/dev/vg1/ubuntu-jammy1 1 5242879 5242879 20G ee GPT
sfdisk -d /dev/vg1/ubuntu-jammy
shows
GPT PMBR size mismatch (41943039 != 5242879) will be corrected by write.
label: dos
label-id: 0x00000000
device: /dev/vg1/ubuntu-jammy
unit: sectors
sector-size: 4096
/dev/vg1/ubuntu-jammy1 : start= 1, size= 5242879, type=ee
Fixing the incorrect table
On the correct table, take note of start and end sectors, and divide by 8. This is the 4K sector positions we need to use. If you're going from 4K to 512 byte, then you'll need to multiply by 8 instead. We'll assume the sector positions are multiples of 8. If it is not, there may be other ways you can deal with this, but it's not described here.
- sectors 256 up to 511 for BIOS grub
- sectors 512 to end of disk for main partition
Use parted to make a new partition table aligned to those values. Here are some commands which could be used, but you need to use your own values for your desk. Change units and print the partition table as you progress.
(parted) mklabel gpt
(parted) mkpart primary 256s 511s
(parted) mkpart primary 512s -1s
(parted) set 1 boot off
(parted) set 1 bios_grub on
(parted) unit s
(parted) print
Model: Linux device-mapper (linear) (dm)
Disk /dev/dm-8: 5242880s
Sector size (logical/physical): 4096B/4096B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 256s 511s 256s primary bios_grub
2 512s 5242874s 5242363s ext4 primary
Trying booting machine, if it doesn't boot, you'll need to re-install grub.
Read the partition table and create device maps with kpartx
kpartx /dev/vg1/ubuntu-jammy
It should return something like
vg1-ubuntu--jammy1 : 0 2048 /dev/vg1/ubuntu-jammy 2048
vg1-ubuntu--jammy2 : 0 41938904 /dev/vg1/ubuntu-jammy 4096
Mount the mapped device to /mnt
mount /dev/mapper/vg1-ubuntu--jammy2 /mnt
Run ls -l /mnt/boot
and check we can see the contents of /boot
on our partition.
total 249428
-rw-r--r-- 1 root root 262053 Aug 14 19:05 config-5.15.0-83-generic
-rw-r--r-- 1 root root 261844 Oct 31 07:15 config-5.15.0-89-generic
drwxr-xr-x 5 root root 4096 Dec 8 06:22 grub
lrwxrwxrwx 1 root root 28 Dec 8 05:45 initrd.img -> initrd.img-5.15.0-89-generic
-rw-r--r-- 1 root root 109539581 Dec 8 05:45 initrd.img-5.15.0-83-generic
-rw-r--r-- 1 root root 109550579 Dec 8 06:22 initrd.img-5.15.0-89-generic
lrwxrwxrwx 1 root root 28 Sep 13 02:03 initrd.img.old -> initrd.img-5.15.0-83-generic
-rw------- 1 root root 6273612 Aug 14 19:05 System.map-5.15.0-83-generic
-rw------- 1 root root 6276836 Oct 31 07:15 System.map-5.15.0-89-generic
lrwxrwxrwx 1 root root 25 Dec 8 05:45 vmlinuz -> vmlinuz-5.15.0-89-generic
-rw------- 1 root root 11615656 Aug 14 19:07 vmlinuz-5.15.0-83-generic
-rw------- 1 root root 11619464 Oct 31 07:25 vmlinuz-5.15.0-89-generic
lrwxrwxrwx 1 root root 25 Sep 13 02:03 vmlinuz.old -> vmlinuz-5.15.0-83-generic
(Re)Install grub
grub-install --skip-fs-probe --boot-directory=/mnt/boot /dev/vg1/ubuntu-jammy
Try booting again, if that doesn't work, try open a VNC port and see if that shows any more details.
Unmount partition at the end
umount /mnt
After fixing the partition table
Running fdisk -l /dev/vg1/ubuntu-jammy
now shows the correct partition table.
Disk /dev/vg1/ubuntu-jammy: 20 GiB, 21474836480 bytes, 5242880 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 5C5C146F-D091-4D01-8585-C07C95C6876E
Device Start End Sectors Size Type
/dev/vg1/ubuntu-jammy1 256 511 256 1M BIOS boot
/dev/vg1/ubuntu-jammy2 512 5242874 5242363 20G Linux filesystem
Running sfdisk -d /dev/vg1/ubuntu-jammy
shows
label: gpt
label-id: 5C5C146F-D091-4D01-8585-C07C95C6876E
device: /dev/vg1/ubuntu-jammy
unit: sectors
first-lba: 6
last-lba: 5242874
sector-size: 4096
/dev/vg1/ubuntu-jammy1 : start= 256, size= 256, type=21686148-6449-6E6F-744E-656564454649, uuid=B96C4256-BC46-4993-8D74-4DA3206304F2, name="primary"
/dev/vg1/ubuntu-jammy2 : start= 512, size= 5242363, type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=B9423558-D29B-4A23-9B25-BB8C38409E69, name="primary"
Mounting a device with a different sector size using loop device
If you need to mount a device with a 512-byte based partition table, but are on a 4K disk, you could use a loop device to mount it .
kpartx -a /dev/vg1/backup-dc2
doesn't work because the parition table sector positions don't align with where the partitions actually are on the disk.
Create loop device
losetup --find --show --sector-size 512 -r /dev/vg1/backup-dc2
It should respond with a device name like /dev/loop5
.
fdisk -l /dev/loop5 # check partition table
kpartx -a /dev/loop5
mount -o ro /dev/mapper/loop5p1 /mnt
Do what you need with /mnt
. Then clean up with:
umount /mnt
kpartx -d /dev/loop5
losetup -d /dev/loop5