Recently I am working on a project requiring me to pack some QEMU images for the CI purpose. As it’s going be a VM which requires almost no changes after it’s configured, I was hoping to minimize it as much as possible. The OS image I need to use is the Debian 12 image from the official Debian release repo.

The softwares I installed required some disk space around 2G, which is more than the original disk space the image initially configured, so I decided to extend the disk to allocate more space directly as I really don’t want to create an extra img file for this work.

However, after following the existing tutorials to use qemu-img and fdisk to extend the disk, I found myself keep failing to reboot the system once the disk size is changed. Most tutorials or stackoverflow’s answers indicate I need to update /etc/fstab to tell the kernel the new PARTUUID, which doesn’t work at all after I updated PARTUUID of the partition / to the new one returned by blkid. It always complains that the PARTUUID doesn’t match then rejects to boot the system.

Only after I went through the boot arguments through cat /proc/cmdline in the initramfs mode, then I realized that the bootloader was keeping using the PARTUUID BEFORE the partition got extended.

So Opening the grub cfg file which controls the boot orders and params we then can see that the root PARTUUID was hardcoded here as the root param in the start up cmd.

menuentry 'Debian GNU/Linux' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-c27ec869-ac05-4efd-bdfa-c7b83e176149' {
        load_video
        insmod gzio
        if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
        insmod part_gpt
        insmod ext2
        set root='hd0,gpt1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1  c27ec869-ac05-4efd-bdfa-c7b83e176149
        else
          search --no-floppy --fs-uuid --set=root c27ec869-ac05-4efd-bdfa-c7b83e176149
        fi
        echo    'Loading Linux 6.1.0-28-amd64 ...'
        linux   /boot/vmlinuz-6.1.0-28-amd64 root=PARTUUID=1bd63af9-84e1-46f1-84de-ec62bcb5a427 ro console=tty0 console=ttyS0,115200 earlyprintk=ttyS0,115200 consoleblank=0
        echo    'Loading initial ramdisk ...'
        initrd  /boot/initrd.img-6.1.0-28-amd64
}

boot entry from /boot/grub/grub.cfg

Steps to extend the root partition

As a summary, in order to extend the root partition in the qcow2 image, you need:

  • Extend the qcow2 image in the host. qemu-img resize <qcow2 img file name> <new size>

  • boot the VM, in VM’s terminal, use fdisk to resize the root partition. Delete the partition 1 that the root / mounts to, usually it would be /dev/vda1. Then recreate a new one from the same starting block with the new size. Write the result and exit fdisk.

  • in VM’s terminal, run resize2fs /dev/vda1 to resize the file system

  • in VM’s terminal, run blkid to get the new /dev/vda1’s PARTUUID.

  • update the PARTUUID of root in /etc/fstab with the new id returned in the previous step.

  • update the root’s PARTTUID in /boot/grub/grub.cfg, you may globally replace all old root’s PARTUUID in it with the new root’s PARTUUID.

  • Reboot the system and it should have no errors.