What is the Logical Volume Manager (LVM) and how to use it?

LVM stands for Logical Volume Manager, it is a tool for file system and disk management on Linux. It can work in different ways like allocating whole devices, but the general usage is putting the LVM on a partition. One of the most common System [Engineer|Administrator] and DevOps interview topic is creating and resizing LVM volumes.

Using LVM gives us flexibility to extend, shrink or snapshot the filesystem. It is possible to mirror or stripe disks or partitions with it. With the snapshotting feature we can create filesystem snapshots. We can add new storage devices easily, and extend the volume of an existing setup. It is also possible to encrypt LVM volumes.

View my video about presenting a disk extension on a virtual Debian Linux!

Physical Volume

Physical Volumes are the storage devices or partitions attached to the system and handled by the LVM. For example the /dev/sdb device or its /dev/sdb1 is a partition.

Volume Group

A Volume Group consists of one or more Physical Volumes to allocate space from them. We can handle a Volume Group as a whole.

Logical Volume

The Logical Volumes are the virtual space allocations from Volume Groups. We can consider them as virtual partitions to create file system on them.

Basic operations with LVM

We can list our attached storage devices with the fdisk command. The following output is from a machine that has already installed LVM. It is the lvm2 package on Debian Linux.

root@debtop:~# fdisk -l

Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 sectors
Disk model: VMware Virtual S
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: dos
Disk identifier: 0xdc94f4be

Device     Boot   Start      End  Sectors  Size Id Type
/dev/sda1  *       2048   999423   997376  487M 83 Linux
/dev/sda2       1001470 62912511 61911042 29.5G  5 Extended
/dev/sda5       1001472 62912511 61911040 29.5G 8e Linux LVM

Disk /dev/mapper/debtop--vg-root: 10.14 GiB, 10888413184 bytes, 21266432 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

Disk /dev/mapper/debtop--vg-swap_1: 976 MiB, 1023410176 bytes, 1998848 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

Disk /dev/mapper/debtop--vg-home: 18.43 GiB, 19784531968 bytes, 38641664 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

From the output of the above command we can see that there is only one block device attached to the system. It is on /dev/sda and its size is exactly 30 GB.

There are three partitions on this device, sda[1,2,5]. The sda1 partition is flagged as boot partition, from here we can safely assume that it contains our /boot filesystem. Linux cannot boot from an LVM partition (the LVM is still not available at this time of the boot to read from). The sda2 partition is an extended type, it means it holds one or more further partitions, in this case it is the sda5. We see that this is an LVM partition, its size is 29.5 GB. Furthermore we can assume that the /dev/sda5 is a Physical Volume for LVM and it is added to the debtop-vg volume group.

List the Physical Volumes of the system (pvdisplay)

We can use the pvdisplay command to list the the Physical Volumes.

root@debtop:~# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda5
  VG Name               debtop-vg
  PV Size               29.52 GiB / not usable 2.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              7557
  Free PE               0
  Allocated PE          7557
  PV UUID               MTO8uI-gRWH-Kc2T-skB0-QR6j-W7mB-ad7xrw

The command output gives us an overall image about the attached volumes to the system. We assumed well that /dev/sda5 is a Physical Volume of the system containing a Volume Group called debtop-vg. We can see the maximum space we can allocate from this PV on the third line.

Investigate the Volume Groups (vgdisplay)

We can use the vgdisplay command to list the Volume Groups.

root@debtop:~# vgdisplay 
  --- Volume group ---
  VG Name               debtop-vg
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  4
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                3
  Open LV               3
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               <29.52 GiB
  PE Size               4.00 MiB
  Total PE              7557
  Alloc PE / Size       7557 / <29.52 GiB
  Free  PE / Size       0 / 0   
  VG UUID               8X1Vdg-OEzV-ekRJ-4DRa-ycFJ-0wmp-soAUia

Our assumption regarding the debtop-vg Volume Group was correct. We can see from the output that currently this VG has three Logical Volumes (LV).

