My mailserver’s root partition has gotten really full lately, and I didn’t want to incur downtime by taking it down to enlarge offline:
root@mail:~# df -hT
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda2 ext4 19G 17G 1.2G 94% /
I run my VMs on KVM and I use an LVM LV for each VM, and according to a SO post, it is possible to increase the size partitions within a VM online, so let’s go for it:
Firstly, ensure there is enough free VG space to make room for the slice and check its current size:
root@fireball:~# vgs
VG #PV #LV #SN Attr VSize VFree
vg1 2 16 0 wz--n- 836.74g 143.74g
Next, increase the LV:
root@fireball:~# lvresize -L +10G /dev/vg1/vm-mail
Size of logical volume vg1/vm-mail changed from 20.00 GiB (5120 extents) to 30.00 GiB (7680 extents).
Logical volume vm-mail successfully resized.
Now that the LV is physically larger, we need to make KVM notify the guest that its disk has increased. First, get the virtio identifier:
root@fireball:~# virsh qemu-monitor-command mail info block --hmp
drive-virtio-disk0: /dev/vg1/vm-mail (raw)
Next, use that identifier like this:
root@fireball:~# virsh qemu-monitor-command mail block_resize drive-virtio-disk0 30G --hmp
root@mail:~#
Now, ensure dmesg within the VM indicates it has been notified of the size increase:
root@mail:~# dmesg -T
[Fri Oct 18 20:21:53 2019] vda: detected capacity change from 21474836480 to 32212254720
Whenever I make a VM, I always make swap really tiny as vda1, and the rest goes to the root partition as vda2, so increases are always possible without a full reinstall.
Now, we need to physically resize the partition within the VM. We’re going to use fdisk to first take note of the existing root partition and its starting sector, then delete it, recreate it at the same start sector, and re-apply the boot flag.
First, learn what the disk layout currently is and the current start sector for the root partition:
root@mail:~# fdisk -l
Disk /dev/vda: 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: dos
Disk identifier: 0x6e63ab94
Device Boot Start End Sectors Size Id Type
/dev/vda1 2048 2099199 2097152 1G 82 Linux swap / Solaris
/dev/vda2 * 2099200 41943039 39843840 19G 83 Linux
Now we’re ready to delete and recreate the partition
root@mail:~# fdisk /dev/vda
Welcome to fdisk (util-linux 2.25.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): d
Partition number (1,2, default 2):
Partition 2 has been deleted.
Command (m for help): n
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p):
Using default response p.
Partition number (2-4, default 2):
First sector (2099200-62914559, default 2099200): 2099200
Last sector, +sectors or +size{K,M,G,T,P} (2099200-62914559, default 62914559):
Created a new partition 2 of type 'Linux' and of size 29 GiB.
Command (m for help): p
Disk /dev/vda: 30 GiB, 32212254720 bytes, 62914560 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: 0x6e63ab94
Device Boot Start End Sectors Size Id Type
/dev/vda1 2048 2099199 2097152 1G 82 Linux swap / Solaris
/dev/vda2 2099200 62914559 60815360 29G 83 Linux
Command (m for help): a
Partition number (1,2, default 2):
The bootable flag on partition 2 is enabled now.
Command (m for help): w
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).
root@mail:~#
That warning at the end is expected and can be safely ignored. Last step is to resize the filesystem itself. Luckily ext4 lets you do this online in a single easy command:
root@mail:~# resize2fs /dev/vda2
resize2fs 1.42.12 (29-Aug-2014)
Filesystem at /dev/vda2 is mounted on /; on-line resizing required
old_desc_blocks = 2, new_desc_blocks = 2
The filesystem on /dev/vda2 is now 7601920 (4k) blocks long.
root@mail:~#
There, much better:
root@mail:~# df -hT
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda2 ext4 29G 17G 11G 61% /
This method is slightly dangerous if done wrong, but ideally you keep daily backups, right? Besides, why incur needless downtime and ruin a 320+ day uptime?