Expanding the hard drive (non-LVM) of a Linux virtual machine

I created an Ubuntu desktop virtual machine (VM) on my KVM system, and shortly after I started using it, I realized that I hadn't allocated/created a large enough hard drive for my use.

I have a "master" Ubuntu VM that I clone when I need an Ubuntu VM, which is set up and configured they way I like it.

I had 2 options at this point to get a larger hard drive:

  1. Create a new Ubuntu VM.
  2. Expand/extend the hard drive/image in the existing Ubuntu VM.

I went with option #2, which was a learning experience, as by default, Ubuntu desktop does not use LVM, which is what I had documented previously on how to expand the hard drive of a VM.

I found a lot of instructions on the Internet that reference using the growpart and/or cfdisk commands, but those won't work on a mounted file system. They would require booting from a LiveCD/Rescue disc, then using the commands.

The instructions below worked on resizing a mounted file system.

tl;dr instructions to increase the hard drive space of an existing non-LVM Linux VM:

  • Increase the hard drive image size on the VM host (KVM)
  • Delete, then recreate the hard drive partitions in the VM

In this example, my VM's hard drive was /dev/vda, which had a logical partition (/dev/vda2) and Linux partition (/dev/vda5).

Both /dev/vda2 and /dev/vda5 are tied together, so any modifications would need to be done to both.

Pre checks run on the virtual machine (VM)

sudo fdisk /dev/vda -l
Disk /dev/vda: 25 GiB, 26843545600 bytes, 52428800 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: dos
Disk identifier: 0x4e3fd9a3

Device     Boot   Start      End  Sectors  Size Id Type
/dev/vda1  *       2048  1050623  1048576  512M  b W95 FAT32
/dev/vda2       1052670 52426751 51374082 24.5G  5 Extended
/dev/vda5       1052672 52426751 51374080 24.5G 83 Linux
df -h /dev/vda5
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda5        24G  6.7G   17G  30% /

