Luc Gommans/ blog

Hot resizing partitions LVM-on-LUKS

Written on 2016-02-19

Prerequisites

I assume you know a little bit about GNU/Linux systems and are able to use a command line (cd, ls, man). If you take the time to read man pages and look up an explanation about lvm, this little knowledge should be more or less sufficient. A rescue system (live boot) is always handy in case shit hits the fan, but if you did this partitioning before and are just looking up the commands to be sure, this is probably unnecessary.

Expected data layout

When installing Debian with an encrypted LVM, it uses the following configuration by default:

Two partitions: a boot partition for grub (sda1, mounted on /boot), and a data partition (sda5, filesystem type crypt-luks) contained in an extended partition (sda2). You can see this nicely in gparted.

This sda5 is the mother lode of course. It's encrypted with LUKS so everything inside is hidden. In here resides your LVM.

The LVM has one PV, one VG and two LVs: root and home. I am not sure whether the default install also includes swap, I guess so, but I disabled this. If you have swap, you might need to adjust the instructions.

Because LVM is contained within LUKS, this is called LVM-on-LUKS.

If you have a third logical volume for swap, that is not a big difference so you can still use these instructions slightly.

Introduction

All sources that I could find tell you to boot a live system, which is completely unnecessary if you are going to either grow, or leave unchanged, your root filesystem.

If you do wish to shrink your root filesystem, you probably have to boot a live system. You may also get away with copying the necessary files (a shell, lvm, etc.) to another partition and chrooting there, or booting from that partition in single user mode (though that would require you to copy the kernel), I'm not sure.

If you wish to change your swap partition, useful commands are swapon -a and swapoff -a.

In any case, this article is going to focus on growing the root filesystem and shrinking the home partition without rebooting. You will have to unmount your home partition, though, so you probably need to kill your desktop environment (or at the very least, log out, I'm not sure if it still keeps a file handle on your /home directory).

At least you don't need to find a usb stick and download an image with all dependencies! Everything you need is in your root filesystem already.

Inspect the situation

I expect you to understand the lay-out of the data. If not, make sure you are familiar with the basic concepts of lvm and know the commands to inspect and troubleshoot the situation. Some commands to know:

df -h display mounted partitions with free space, human readable.

lvdisplay display logical volumes

vgdisplay, pvdisplay display volume groups and physical volumes, respectively. Hint: type pv, vg or lv and hit tab one or two times to see all commands you can use to display/manipulate your physical volumes, volume groups or logical volumes, respectively.

systemctl or service for service management (old, simple way is service $name {start|stop|status}, but I'll be using systemctl, the new systemd way of doing this).

gparted is a graphical partition manager that is of little use here since we are using lvm (and encrypted lvm at that). Still, it can be of use.

Also know where your logical volumes are (/dev/mapper) and which is which.

For backups, I can kind of recommend duplicity. It's not everything I would wish for when doing regular and incremental backups, but at least for one-off backups it's close to perfect.

Shrinking your /home

Hold on, not so fast! First make a backup ;). Now continue.

First we need to unmount /home. To do this, I killed my desktop environment: close all programs, switch to a virtual terminal (Ctrl+Alt+F2), log in, and run systemctl stop lightdm.

Now check if anything else is using /home: lsof | grep /home.

In my case, docker was still using it, so I stopped docker: systemctl stop docker.

Does lsof bring up no more results for your home directory? Great, run umount /home and let's resize.

Resize the filesystem first: resize2fs /dev/mapper/${HOSTNAME}-vg--home 999G where 999G is the size you wish (you could also use 123M for megabytes, etc.). The default volume group name is $(HOSTNAME}-vg so I used that, but this may differ for you. Use vgdisplay if you are unsure. The command may tell you to run e2fsck first, but that's self-explanatory.

Then deactivate the volume so we can edit it: lvchange -an $VGNAME/home where $VGNAME is usually ${HOSTNAME}-vg. E.g. if your hostname is 'teapot' then it would be 'teapot-vg'.

Now change the size of the volume: lvresize -L -10G ${VGNAME}/home where -10G is the change (in this case, shrink 10 gigabytes).

Finally activate your volume again and mount it: lvchange -ay $VGNAME/home and mount /dev/mapper/${HOSTNAME}-vg--home /home.

Does this not mount? Then you probably made it too small. For some reason I had this issue: I resized the filesystem to 207GB (with resize2fs) and the volume to 207.5GB (I know how these things go, better leave some extra space) and still, the volume was made smaller than the filesystem.

Luckily changing it right back worked just fine: lvresize -L +10G $VGNAME/home made it mountable again. Just try shrinking again but leave some more space over this time. Using relative sizes seems to work better than absolute ones.

Checking the situation

You should be able to mount your home directory, see your files in there, and using pvdisplay you should see there are more than zero (probably a few thousand) free physical extents (see the field "Free PE"). This means we have space available on disk (or ssd) that we can assign to our root filesystem.

Growing root without unmounting

Here I did not do filesystem and volume resizing separately because it does need unmounting/deactivating. The command is simply lvresize -L +10G -r $VGNAME/root. Change the +10G with the desired size, of course. The -r flag tell it to resize the underlying filesystem by itself. I assume this always works just fine for ext-filesystems, but beware if you happen to be using something funky. You may, like with home, do this in two steps.

You should get output like "size changed from X to Y, successful. Resize2fs, on-line resizing required, the filesystem is now Z blocks long." This means it all worked fine.

Checking the situation

Running df -h will show you the new sizes of your partitions; pvdisplay should now show that there are no more physical extents available.

Some love for lvm

The reason this is so easy, is because we are using lvm. I don't think my root partition is a contiguous block on disk, like it would be when using normal partitions. Lvm can take physical extents (physical space) from anywhere on the physical volume and assign then to any logical volume.

Without this, you would have to move your whole home partition, copying every byte. If you have a 900GB home directory on a spinning disk, that takes some time (learned this the hard way).