Convert existing root filesystem to LVM

On my Debian 9 virtual machines i wanted to be able to:

  • create snapshots to get consistent backups
  • easily extend the size of the disk

Snapshotting the disk images is not an option as some of those backups run every hour and i’m only interested in the files, not the whole VM.

On this page i describe what i did to convert my existing root file system to an LVM setup. LVM is set up on a new disk and the data from the existing root file system is copied to the new LVM root file system. This also involves modifying /etc/fstab and some initramfs configuration, recreating the initramfs and reinstalling grub.

Create a new disk and add it to the VM. How this is done depends an which virtualization tools are used. I use Proxmox so i added an additional disk with 12 gb through the GUI. This disk is added as /dev/vdbto the VM.

Create a partition /dev/vdb1 spanning the whole disk with e.g. cfdisk or parted and assign it partition type “8e”  (Linux LVM).

To use LVM initialize the partition /dev/vdb1 to be used with LVM and create a volume group named vgroup and logical volumes for root and swap:

# pvcreate /dev/vdb1
# vgcreate vgroup /dev/vdb1

Before creating the logical volumes for / named root and swap named swap, check the sizes of the existing root (10gb) and swap (2 gb) partition. The root file system has a size of 10 gb and the swap partition is created using the remaining free disk space.

# lvcreate -L 10G -n root vgroup
# lvcreate -l 100%FREE -n swap vgroup

Create the file system on the new root lv, the example below creates an ext4 file system:

# mkfs.ext4 /dev/vgroup/root

Initialize the new swap partition:

# mkswap /dev/vgroup/swap

For the system to be able to mount the root file system after switching to the new disk the disk UUID for the root and swap file system need to be changed in /etc/fstab.  This should be done now. Enter blkid as root to get the UUIDs of the new LVs:

# blkid
/dev/vda1: LABEL="root" UUID="d2a6d74f-bc44-4232-9239-f921da8985bc" TYPE="ext4" PARTUUID="2b039b23-01"
/dev/vda2: UUID="6dd0ebe4-a535-4d1f-b0e7-544ec9f0c89c" TYPE="swap" PARTUUID="2b039b23-02"
/dev/vdb1: UUID="jT11Ff-vGtf-kQX5-bRbf-y5pr-5JC6-RpQMRv" TYPE="LVM2_member" PARTUUID="0c0689e5-01"
/dev/mapper/vgroup-root: UUID="a163fcb6-38bf-47c2-84b0-2d80cfffa76d" TYPE="ext4"
/dev/mapper/vgroup-swap: UUID="c3420a3d-47a6-4f2f-9dba-abce6fc01e4c" TYPE="swap"

In /etc/fstab duplicate the configuration for the root and swap partitions, change the UUIDs to use the LVs UUIDs and comment those lines for now.

# vim /etc/fstab
# / was on /dev/vda1 during installation
UUID=d2a6d74f-bc44-4232-9239-f921da8985bc /    ext4 errors=remount-ro 0 1
#UUID=a163fcb6-38bf-47c2-84b0-2d80cfffa76d /    ext4 errors=remount-ro 0 1
# swap was on /dev/vda2 during installation
UUID=6dd0ebe4-a535-4d1f-b0e7-544ec9f0c89c none    swap sw 0 0
#UUID=c3420a3d-47a6-4f2f-9dba-abce6fc01e4c none    swap sw 0 0

When booting from the new LVM disk, this message can appear during the early boot process after some waiting time:

Gave up waiting for suspend/resume device

This is because the swap device is used as suspend/resume device and the old swap partitions UUID is configured in the initramfs. This UUID is configured in the file /etc/initramfs-tools/conf.d/resume. Make a backup of this file before the changeing the UUID to the new one. For this to take effect a rebuild of the initramfs is necessary.

# vim /etc/initramfs-tools/conf.d/resume

The next steps are done using Rescue mode from a Debian 9 (net)install disk.

First get the (net)install disk image for Debian 9 (or whatever distribution is used) and add it as CD-Rom drive to the VM. Boot from this disk and enter Rescue mode.

Once in Rescue mode select the old root partition /dev/vda1 for the root file system and select Execute a shell in /dev/vda1. This is the old root file system with the prepared /etc/fstab and /etc/initramfs-tools/conf.d/resume files containing the new disk UUIDs.

To copy the data to the new disk create a new mount point and mount the LV on it

# mkdir /aaAa
# mount /dev/vgroup/root /aaAa

I use this little script rootfs2lvm to copy everything to the new disk. The script can also be used to update the destination when the source has changed.

# (c) 2018 Christian valo Kivalo
# Version 0.1
# copy filesystem contents to lvm mounted on $2

set -e

usage() {
    printf '%b\n' "$0 $src $dst\n"
    exit 1

die() {
    local ecode=$1; shift
    local reason="$1"; shift
    printf '%b\n' "$reason"
    exit $ecode

test $# -eq 2 || usage


# test if $srcdir is / and if $dstdir is a mounted disks root
test -d ${srcdir}/lost+found || die 244 "SRCDIR not mounted"
test -d ${dstdir}/lost+found || die 245 "DSTDIR not mounted"

# some directories and files should not be copied or deleted
exclude="--exclude=${dstdir} --filter=exclude_/dev/* --filter=exclude_/run/* --filter=protect_/lost+found/ --filter=exclude_/proc/* --filter=exclude_/sys/*"

# rsync options. _rsync_opt3 is empty, add --dry-run for testing
_rsync_opt1="-aHAX --numeric-ids --stats --progress --human-readable"
_rsync_opt2="--delete-during --inplace --delete-excluded"

rsync "$_rsync_opt1" "$_rsync_opt2" "$_rsync_opt3" \
    "$exclude" "$srcdir" "$dstdir"

Invoke the script with and wait until all data is copied to the new disk. This take some time depending on the amount of data.

# ./rootfs2lvm / /aaAa/

After the data is copied to the new disk exit the shell and select Choose a different root file system . Then select the new LVM root LV /dev/vgroup/root.

First select Reinstall GRUB boot loader  and enter /dev/vdb  when prompted. After this select Execute a shell in /dev/vgroup/root.

The following steps prepare the system to boot from the new disk.

First change /etc/fstab and comment the fstab entries with the old disks UUID and uncomment the entries with the new UUIDs.

# / was on /dev/vda1 during installation
#UUID=d2a6d74f-bc44-4232-9239-f921da8985bc /    ext4 errors=remount-ro 0 1
UUID=a163fcb6-38bf-47c2-84b0-2d80cfffa76d /    ext4 errors=remount-ro 0 1
# swap was on /dev/vda2 during installation
#UUID=6dd0ebe4-a535-4d1f-b0e7-544ec9f0c89c none    swap sw 0 0
UUID=c3420a3d-47a6-4f2f-9dba-abce6fc01e4c none    swap sw 0 0

Update grub configuration to know about and load the lvm module and update the initramfs images

# update-grub
# update-initramfs -k all -u

Preparation is finished. Now shutdown the VM and remove the old disk and make sure to boot from the new LVM disk.

Hope everything went well and the system comes up from the new disk

Leave a Comment