Skip to content

How to extend an LVM logical volume online

A filesystem mounted at /srv/data has filled up. It lives on an LVM logical volume, so you can give it more space while it stays mounted and in use. This guide grows the logical volume and the filesystem on it, and adds a new disk to the volume group first if the group has no free space left.

Before you begin

  • You need a shell with sudo on the machine.
  • The filesystem is ext4 or XFS on an LVM logical volume, and the lvm2 tools are installed (they are, if the volume already exists).
  • If the volume group is full, you need an unused disk or partition to add to it.

Back up first

Growing a logical volume and its filesystem online is routine, but a mistake such as typing the wrong device name in pvcreate destroys data. Make sure you have a current, tested backup of /srv/data and of anything on the disk you plan to add before you start.

Throughout this guide, replace these placeholders with your own values:

Placeholder Meaning Example
<VG> The volume group vg_data
<LV> The logical volume lv_data
<NEW_DISK> An empty disk or partition to add to the volume group /dev/vdc

Steps

  1. Find the logical volume behind the mount point, and how full the filesystem is:

    $ df -h /srv/data
    Filesystem                   Size  Used Avail Use% Mounted on
    /dev/mapper/vg_data-lv_data  974M  903M  4.0M 100% /srv/data
    $ findmnt -no SOURCE,FSTYPE /srv/data
    /dev/mapper/vg_data-lv_data ext4
    

    The source is shown as /dev/mapper/<VG>-<LV>, for example /dev/mapper/vg_data-lv_data. A hyphen inside a volume group or logical volume name appears doubled in this form.

  2. Check how much free space the volume group has:

    $ sudo vgs <VG>
      VG      #PV #LV #SN Attr    VSize VFree
      vg_data   1   1   0 wz--n-- 1.00g    0
    $ sudo lvs <VG>
      LV      VG      Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
      lv_data vg_data -wi-ao---- 1.00g
    

    The VFree column of vgs is the space you can still give to logical volumes. (Depending on the LVM version, the Attr column has six or seven characters; the difference doesn't matter here.) If it's large enough for the growth you want, go to step 4.

  3. If VFree is too small, add a new disk or partition to the volume group.

    List the block devices and identify the new one by its size and by having no partitions, filesystem or mount point:

    lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS
    

    Then confirm that <NEW_DISK> carries no signatures. wipefs without options only lists them; empty output means the device is unused:

    sudo wipefs <NEW_DISK>
    

    Warning

    pvcreate overwrites the start of the device. Check the device name twice: initialising the wrong disk destroys what is on it.

    Initialise the device as a physical volume and add it to the volume group:

    $ sudo pvcreate <NEW_DISK>
      Physical volume "/dev/vdc" successfully created.
    $ sudo vgextend <VG> <NEW_DISK>
      Volume group "vg_data" successfully extended
    $ sudo vgs <VG>
      VG      #PV #LV #SN Attr    VSize  VFree
      vg_data   2   1   0 wz--n-- <4.00g <3.00g
    

    VFree now includes the new device's capacity.

  4. Extend the logical volume and resize its filesystem in one command:

    $ sudo lvextend --resizefs -L +1G <VG>/<LV>
      File system ext4 found on vg_data/lv_data mounted at /srv/data.
      Size of logical volume vg_data/lv_data changed from 1.00 GiB (256 extents) to 2.00 GiB (512 extents).
      Extending file system ext4 to 2.00 GiB (2147483648 bytes) on vg_data/lv_data...
    resize2fs /dev/vg_data/lv_data
    Filesystem at /dev/vg_data/lv_data is mounted on /srv/data; on-line resizing required
    old_desc_blocks = 1, new_desc_blocks = 1
    The filesystem on /dev/vg_data/lv_data is now 524288 (4k) blocks long.
    
    resize2fs done
      Extended file system ext4 on vg_data/lv_data.
      Logical volume vg_data/lv_data successfully resized.
    

    --resizefs (short form -r) tells lvextend to grow the filesystem after the volume, using resize2fs for ext4 and xfs_growfs for XFS. Both work while the filesystem is mounted. -L +1G adds 1 GiB; use -L 20G to set an absolute size, or -l +100%FREE to use all the free space in the volume group.

Extend the volume and the filesystem separately

If you extended the logical volume without --resizefs, or a tool did it for you, the extra space isn't usable until you grow the filesystem as well. Extend the volume:

sudo lvextend -L +256M <VG>/<LV>

Then grow the filesystem to fill the volume, with the tool for its type.

For ext4, give resize2fs the device. Without a size argument, it grows the filesystem to the size of the volume:

sudo resize2fs /dev/<VG>/<LV>

For XFS, give xfs_growfs the mount point. XFS can only be grown while it's mounted:

sudo xfs_growfs /srv/data

In practice, space you add can't easily be taken back: XFS can't be shrunk, apart from removing unused space at the very end of the filesystem on recent kernels, and ext4 can be shrunk only while unmounted. Add space in modest steps rather than giving a volume more than it needs.

Verify

Check that the logical volume and the filesystem both show the new size, and that the filesystem has free space again:

$ sudo lvs <VG>/<LV>
  LV      VG      Attr       LSize Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  lv_data vg_data -wi-ao---- 2.00g
$ df -h /srv/data
Filesystem                   Size  Used Avail Use% Mounted on
/dev/mapper/vg_data-lv_data  2.0G  903M  971M  49% /srv/data

The LSize column of lvs and the Size column of df should agree, allowing for filesystem overhead.

Troubleshooting

Insufficient free space: … extents needed, but only … available
The volume group doesn't have the space you asked for. Check VFree with sudo vgs <VG> and either request less (for example -l +100%FREE) or add a physical volume as in step 3.
df still shows the old size after lvextend
The volume grew but the filesystem didn't, usually because --resizefs was left out. Grow the filesystem as described in Extend the volume and the filesystem separately.
Cannot use <NEW_DISK>: device is partitioned from pvcreate

The device has a partition table. Usually you gave the whole disk when you meant one of its partitions (for example /dev/vdc instead of /dev/vdc1), or picked the wrong disk. Check with lsblk and use the empty partition instead.

Less often, a device is rejected because an LVM filter in /etc/lvm/lvm.conf, or the devices file /etc/lvm/devices/system.devices (which RHEL 10 and its rebuilds create), doesn't include it.

WARNING: … signature detected on <NEW_DISK> … Wipe it? [y/n] from pvcreate

The device holds a filesystem, partition table or other signature, so it may contain data. Answer n unless you're certain the device is the one you meant and its contents are no longer needed. Run sudo wipefs <NEW_DISK> to see what is there.

Warning

sudo wipefs -a <NEW_DISK> erases every signature on the device, after which its previous contents are effectively lost. Run it only on a device you've identified beyond doubt, and whose data is backed up or no longer needed; then run pvcreate again.

The volume group isn't active after a reboot on Gentoo
With OpenRC, volume groups are activated at boot by the lvm service, which installing lvm2 doesn't add to any runlevel. Check with rc-update show boot, and add it with sudo rc-update add lvm boot if it's missing. Once the service is enabled, it activates the volume group with all its physical volumes, including the one you added.