Logical Volumes of the system (lvdisplay)

The Logical Volumes can be displayed by the lvdisplay command.

root@debtop:~# lvdisplay 
  --- Logical volume ---
  LV Path                /dev/debtop-vg/root
  LV Name                root
  VG Name                debtop-vg
  LV UUID                zkXB5m-7i1r-BOLd-YFcS-q1Gi-qt3J-ffuz9K
  LV Write Access        read/write
  LV Creation host, time debtop, 2022-12-19 07:51:04 +0100
  LV Status              available
  # open                 1
  LV Size                10.14 GiB
  Current LE             2596
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           254:0
   
  --- Logical volume ---
  LV Path                /dev/debtop-vg/swap_1
  LV Name                swap_1
  VG Name                debtop-vg
  LV UUID                iDl16X-TfL6-2m3V-iTLA-HX1d-OgHr-A2Q6BS
  LV Write Access        read/write
  LV Creation host, time debtop, 2022-12-19 07:51:05 +0100
  LV Status              available
  # open                 2
  LV Size                976.00 MiB
  Current LE             244
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           254:1
   
  --- Logical volume ---
  LV Path                /dev/debtop-vg/home
  LV Name                home
  VG Name                debtop-vg
  LV UUID                f9s1fS-EffG-6g1e-pfhf-P67g-ba0T-Nr4Pp5
  LV Write Access        read/write
  LV Creation host, time debtop, 2022-12-19 07:51:05 +0100
  LV Status              available
  # open                 1
  LV Size                <18.43 GiB
  Current LE             4717
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           254:2

Excuse me for the long text, but from the output we can see the three LVs of the system with their name, size and other data.

Hands-on lab practice

Let’s add a new disk to the system and extend our /home with it!

Preparing the disk partition

I added a new 10 GB storage device to the system. It must show up in the output of the fdisk command now.

root@debtop:~# fdisk -l
Disk /dev/sdb: 10 GiB, 10737418240 bytes, 20971520 sectors
Disk model: VMware Virtual S
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

I truncated the output of the command, but we can see that the new storage device is on /dev/sdb so we can start preparing the partition on it.

We are going to use the entire size of the disk for LVM. Using the fdisk /dev/sdb command we can create a Linux LVM partition type. Using fdisk is out of the scope of this article, but the disk settings must look like the followings. It is worth to mention that other partitioning tools are also fine for creating this setup.

root@debtop:~# fdisk -l
Disk /dev/sdb: 10 GiB, 10737418240 bytes, 20971520 sectors
Disk model: VMware Virtual S
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: dos
Disk identifier: 0x32d3237f

Device     Boot Start      End  Sectors Size Id Type
/dev/sdb1        2048 20971519 20969472  10G 8e Linux LVM

As we can see the partition is ready for LVM: /dev/sdb1 2048 20971519 20969472 10G 8e Linux LVM

Adding the storage as Physical Volume

We will add the partition as Physical Volume to the LVM with the pvceate command. Note that pvcreate can work on both partition and device. We use a partition here.

root@debtop:~# pvcreate /dev/sdb1
  Physical volume "/dev/sdb1" successfully created.

Now it is part of our PVs.

root@debtop:~# pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda5
  VG Name               debtop-vg
  PV Size               29.52 GiB / not usable 2.00 MiB
  Allocatable           yes (but full)
  PE Size               4.00 MiB
  Total PE              7557
  Free PE               0
  Allocated PE          7557
  PV UUID               MTO8uI-gRWH-Kc2T-skB0-QR6j-W7mB-ad7xrw

Adding the PV to our Volume Group

Let’s extend our VG with this PV.

root@debtop:~# vgextend debtop-vg /dev/sdb1
  Volume group "debtop-vg" successfully extended
root@debtop:~# vgs
  VG        #PV #LV #SN Attr   VSize   VFree  
  debtop-vg   2   3   0 wz--n- <39.52g <10.00g

