resizing a libvirt VMs BTRFS root

Today I wanted to resize the root partition and backing storage of a SLE12-SP3 VM I use for debugging. This included quite some Google research and thus I thought I’ll write down the steps I took for reference and others.

First check your VM’s block devices:

jthumshirn@laptop:~$ virsh -c qemu+ssh://root@kvm-server/system domblklist sles12sp3 
Target     Source
------------------------------------------------
vda        /var/lib/libvirt/images/sles12sp3-1.qcow2
sda        /mounts/dist/install/SLE-12-SP3-Server-GM/SLE-12-SP3-Server-DVD-x86_64-GM-DVD1.iso

I want to resize vda which is the device my / lives on.

jthumshirn@laptop:~$ virsh -c qemu+ssh://root@kvm-server/system blockresize sles12sp3 vda 80G
Block device 'vda' is resized

Just to be sure, lets check if the VM noticed the resize.

sles12sp3-fstests-vm:~ # dmesg | tail -n2
[ 1842.675424] virtio_blk virtio2: new size: 167772160 512-byte logical blocks (85.9 GB/80.0 GiB)
[ 1842.675434] vda: detected capacity change from 42949672960 to 85899345920

Until now, we’ve only resized the block device itself. Next we need to adjust the partition. As I’m using a GPT based partition layout, I’ll have to fix the backup GPT at the end of the disk first. For which I had to use parted.

les12sp3-fstests-vm:~ # parted /dev/vda print
Error: The backup GPT table is not at the end of the disk, as it should be.
This might mean that another operating system believes the disk is smaller.
Fix, by moving the backup to the end (and removing the old backup)?
Fix/Ignore/Cancel? F
Warning: Not all of the space available to /dev/vda appears to be used, you can
fix the GPT to use all of the space (an extra 83886080 blocks) or continue with
the current setting?
Fix/Ignore? Fix
Model: Virtio Block Device (virtblk)
Disk /dev/vda: 85.9GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system     Name     Flags
 1      1049kB  165MB   164MB   fat16           primary  boot
 2      165MB   2319MB  2155MB  linux-swap(v1)  primary
 3      2319MB  42.9GB  40.6GB  btrfs

Now up to resizing the partition itself. Parted didn’t let me resize a mounted partition, so I went old school and used fdisk. As fdisk doesn’t know how to resize a partition you have to delete it and then re-create it. This is save as fdisk uses in-memory datastructures and only commits changes to disk when you instruct it to.

sles12sp3-fstests-vm:~ # fdisk /dev/vda

Welcome to fdisk (util-linux 2.29.2).
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: 80 GiB, 85899345920 bytes, 167772160 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: 087BD880-90A9-46B1-8277-CD68D6881096

Device       Start      End  Sectors  Size Type
/dev/vda1     2048   321535   319488  156M EFI System
/dev/vda2   321536  4530175  4208640    2G Microsoft basic data
/dev/vda3  4530176 83886046 79355871 37.9G Linux filesystem

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

Partition 3 has been deleted.

Command (m for help): n
Partition number (3-128, default 3): 3
First sector (4530176-167772126, default 4530176):
: st sector, +sectors or +size{K,M,G,T,P} (4530176-167772126, default 167772126):

Created a new partition 3 of type 'Linux filesystem' and of size 77.9 GiB.
Partition #3 contains a btrfs signature.

Do you want to remove the signature? [Y]es/[N]o: n

Command (m for help): p

Disk /dev/vda: 80 GiB, 85899345920 bytes, 167772160 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: 087BD880-90A9-46B1-8277-CD68D6881096

Device       Start       End   Sectors  Size Type
/dev/vda1     2048    321535    319488  156M EFI System
/dev/vda2   321536   4530175   4208640    2G Microsoft basic data
/dev/vda3  4530176 167772126 163241951 77.9G Linux filesystem

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).

Thankfully fdisk notifies you that you have to tell the kernel about the changed partition table as well, for this I used partx. Check with lsblk that the kernel actually sees the update.

sles12sp3-fstests-vm:~ # partx -u -n 3 /dev/vda
sles12sp3-fstests-vm:~ # lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0     11:0    1  3.6G  0 rom
vda    253:0    0   80G  0 disk
├─vda1 253:1    0  156M  0 part /boot/efi
├─vda2 253:2    0    2G  0 part [SWAP]
└─vda3 253:3    0 77.9G  0 part /

Next on we have to resize the filesystem (btrfs in my case) on top of our new device as well.

sles12sp3-fstests-vm:~ # btrfs filesystem resize max /
Resize '/' of 'max'
sles12sp3-fstests-vm:~ # dmesg | tail -n 1
[ 2284.767980] BTRFS info (device vda3): new size for /dev/vda3 is 83579875328
sles12sp3-fstests-vm:~ # btrfs filesystem show /
Label: none  uuid: 16511074-0ba2-422c-98b6-a8ea19a296a1
	Total devices 1 FS bytes used 4.01GiB
	devid    1 size 77.84GiB used 5.06GiB path /dev/vda3

Et voilà we have a 80GB root filesystem.