How to Expand a Linux VM Disk and Filesystem Without Rebooting

How to Expand a Linux VM Disk and Filesystem Without Rebooting

In Guides, Linux, Virtualization by KevinLeave a Comment

Ever found yourself in the position were you were running out of space on a Linux server and needed to expand the storage but couldn’t reboot the server? This article aims to explain how to increase the size of the root partition without rebooting.

Expanding the virtual disk is usually easy, but making the operating system use that additional space requires changes inside the guest. The good news is that most modern Linux distributions support online filesystem expansion, allowing you to increase available storage without rebooting the server or interrupting running applications.

This guide explains the general process and covers the most common Linux VM storage layouts across platforms such as:

  • KVM / QEMU
  • VMware ESXi
  • Microsoft Hyper-V
  • Xen
  • VirtualBox
  • Cloud providers using VirtIO, SCSI, or NVMe disks

The exact commands depend on your disk layout, filesystem, and storage technology.

Understanding the Storage Stack of a Linux VM

It is important to understand where the available space exists. A virtual machine disk has multiple layers:

Hypervisor
    |
    ↓
Virtual Disk (VMDK/QCOW2/VHDX/VHD)
    |
    ↓
Linux Block Device (/dev/sda, /dev/vda, /dev/nvme0n1)
    |
    ↓
Partition / LVM / RAID
    |
    ↓
Filesystem (ext4, XFS, Btrfs)
    |
    ↓
Mounted Directory (/)

Increasing the virtual disk only changes the first layer. For example:

Before:

Virtual disk: 50GB

/dev/vda
└── /dev/vda1
        └── ext4 filesystem (50GB)

After expanding the disk:

Virtual disk: 100GB

/dev/vda
└── /dev/vda1
        └── ext4 filesystem (50GB)

Unused space: 50GB

The additional storage is not automatically available. The partition and filesystem still need to be expanded before Linux can use the extra capacity.

Pre-requisites

Before making any changes make sure you have:

  • Administrative access to the virtual machine hypervisor.
  • Permission to resize the virtual disk on the hypervisor.
  • SSH access to the virtual machine.
  • A recent snapshot or backup.
  • Knowledge of the current storage layout.

1. Check the Current Disk Layout

Identify how the system is currently configured.

Start with lsblk:

root@server01:~# lsblk

NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
vda    252:0    0   50G  0 disk
├─vda1 252:1    0    1G  0 part /boot
└─vda2 252:2    0   49G  0 part /

This shows:

  • The disk (vda) is 50GB.
  • The root partition (vda2) is only 49GB.

Check filesystem usage:

root@server01:~# df -h

Filesystem      Size  Used Avail Use% Mounted on
/dev/vda2        49G   43G  4.0G  92% /
/dev/vda1       974M  120M  854M  13% /boot

2. Expand the Virtual Disk

The first step is done at the hypervisor level. Increase the virtual disk size to the desired final capacity. For example, if the current disk is 50GB and you need an additional 50GB, resize the virtual disk to 100GB.

Increase the disk size:

  • Virtual Machine → Edit Settings → Hard Disk → Increase Capacity

Powershell:

Resize-VHD 
  -Path "LinuxServer01.vhdx" 
  -SizeBytes 100GB

VBoxManage modifymedium disk LinuxServer01.vdi --resize 102400

Because:

100GB × 1024MB = 102400MB

qemu-img resize is different. Without a + prefix it sets the final size:

qemu-img resize linux-server.qcow2 100G

With a + prefix it adds space:

qemu-img resize linux-server.qcow2 +50G

Both result in:

50GB + 50GB = 100GB

For a running VM:

virsh blockresize linux-server /var/lib/libvirt/images/linux-server.qcow2 100G

The exact command depends on the Xen storage backend. For example, with an LVM-backed virtual disk:

lvextend -L +50G /dev/vg/vm-disk

At this point, the hypervisor disk is larger, but Linux has not necessarily detected the change yet.

3. Rescan the Disk From Linux

After resizing the virtual disk, Linux may not immediately detect the additional capacity.

root@server01:~# lsblk

NAME   SIZE TYPE MOUNTPOINTS
vda     50G disk
├─vda1   1G part /boot
└─vda2  49G part /

The disk is still showing the old size. So we need to rescan the device.

Rescan depending on the device type.

For SCSI disks:

echo1 > /sys/class/block/sda/device/rescan

For VirtIO disks:

