CertGrid CertGrid
Hands-on Lab·CompTIA Linux+

LVM, from physical volume to a filesystem that grows

Domain 1 names LVM and this guide builds the whole stack: two devices into physical volumes, a volume group, a logical volume with a filesystem on it - then grows it while it is mounted, runs out of space on purpose, adds the second device, and spans the volume across both, with the data checksummed before and after.

System Management Guide 17 of 28 Intermediate

One host. The physical volumes are loop devices made from files, so every command works on a machine with no spare disk - the commands are identical on real ones.
Server NameIP AddressOSRolesCPURAMHDD
LPLUS-A01192.168.0.73Ubuntu 26.04 LTSDebian-family host - apt, ufw, netplan, AppArmor2 Core4 GB50 GB

This guide includes

Use this when a filesystem is filling and downtime is not an option. This matters because growing a volume and growing the filesystem inside it are two separate operations - doing only the first leaves df reporting the old size and looks like the resize failed.

Before you start

  1. Two devices to build on

    What the machine already has, before anything is added.

    bash Example session
    for n in 1 2; do sudo truncate -s 512M /var/tmp/lvm$n.img; done; for n in 1 2; do sudo losetup -f --show /var/tmp/lvm$n.img; done | sudo tee /tmp/lvm.devs; lsblk $(head -1 /tmp/lvm.devs) $(tail -1 /tmp/lvm.devs) -o NAME,SIZE,TYPE/dev/loop0/dev/loop1NAME   SIZE TYPEloop0  512M looploop1  512M loopsudo pvs; sudo vgs; sudo lvs; echo "--- exit $? : nothing yet, and the commands still answer"  PV         VG        Fmt  Attr PSize   PFree  /dev/sda3  ubuntu-vg lvm2 a--  <48.00g    0  VG        #PV #LV #SN Attr   VSize   VFree  ubuntu-vg   1   1   0 wz--n- <48.00g    0  LV        VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert  ubuntu-lv ubuntu-vg -wi-ao---- <48.00g--- exit 0 : nothing yet, and the commands still answer

    Expected result/dev/loop0 and /dev/loop1 at 512M each - and the existing ubuntu-vg on /dev/sda3, which the three reporting commands answer for even before anything new exists.

    Success conditionYou can read a machine's LVM layout before changing it.

  2. Physical volume, then volume group

    Two layers before anything is usable, and what each costs.

    bash Example session
    sudo pvcreate $(head -1 /tmp/lvm.devs) && sudo pvs -o pv_name,pv_size,pv_free,vg_name  Physical volume "/dev/loop0" successfully created.  PV         PSize   PFree   VG  /dev/loop0 512.00m 512.00m  /dev/sda3  <48.00g      0  ubuntu-vgsudo vgcreate lplusvg $(head -1 /tmp/lvm.devs) && sudo vgs -o vg_name,pv_count,vg_size,vg_free,vg_extent_size  Volume group "lplusvg" successfully created  VG        #PV VSize   VFree   Ext  lplusvg     1 508.00m 508.00m 4.00m  ubuntu-vg   1 <48.00g      0  4.00m

    Expected resultPhysical volume "/dev/loop0" successfully created with 512.00m free - then a volume group of 508.00m with an extent size of 4.00m.

    Success conditionYou can build the two layers under a logical volume and read their sizes.

  3. A logical volume, a filesystem, a mount

    The layer you can finally write to.

    bash Example session
    sudo lvcreate -L 200M -n data lplusvg && sudo lvs -o lv_name,vg_name,lv_size,lv_path  Logical volume "data" created.  LV        VG        LSize   Path  data      lplusvg   200.00m /dev/lplusvg/data  ubuntu-lv ubuntu-vg <48.00g /dev/ubuntu-vg/ubuntu-lvsudo mkfs.ext4 -q /dev/lplusvg/data && sudo mkdir -p /mnt/lplus && sudo mount /dev/lplusvg/data /mnt/lplus && df -h /mnt/lplus | tail -1; sudo dd if=/dev/urandom of=/mnt/lplus/payload.bin bs=1M count=60 status=none && sudo md5sum /mnt/lplus/payload.bin | cut -c1-32/dev/mapper/lplusvg-data  172M  152K  158M   1% /mnt/lpluseb2af2b557e9bc6b4cddaab2058d7c2a

    Expected resultA 200.00m volume at /dev/lplusvg/data, mounted as 172M with 158M available - and 60 MB of random data written, with an md5 beginning eb2af2b5.

    Success conditionYou have a filesystem on LVM with data on it you can verify later.

  4. Growing it while it stays mounted

    The volume grows. The filesystem does not.

    bash Example session
    sudo lvextend -L +150M /dev/lplusvg/data && df -h /mnt/lplus | tail -1; echo "--- the volume grew and the filesystem did not"  Rounding size to boundary between physical extents: 152.00 MiB.  Size of logical volume lplusvg/data changed from 200.00 MiB (50 extents) to 352.00 MiB (88 extents).  Logical volume lplusvg/data successfully resized./dev/mapper/lplusvg-data  172M   61M   98M  39% /mnt/lplus--- the volume grew and the filesystem did notsudo resize2fs /dev/lplusvg/data 2>&1 | tail -1; df -h /mnt/lplus | tail -1; sudo md5sum /mnt/lplus/payload.bin | cut -c1-32; echo "--- and the data is unchanged" /dev/mapper/lplusvg-data  318M   61M  240M  21% /mnt/lpluseb2af2b557e9bc6b4cddaab2058d7c2a--- and the data is unchanged

    Expected resultRounding size to boundary between physical extents: 152.00 MiB, the volume going from 50 to 88 extents - and df still reporting 172M. After resize2fs, 318M, with the same md5.

    Success conditionYou can grow a mounted filesystem and prove the data survived.

  5. Running out of room, and adding the second device

    A refusal, then a bigger pool, then one command that does both jobs.

    bash Example session
    sudo lvextend -L +400M /dev/lplusvg/data 2>&1 | tail -1; echo "--- exit $? : the group has no more extents"  Insufficient free space: 100 extents needed, but only 39 available--- exit 0 : the group has no more extentssudo pvcreate $(tail -1 /tmp/lvm.devs) > /dev/null && sudo vgextend lplusvg $(tail -1 /tmp/lvm.devs) && sudo vgs -o vg_name,pv_count,vg_size,vg_free  Volume group "lplusvg" successfully extended  VG        #PV VSize    VFree  lplusvg     2 1016.00m 664.00m  ubuntu-vg   1  <48.00g      0sudo lvextend -r -L +400M /dev/lplusvg/data 2>&1 | tail -2; df -h /mnt/lplus | tail -1; echo "--- -r resized the filesystem in the same command"  Extended file system ext4 on lplusvg/data.  Logical volume lplusvg/data successfully resized./dev/mapper/lplusvg-data  699M   61M  610M   9% /mnt/lplus--- -r resized the filesystem in the same commandsudo lvs -o lv_name,lv_size,seg_count,devices --noheadings; echo "--- and the volume now spans both devices"  data      752.00m    2 /dev/loop0(0)  data      752.00m    2 /dev/loop1(0)  ubuntu-lv <48.00g    1 /dev/sda3(0)--- and the volume now spans both devices

    Expected resultInsufficient free space: 100 extents needed, but only 39 available - then a group of 2 PVs and 1016.00m, Extended file system ext4 and 699M mounted, with the volume showing 2 segments across loop0 and loop1.

    Success conditionYou can extend a volume group and let a volume span more than one device.

  6. Putting the machine back

    The three layers removed in the order they were built, reversed.

    bash Example session
    sudo umount /mnt/lplus && sudo lvremove -f lplusvg > /dev/null && sudo vgremove -f lplusvg > /dev/null && sudo pvremove -f $(head -1 /tmp/lvm.devs) $(tail -1 /tmp/lvm.devs) > /dev/null; sudo pvs; sudo vgs; echo "--- exit $? : no physical volumes, no groups"  PV         VG        Fmt  Attr PSize   PFree  /dev/sda3  ubuntu-vg lvm2 a--  <48.00g    0  VG        #PV #LV #SN Attr   VSize   VFree  ubuntu-vg   1   1   0 wz--n- <48.00g    0--- exit 0 : no physical volumes, no groupsfor d in $(cat /tmp/lvm.devs); do sudo losetup -d $d; done; sudo rm -f /var/tmp/lvm1.img /var/tmp/lvm2.img /tmp/lvm.devs; sudo rmdir /mnt/lplus; losetup -a | wc -l; echo "loop devices left"0loop devices left

    Expected resultOnly ubuntu-vg on /dev/sda3 left in pvs and vgs, and 0 loop devices.

    Success conditionThe machine's own LVM layout is exactly as it was.

Troubleshooting

Official sources