We used the vgextend command here, added the /dev/sdb1 to the debtop-vg Volume Group. Note that I used the vgs command to list the VGs here.

With the vgdisplay command we can check the unallocated space in the VG.

root@debtop:~# vgdisplay 
  --- Volume group ---
  VG Name               debtop-vg
  System ID             
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  5
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                3
  Open LV               3
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               <39.52 GiB
  PE Size               4.00 MiB
  Total PE              10116
  Alloc PE / Size       7557 / <29.52 GiB
  Free  PE / Size       2559 / <10.00 GiB
  VG UUID               8X1Vdg-OEzV-ekRJ-4DRa-ycFJ-0wmp-soAUia

Let’s extend our home Logical Volume! We are going to extend the /home with the new space.

--- Logical volume ---
  LV Path                /dev/debtop-vg/home
  LV Name                home
  VG Name                debtop-vg

Extending the LVM Logical Volume

Now we have the free space in our VG to extend our LV with it. Let’s use the lvextend command and add the maximum free space to the home filesystem. After reading the manual page carefully we can put together our command.

root@debtop:~# lvextend -l +100%FREE /dev/debtop-vg/home
  Size of logical volume debtop-vg/home changed from <18.43 GiB (4717 extents) to 28.42 GiB (7276 extents).
  Logical volume debtop-vg/home successfully resized.

We can see from the output that the extension was successful. We can double-check the extension of the LV now.

root@debtop:~# lvs
  LV     VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  home   debtop-vg -wi-ao----  28.42g                                                    
  root   debtop-vg -wi-ao----  10.14g                                                    
  swap_1 debtop-vg -wi-ao---- 976.00m

It’s time to handle the file system extension.

Extending the ext4 filesystem on the LV

We have stretched the free space under the filesystem, but still a step is missing. We have to stretch the filesystem too. The method and command depend on the filesystem type.

On the Debtop machine the /home is on ext4, thus I will use resize2fs to do this operation.

root@debtop:~# resize2fs /dev/debtop-vg/home
resize2fs 1.46.2 (28-Feb-2021)
Filesystem at /dev/debtop-vg/home is mounted on /home; on-line resizing required
old_desc_blocks = 3, new_desc_blocks = 4
The filesystem on /dev/debtop-vg/home is now 7450624 (4k) blocks long.

According to the command output our operation was successful and we extended the filesystem with the maximum available free space.

Let’s double check it with the df command!

root@debtop:~# df -h
Filesystem                   Size  Used Avail Use% Mounted on
udev                         1.9G     0  1.9G   0% /dev
tmpfs                        390M  1.2M  389M   1% /run
/dev/mapper/debtop--vg-root  9.9G  4.1G  5.4G  44% /
tmpfs                        2.0G     0  2.0G   0% /dev/shm
tmpfs                        5.0M  4.0K  5.0M   1% /run/lock
/dev/sdb1                    470M   99M  347M  23% /boot
/dev/mapper/debtop--vg-home   28G   63M   27G   1% /home
tmpfs                        390M  860K  389M   1% /run/user/1000

Our /home got the +10 Gigabytes free space now. We have managed to add a new disk and extend a Logical Volume with it.

Summary

With this longer article we have just scratched the surface of the LVM. There are more ways to use this versatile system and we just dipped our pinky in it.

We started the whole work with adding a disk to the system where we already had an LVM configuration. With the fdisk tool we created a new partition on the fresh disk marked as Linux LVM.

Then we added the partition as a Physical Volume to our LVM, extended our already present Volume Group with it.

At this point all was set to extend the Logical Volume with the free space on the system.

After extending the LV we stretched the ext4 filesystem too to use all the new free space. The filesystem extension can help online, when it is mounted. Please note that shrinking a filesystem cannot happen online, and it is a different process.

Please use this write up on your own risk!

If you have a comment or other opinion, visit Tom’s IT Cafe Discord Server and share it!

Leave a comment