echo1 > /sys/class/block/vda/device/rescan

For NVMe:

nvme rescan

Verify

Verify the new size after scanning the device.

root@server01:~# lsblk

NAME   SIZE TYPE MOUNTPOINTS
vda    100G disk
├─vda1   1G part /boot
└─vda2  49G part /

Linux now sees the additional storage. But the partition has not increased yet.

4. Determine Your Storage Type

The expansion procedure depends on how the disk is configured.

Common layouts include:

  • Standard partitions
  • LVM
  • Software RAID
  • ZFS
  • Encrypted volumes

The most common Linux setups are standard partitions and LVM.

Traditional partitions

Example:

/dev/vda1 → /

Tools:

  • fdisk
  • parted
  • resize2fs
  • xfs_growfs

LVM

Example:

/dev/vda
 └── partition
      └── volume group
            └── logical volume /

Tools:

  • pvresize
  • lvextend
  • resize2fs
  • xfs_growfs

LVM is usually the easiest layout to expand.

Other storage technologies

Some environments use:

  • RAID
  • ZFS
  • Btrfs
  • encrypted volumes

These require their own expansion procedures.

5. Expanding an LVM Root Filesystem

LVM is common in enterprise Linux distributions and many cloud images.

Check LVM disk

Check whether LVM is being used:

root@server01:~# lsblk

NAME                 SIZE TYPE MOUNTPOINTS
vda                   50G disk
└─vda2                50G part
  └─ubuntu--vg-root   50G lvm  /

After expanding the virtual disk to 100GB and rescanning:

root@server01:~# lsblk

NAME                 SIZE TYPE MOUNTPOINTS
vda                  100G disk
└─vda2               100G part
  └─ubuntu--vg-root   50G lvm  /

The disk and partition are now larger, but the logical volume still uses the original 50GB.

Check volume groups:

root@server01:~# vgdisplay

  VG Name               ubuntu-vg
  VG Size               98.00 GiB
  Alloc PE / Size       49.00 GiB
  Free PE / Size        49.00 GiB

Resize the physical volume

root@server01:~# pvresize /dev/vda2

Physical volume "/dev/vda2" changed
1 physical volume(s) resized or updated

Extend the logical volume

root@server01:~# lvextend -l +100%FREE /dev/ubuntu-vg/root

Size of logical volume ubuntu-vg/root changed from 49.00 GiB to 98.00 GiB.
Logical volume ubuntu-vg/root successfully resized.

Alternatively:

lvextend -L +50G /dev/mapper/root

Grow the filesystem

For ext4:

root@server01:~# resize2fs /dev/ubuntu-vg/root

resize2fs 1.46.5 (30-Dec-2021)
Filesystem at /dev/ubuntu-vg/root is mounted on /; on-line resizing required
The filesystem on /dev/ubuntu-vg/root is now 25690112 (4k) blocks long.

For XFS:

root@server01:~# xfs_growfs /

data blocks changed from 12845056 to 25690112

Verify

root@server01:~# df -h /

Filesystem                   Size Used Avail Use%
/dev/mapper/ubuntu--vg-root   98G  43G   51G  46% /

6. Expanding a Traditional Partition

Some Linux installations use a simple partition layout without LVM.

Example:

root@server01:~# fdisk -l /dev/vda

Device      Start     End        Sectors    Size
/dev/vda1   2048      96471039   96468991   46G
/dev/vda2   96471040  104857599  8386559    4G

The important value is the Start sector.

When recreating the partition, this start sector must remain identical. A mistake here can corrupt the filesystem and make it inaccessible.

Disable Swap (If Required)

If swap is a dedicated partition (⚠️ Make sure that your system can stay online for a bit without swap):

swapoff -a

Delete Partitions

Reconfigure the partitions using fdisk. First we delete the two existing partitions. Run fdisk /dev/vda and then use d to delete partition 2, and then delete partition 1:

root@prod-deb-01:~# fdisk /dev/vda

Command (m for help): d
Partition number (1,2, default 2):

Partition 2 has been deleted.

Command (m for help): d
Selected partition 1
Partition 1 has been deleted.

⚠️ Important: This process modifies the partition table. The existing partitions are deleted and recreated with new boundaries. The data is preserved only because the partitions are recreated with the exact same starting sectors. Always verify the start sector before writing changes and ensure you have a working backup or snapshot.

Recreate Partitions