Increase the VM's hard drive size on the KVM host

  1. Make sure the VM is shut off:

    virsh list --all
     Id   Name                            State
    ------------------------------------------------
     -    ubuntu20.04-disk-resize-test   shut off
    
  2. Dump the current disks configuration:

    virsh domblklist ubuntu20.04-disk-resize-test
     Target   Source
    -------------------------------------------------------
     vda      /kvm/images/ubuntu20.04-disk-resize-test.qcow2
    
  3. Check for any VM snapshots, and delete any that are exist:

    The qemu-img command can't resize an image if that image has snapshots, so we'll need to delete any snapshots before resizing.

    virsh snapshot-list ubuntu20.04-disk-resize-test
    Name        Creation Time               State
    --------------------------------------------------
     snapshot1   2021-09-01 11:31:51 -0600   shutoff
    
    virsh snapshot-delete --domain ubuntu20.04-disk-resize-test --snapshotname snapshot1
    Domain snapshot snapshot1 deleted
    
  4. Resize the hard drive image on the KVM host:

    As, at least in my system, the /kvm/images/ are all owned by root, need to use sudo to resize the image.

    In this example, I'm increasing the disk size by 25Gb.

    sudo qemu-img resize /kvm/images/ubuntu20.04-disk-resize-test.qcow2 +25G
    Image resized.
    

    It doesn't actually perform the resize, it only configures it to use the additional space, so the Image resized. comes back almost immediately.

  5. Verify new disk size:

    sudo qemu-img info /kvm/images/ubuntu20.04-disk-resize-test.qcow2
    image: /mnt/kvm/images/ubuntu20.04-clone-1.qcow2
    file format: qcow2
    virtual size: 50 GiB (53687091200 bytes)
    disk size: 3.94 GiB
    cluster_size: 65536
    Format specific information:
        compat: 1.1
        lazy refcounts: true
        refcount bits: 16
        corrupt: false
    
  6. After restarting the VM, configure the VM to use the additional disk space:

    Check that the VM sees the new disk size:

    sudo fdisk /dev/vda -l
    Disk /dev/vda: 50 GiB, 53687091200 bytes, 104857600 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: dos
    Disk identifier: 0x4e3fd9a3
    
    Device     Boot   Start      End  Sectors  Size Id Type
    /dev/vda1  *       2048  1050623  1048576  512M  b W95 FAT32
    /dev/vda2       1052670 52426751 51374082 24.5G  5 Extended
    /dev/vda5       1052672 52426751 51374080 24.5G 83 Linux
    

    While the disk sees the additional space, the file system doesn't (yet):

    df -h /dev/vda5
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/vda5        24G  6.7G   17G  30% /
    
  7. Use fdisk to delete/recreate the partitions, to use the additional space.

    To get the filesystem to use the additional disk space, we will need to delete the Extended (ID 5) and the Linux (ID 83) partitions, but immediately recreate them, before writing the new partition information to disk.

    Delete the Linux (ID 83) partition first, then the Extended (ID 5) partition, then create them in the same order.

    If you get a Failed to add partition 2 to system: Device or resource busy error message, that's normal, as you're modifying a mounted partition

    sudo fdisk /dev/vda
    
    Welcome to fdisk (util-linux 2.34).
    Changes will remain in memory only, until you decide to write them.
    Be careful before using the write command.
    
    
    Command (m for help): p
    Disk /dev/vda: 50 GiB, 53687091200 bytes, 104857600 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: dos
    Disk identifier: 0x4e3fd9a3
    
    Device     Boot   Start      End  Sectors  Size Id Type
    /dev/vda1  *       2048  1050623  1048576  512M  b W95 FAT32
    /dev/vda2       1052670 52426751 51374082 24.5G  5 Extended
    /dev/vda5       1052672 52426751 51374080 24.5G 83 Linux
    
    Command (m for help): d
    Partition number (1,2,5, default 5): 5
    
    Partition 5 has been deleted.
    
    Command (m for help): d
    Partition number (1,2, default 2): 2
    
    Partition 2 has been deleted.
    
    Command (m for help): p
    Disk /dev/vda: 50 GiB, 53687091200 bytes, 104857600 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: dos
    Disk identifier: 0x4e3fd9a3
    
    Device     Boot Start     End Sectors  Size Id Type
    /dev/vda1  *     2048 1050623 1048576  512M  b W95 FAT32
    
    Command (m for help): n
    Partition type
       p   primary (1 primary, 0 extended, 3 free)
       e   extended (container for logical partitions)
    Select (default p): e
    Partition number (2-4, default 2): 2
    First sector (1050624-104857599, default 1050624):
    Last sector, +/-sectors or +/-size{K,M,G,T,P} (1050624-104857599, default 104857599):
    
    Created a new partition 2 of type 'Extended' and of size 49.5 GiB.
    
    Command (m for help): n
    All space for primary partitions is in use.
    Adding logical partition 5
    First sector (1052672-104857599, default 1052672):
    Last sector, +/-sectors or +/-size{K,M,G,T,P} (1052672-104857599, default 104857599):
    
    Created a new partition 5 of type 'Linux' and of size 49.5 GiB.
    Partition #5 contains a ext4 signature.
    
    Do you want to remove the signature? [Y]es/[N]o: y
    
    The signature will be removed by a write command.
    
    Command (m for help): t
    Partition number (1,2,5, default 5): 5
    Hex code (type L to list all codes): L
    
     0  Empty           24  NEC DOS         81  Minix / old Lin bf  Solaris
     1  FAT12           27  Hidden NTFS Win 82  Linux swap / So c1  DRDOS/sec (FAT-
     2  XENIX root      39  Plan 9          83  Linux           c4  DRDOS/sec (FAT-
     3  XENIX usr       3c  PartitionMagic  84  OS/2 hidden or  c6  DRDOS/sec (FAT-
     4  FAT16 <32M      40  Venix 80286     85  Linux extended  c7  Syrinx
     5  Extended        41  PPC PReP Boot   86  NTFS volume set da  Non-FS data
     6  FAT16           42  SFS             87  NTFS volume set db  CP/M / CTOS / .
     7  HPFS/NTFS/exFAT 4d  QNX4.x          88  Linux plaintext de  Dell Utility
     8  AIX             4e  QNX4.x 2nd part 8e  Linux LVM       df  BootIt
     9  AIX bootable    4f  QNX4.x 3rd part 93  Amoeba          e1  DOS access
     a  OS/2 Boot Manag 50  OnTrack DM      94  Amoeba BBT      e3  DOS R/O
     b  W95 FAT32       51  OnTrack DM6 Aux 9f  BSD/OS          e4  SpeedStor
     c  W95 FAT32 (LBA) 52  CP/M            a0  IBM Thinkpad hi ea  Rufus alignment
     e  W95 FAT16 (LBA) 53  OnTrack DM6 Aux a5  FreeBSD         eb  BeOS fs
     f  W95 Ext'd (LBA) 54  OnTrackDM6      a6  OpenBSD         ee  GPT
    10  OPUS            55  EZ-Drive        a7  NeXTSTEP        ef  EFI (FAT-12/16/
    11  Hidden FAT12    56  Golden Bow      a8  Darwin UFS      f0  Linux/PA-RISC b
    12  Compaq diagnost 5c  Priam Edisk     a9  NetBSD          f1  SpeedStor
    14  Hidden FAT16 <3 61  SpeedStor       ab  Darwin boot     f4  SpeedStor
    16  Hidden FAT16    63  GNU HURD or Sys af  HFS / HFS+      f2  DOS secondary
    17  Hidden HPFS/NTF 64  Novell Netware  b7  BSDI fs         fb  VMware VMFS
    18  AST SmartSleep  65  Novell Netware  b8  BSDI swap       fc  VMware VMKCORE
    1b  Hidden W95 FAT3 70  DiskSecure Mult bb  Boot Wizard hid fd  Linux raid auto
    1c  Hidden W95 FAT3 75  PC/IX           bc  Acronis FAT32 L fe  LANstep
    1e  Hidden W95 FAT1 80  Old Minix       be  Solaris boot    ff  BBT
    Hex code (type L to list all codes): 83
    
    Changed type of partition 'Linux' to 'Linux'.
    
    Command (m for help): p
    Disk /dev/vda: 50 GiB, 53687091200 bytes, 104857600 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: dos
    Disk identifier: 0x4e3fd9a3
    
    Device     Boot   Start       End   Sectors  Size Id Type
    /dev/vda1  *       2048   1050623   1048576  512M  b W95 FAT32
    /dev/vda2       1050624 104857599 103806976 49.5G  5 Extended
    /dev/vda5       1052672 104857599 103804928 49.5G 83 Linux
    
    Filesystem/RAID signature on partition 5 will be wiped.
    
    Command (m for help): w
    The partition table has been altered.
    Failed to add partition 2 to system: Device or resource busy
    
    The kernel still uses the old partitions. The new table will be used at the next reboot.
    Syncing disks.
    
  8. Resize the file system.

    Once the new, larger partitions exist, we need to resize the file system.

    From the resize2fs man page:

    The resize2fs program does not manipulate the size of partitions. If you wish to enlarge a filesystem, you must make sure you can expand the size of the underlying partition first. This can be done using fdisk(8) by deleting the partition and recreating it with a larger size or using lvextend(8), if you're using the logical volume manager lvm(8).

    sudo resize2fs /dev/vda5
    resize2fs 1.45.5 (07-Jan-2020)
    Filesystem at /dev/vda5 is mounted on /; on-line resizing required
    old_desc_blocks = 4, new_desc_blocks = 7
    The filesystem on /dev/vda5 is now 12975616 (4k) blocks long.
    
  9. Verify that the new space is being used by the partitions:

    sudo fdisk /dev/vda -l
    Disk /dev/vda: 50 GiB, 53687091200 bytes, 104857600 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: dos
    Disk identifier: 0x4e3fd9a3
    
    Device     Boot   Start       End   Sectors  Size Id Type
    /dev/vda1  *       2048   1050623   1048576  512M  b W95 FAT32
    /dev/vda2       1050624 104857599 103806976 49.5G  5 Extended
    /dev/vda5       1052672 104857599 103804928 49.5G 83 Linux
    
  10. Finally, verify that the file system is also using the new space:

    df -h /dev/vda5
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/vda5        49G  6.7G   40G  15% /
    

Reboot the system and enjoy the additional space.

References

Increasing a KVM Virtual Machine Disk when using LVM and ext4 https://sandilands.info/sgordon/increasing-kvm-virtual-machine-disk-using-lvm-ext4

Ubuntu manuals - resize2fs - ext2/ext3/ext4 file system resizer https://manpages.ubuntu.com/manpages/focal/man8/resize2fs.8.html