Then we recreate our partitions. Since we had 4GB of swap space we want to keep at least the same amount for the new swap partition (you could increase it too if you wanted).

First recreate /dev/vda1:

  • Press n to create a new partition.
  • Enter p to create a primary partition.
  • We can press Enter to accept the default value of 2048 for the first sector.
  • Then enter a size for the partition. You can enter a value in GB, so if we are increasing the disk to 100 GB, we subtract our 4 GB for swap, and enter +96G for 96 GB.
Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-209715199, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-209715199, default 209715199): +96G

Created a new partition 1 of type 'Linux' and of size 96 GiB.

Then, we recreate the swap partition:

  • Press n and then p to create a new primary partition.
  • Press Enter to accept the default value for “First sector”.
  • We can also press Enter again to accept the default value for “Last sector”.
Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (201328640-209715199, default 201328640):
Last sector, +sectors or +size{K,M,G,T,P} (201328640-209715199, default 209715199):

Created a new partition 2 of type 'Linux' and of size 4 GiB.

Since this partition is going to be used for swap space, we need to change the partition type using fdisk:

  • Press t.
  • We then press 2 to select the second partition.
  • If you want to see the list of available partition types, press L, otherwise enter 82 to select Linux swap / Solaris.
Command (m for help): t
Partition number (1,2, default 2): 2
Partition type (type L to list all types): 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
Partition type (type L to list all types): 82

fdisk should informs us that we have changed the partition type:

Changed type of partition 'Linux' to 'Linux swap / Solaris'.

After that, we save using the w command:

Command (m for help): w

You may get a message like this before exiting:

The partition table has been altered.
Calling ioctl() to re-read partition table.
Re-reading the partition table failed.: Device or resource busy

The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8).

Refresh the Kernel Partition Table Without Rebooting

We can tell the kernel about the new partitions using partprobe:

root@prod-deb-01:~# partprobe

Resize the Filesystem

Once the partition has been expanded:

ext4

resize2fs /dev/vda2

Example:

resize2fs 1.47.0
Filesystem at /dev/vda2 is mounted on /; on-line resizing required
The filesystem on /dev/vda2 is now 39062500 blocks long.

XFS

xfs_growfs /

Example:

meta-data=/dev/vda2
data blocks changed from 12800000 to 39062500

BTRFS

btrfs filesystem resize max /

Initialise new swap location of /dev/vda2

Since we recreated the swap partition, we need to initialise it:

root@prod-deb-01:~# mkswap /dev/vda2
Setting up swapspace version 1, size = 4193276 KiB
no label, UUID=c55c25a2-a386-4653-8455-4d9030586dd2

Then, we edit /etc/fstab and replace the old UUID with the new one returned by the mkswap command. The line to change has no value for “mount point” and has “type” set to swap.

# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
UUID=332f8fb5-ff1f-4297-b512-f2c93a277296 /               ext4    errors=remount-ro 0       1
/dev/fd0        /media/floppy0  auto    rw,user,noauto,exec,utf8 0       0
UUID=c55c25a2-a386-4653-8455-4d9030586dd2       none    swap    sw      0       0

Re-Enable swap

After editing /etc/fstab, we need to enable swap again:

root@prod-deb-01:~# swapon -a

7. Expanding ZFS Storage

ZFS uses a different approach. After increasing the virtual disk:

Check the pool:

zpool status

Expand the device:

zpool online -e pool_name device_name

Verify:

zpool list

8. Verify the Expansion

Check the filesystem:

df-h /

Filesystem      Size Used Avail Use%
/dev/vda2       96G   43G   49G47% /

Check the partition layout:

lsblk

NAME   SIZE TYPE MOUNTPOINTS
vda    100G disk
├─vda1   1G part /boot
└─vda2  96G part /

Confirm uptime:

uptime14:32:51 up147 days,4:21,2 users, load average:0.05,0.02,0.00

The server has been expanded without rebooting.

When a Reboot May Still Be Required

Online expansion works on most modern Linux systems, but some situations may require downtime:

  • The kernel cannot reread the partition table.
  • The root partition layout changes unexpectedly.
  • Older filesystems are being used.
  • Encrypted disks require additional steps.
  • RAID metadata needs rebuilding.
  • The hypervisor does not support online disk resizing.

References

1. KVM / QEMU / libvirt

2. VMware ESXi & vSphere

3. Microsoft Hyper-V

4. VirtualBox

5. Xen / XenServer / XCP-ng

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.