Published Dec. 15, 2024, 11:07 a.m. by dwest
This topic was the inspiration for starting a tech blog.
Unless you’re a Systems Administrator or a Linux geek, you’ve probably never paid much attention to LVM. Standard partitioning is usually “good enough” for most systems. However, I’m often called in to help when someone runs out of disk space on a system that was configured with Logical Volume Manager (LVM). This is especially common on Red Hat based distributions.
Originally, I created a personal wiki page as a quick reference, both to guide newer users and to remind myself of specific command syntax when needed. One day, a former coworker reached out. At their new job, a server had run out of disk space on the root partition because log data filled it up. The previous administrator had configured the system using LVM, but none of the current administrators were familiar with it. They did not know how to fix it.
My former coworker had saved a copy of my LVM wiki page and used it to resolve the issue.
If a simple reference page could make that much of a difference at one company, maybe publishing a full blog post could help even more people.
Logical Volume Manager (LVM) is an abstraction layer that sits between your storage devices and filesystems. It provides features that traditional disk partitioning does not offer, including:
One of the biggest advantages of LVM is that it separates the filesystem from the physical layout of the storage beneath it.
With traditional partitioning, a filesystem is usually tied directly to a specific disk partition. If that partition fills up, changing its size may require moving partitions or taking the filesystem offline.
LVM adds several layers between the physical storage and filesystem. These layers allow storage to be added, removed and redistributed much more easily.
Depending on the filesystem and operation being performed, you can often expand storage without rebooting the system or even unmounting the filesystem. This can save significant downtime when a production system starts running out of space.
The tradeoff is complexity. LVM introduces several layers that need to be understood before the commands start making sense.
Fortunately, the overall design is fairly simple once you understand those layers.
LVM consists of three primary storage layers:
Physical Disks / Partitions
|
v
Physical Volumes
(PV)
|
v
Volume Group
(VG)
|
v
Logical Volumes
(LV)
|
v
Filesystem
The Physical Volume is the base storage layer used by LVM.
A Physical Volume can usually be created from either:
/dev/sdb/dev/sdb1You can think of a Physical Volume as a disk or partition that has been initialized for use by LVM.
For example:
pvcreate /dev/sdb1
Each disk or partition that you add to LVM becomes a Physical Volume.
A Volume Group combines one or more Physical Volumes into a shared storage pool.
For example:
/dev/sdb1 ─┐
├── vg01
/dev/sdc1 ─┘
Instead of worrying about which physical disk contains a particular filesystem, you allocate space from the Volume Group.
A Volume Group can be created with:
vgcreate vg01 /dev/sdb1
Additional Physical Volumes can later be added with:
vgextend vg01 /dev/sdc1
This ability to expand a storage pool across multiple physical devices is one of LVM’s most useful features.
Logical Volumes are created from the free space inside a Volume Group.
They behave much like traditional disk partitions and are usually where you create your filesystems.
For example:
lvcreate -L 25G -n home vg01
This creates a 25 GB Logical Volume named home inside the vg01 Volume Group.
The resulting device would normally appear as:
/dev/vg01/home
Unlike traditional partitions, Logical Volumes can be resized or moved within the storage provided by their Volume Group.
If your original storage layout turns out to be wrong, LVM gives you much more flexibility to correct it later.
Below are some of the commands you will commonly use when working with LVM. I highly recommend reading their man pages before performing unfamiliar operations.
fdisk - Manage disk partition tablesgdisk - Manage GPT partition tablesparted - Advanced disk partitioning and resizingpartprobe - Notify the kernel about partition table changespartx - Tell the kernel about partitions on a devicepvscan - Scan the system for Physical Volumespvdisplay - Display detailed Physical Volume informationpvs - Display summarized Physical Volume informationpvcreate - Initialize a disk or partition for LVMpvresize - Resize an existing Physical Volumevgscan - Scan the system for Volume Groupsvgdisplay - Display detailed Volume Group informationvgs - Display summarized Volume Group informationvgcreate - Create a Volume Groupvgextend - Add a Physical Volume to an existing Volume Grouplvscan - Scan the system for Logical Volumeslvdisplay - Display detailed Logical Volume informationlvs - Display summarized Logical Volume informationlvcreate - Create a Logical Volumelvextend - Extend a Logical Volumelvreduce - Reduce a Logical Volumeresize2fs - Resize ext2, ext3 and ext4 filesystemsxfs_growfs - Grow an XFS filesystemdf - Display filesystem usageMost LVM layouts are initially created during operating system installation. However, you may eventually need to add another disk or create additional storage manually.
For these examples, I will use /dev/sdb as the disk.
Your device names may look different depending on your hardware and operating system. NVMe storage might appear as /dev/nvme0n1 while virtual disks could use other device naming schemes.
Always verify the correct device before modifying a partition table.
You can inspect the available disks with:
lsblk
or:
fdisk -l
You can create the LVM Physical Volume directly on an entire disk, but many environments still create a partition first.
There are several tools available.
gdiskgdisk is designed for GPT partition tables.
Start it with:
gdisk /dev/sdb
Create a new GPT partition table if required:
o
Create a new partition:
n
When prompted for the partition type, use the Linux LVM type:
Hex code or GUID (L to show codes, Enter = 8300): 8e00
Write the changes:
w
Afterward, your new partition might appear as:
/dev/sdb1
fdiskModern versions of fdisk can work with both MBR and GPT partition tables, although older versions were primarily associated with MBR.
Start it with:
fdisk /dev/sdb
Create a new partition:
n
Follow the prompts to choose the partition number, starting sector and ending sector.
If needed, change the partition type to Linux LVM:
t
On an MBR partition table the Linux LVM type is traditionally:
8e
Write the changes:
w
partedYou can also create the partition using parted.
Create a GPT partition table:
parted /dev/sdb -- mklabel gpt
Create a partition using the entire disk:
parted /dev/sdb -- mkpart primary 0% 100%
Depending on the environment, you may also want to set the LVM flag:
parted /dev/sdb -- set 1 lvm on
Initialize the partition as a Physical Volume:
pvcreate /dev/sdb1
Verify it:
pvdisplay /dev/sdb1
You can also use the shorter summary command:
pvs
Create a Volume Group named vg01:
vgcreate vg01 /dev/sdb1
Verify it:
vgdisplay vg01
or:
vgs
You can create a Logical Volume using either a specific size or all available space.
To create a 25 GB Logical Volume:
lvcreate -L 25G -n home vg01
To use all available space:
lvcreate -l 100%FREE -n home vg01
Verify the Logical Volume:
lvdisplay /dev/vg01/home
or:
lvs
For an ext4 filesystem:
mkfs.ext4 /dev/vg01/home
The equivalent generic syntax would be:
mkfs -t ext4 /dev/vg01/home
For XFS:
mkfs.xfs /dev/vg01/home
Some operating systems may require additional packages before tools such as mkfs.xfs or xfs_growfs are available.
This is probably the LVM operation I use most often.
A filesystem fills up, someone expands the virtual disk in VMware, KVM, Hyper-V or another virtualization platform and now Linux needs to make use of the additional space.
Before changing anything, determine where the free space currently exists.
The storage path looks like this:
Disk
|
Partition
|
Physical Volume
|
Volume Group
|
Logical Volume
|
Filesystem
If you increase the size of the virtual disk, that does not automatically increase every layer underneath it.
You may need to expand the partition, Physical Volume, Logical Volume and filesystem individually.
Start by determining which filesystem is running out of space:
df -Th
You might see something like:
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/vg01-root ext4 40G 38G 2.0G 95% /
You should also identify the underlying storage:
lsblk
Display the Physical Volumes:
pvscan
For more detail:
pvdisplay
A concise view is usually available with:
pvs
Display Volume Group information:
vgdisplay
or:
vgs
Pay particular attention to the amount of free space available in the Volume Group.
If the Volume Group already contains free space, you may be able to skip directly to extending the Logical Volume.
Display Logical Volumes:
lvdisplay
or:
lvs
Make note of the LV path.
For example:
/dev/vg01/root
There are several ways to extend an LV.
lvextend -L 50G /dev/vg01/root
This changes the total size of the Logical Volume to 50 GB.
lvextend -L +12G /dev/vg01/root
This adds 12 GB to the existing Logical Volume.
The + is important.
These two commands do different things:
lvextend -L 50G /dev/vg01/root
lvextend -L +50G /dev/vg01/root
The first sets the total size to 50 GB while the second adds another 50 GB.
To consume all free space in the Volume Group:
lvextend -l +100%FREE /dev/vg01/root
You can also resize the filesystem automatically with the -r option:
lvextend -r -l +100%FREE /dev/vg01/root
For most routine expansion operations, this is one of the most convenient commands.
Note: The
-roption tells LVM to resize the filesystem after extending the Logical Volume. If the filesystem is supported by the underlying resize tooling, you can usually skip the manual filesystem resize step.
If you did not use lvextend -r, the Logical Volume can be larger while the filesystem remains its original size.
The filesystem must then be expanded separately.
For ext filesystems:
resize2fs /dev/vg01/root
By default, resize2fs expands the filesystem to use the available space in the Logical Volume.
XFS uses a different tool:
xfs_growfs /
The argument to xfs_growfs is normally the mounted filesystem rather than the Logical Volume device.
For example, if /dev/vg01/data is mounted at /srv/data:
xfs_growfs /srv/data
To grow it to all available space:
xfs_growfs -d /srv/data
Important: XFS can be expanded but cannot currently be shrunk.
A very common scenario looks like this:
Virtual Disk
|
v
Partition
|
v
Physical Volume
|
v
Volume Group
|
v
Logical Volume
|
v
Filesystem
You increase the virtual disk size in your hypervisor, but the filesystem still reports the old size.
This is expected because the additional space still needs to travel through the layers.
For example:
Hypervisor disk: 100 GB -> 150 GB
Partition: still 100 GB
Physical Volume: still 100 GB
Logical Volume: still 100 GB
Filesystem: still 100 GB
The exact procedure depends on whether LVM uses the full disk or a partition.
Increase the size of the disk in your virtualization platform.
This could be:
Sometimes Linux detects the increased size automatically.
Check with:
lsblk
You can also inspect the disk with:
fdisk -l /dev/sdb
If the kernel does not see the updated size, you may need to rescan the device or storage bus.
The exact command depends on the storage driver and platform.
If the Physical Volume resides inside a partition, expand that partition first.
For example:
parted /dev/sdb print free
Then resize partition 1 to the end of the disk:
parted -s /dev/sdb "resizepart 1 100%"
Ask the kernel to reread the partition table:
partprobe /dev/sdb
You can also inspect the partition with:
partx --show /dev/sdb
Note: Partition table changes are usually detected without a reboot on modern Linux systems. However, some storage configurations may prevent the kernel from rereading a partition table that is currently in use. If the new partition size does not appear, a reboot may still be required.
Once /dev/sdb1 has grown, expand the LVM Physical Volume:
pvresize /dev/sdb1
Verify the new free space:
pvs
and:
vgs
Use all newly available Volume Group space:
lvextend -l +100%FREE /dev/vg01/root
Or resize both the LV and filesystem at once:
lvextend -r -l +100%FREE /dev/vg01/root
Check the filesystem:
df -Th
Also confirm the LVM layers:
pvs
vgs
lvs
There is another way to expand an LVM filesystem without changing the size of the existing disk.
You can add an entirely new disk to the system.
For example:
/dev/sda
|
└── Existing PV ─┐
├── vg01 ── root LV
/dev/sdb │
|
└── New PV ──────┘
This can be useful when resizing an existing virtual disk is difficult or when you want to add capacity from another storage device.
However, there is an important tradeoff.
Once the Logical Volume spans both disks, both disks become part of the filesystem’s storage path. Removing either disk without properly migrating the data can destroy the Logical Volume.
Add the disk through your virtualization platform or storage controller.
Identify it:
lsblk
For these examples, assume the new disk is:
/dev/sdb
Using gdisk:
gdisk /dev/sdb
Create a partition and assign it the Linux LVM type.
The resulting partition might be:
/dev/sdb1
pvcreate /dev/sdb1
Determine your Volume Group:
vgs
Then add the new Physical Volume:
vgextend vg01 /dev/sdb1
Verify:
pvs
vgs
Use the new free space:
lvextend -l +100%FREE /dev/vg01/root
Or resize the filesystem at the same time:
lvextend -r -l +100%FREE /dev/vg01/root
df -Th
Warning: Do not disconnect or delete a disk that contains an active Physical Volume. If a Logical Volume has extents stored on that disk, removing it can make the entire filesystem unusable.
Growing storage is usually straightforward.
Shrinking it is not.
There are two separate operations involved:
The filesystem must be reduced before the Logical Volume.
If you shrink the Logical Volume first, data near the end of the filesystem can be permanently destroyed.
Not every filesystem supports shrinking.
For example:
Do not attempt to shrink an XFS filesystem with lvreduce.
First, unmount the filesystem if required:
umount /dev/vg01/home
Check it:
e2fsck -f /dev/vg01/home
Shrink the filesystem:
resize2fs /dev/vg01/home 40G
Then shrink the Logical Volume:
lvreduce -L 40G /dev/vg01/home
Alternatively, you can reduce it by a specific amount:
lvreduce -L -12G /dev/vg01/home
Remount the filesystem afterward.
Warning: Never reduce a Logical Volume below the current size of the filesystem stored inside it. Doing so can corrupt the filesystem and cause permanent data loss.
Before shrinking storage, make sure you have a current backup.
Suppose your root filesystem looks like this:
df -Th /
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/vg01-root ext4 40G 39G 1.0G 98% /
Your virtualization administrator expands the disk by 20 GB.
After resizing the partition and Physical Volume, vgs shows:
VG #PV #LV #SN Attr VSize VFree
vg01 1 2 0 wz--n- 60.00g 20.00g
You can now expand the root filesystem with:
lvextend -r -l +100%FREE /dev/vg01/root
Then verify:
df -Th /
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/vg01-root ext4 60G 39G 21G 66% /
That is the kind of situation where LVM really earns its keep.
Without LVM, recovering that additional storage can require significantly more work.
LVM can look unnecessarily complicated when you first encounter it.
You start with a disk, add a partition, turn that partition into a Physical Volume, place it into a Volume Group and then create a Logical Volume before finally creating a filesystem.
That seems like a lot of layers just to store files.
The benefit becomes clear when your storage requirements change.
Instead of treating disk partitions as permanent boundaries, LVM lets you treat storage as a pool that can be redistributed as your systems evolve.
If /var needs more space, you can give it more space. If a virtual disk gets expanded, LVM can make use of it. If one disk is not enough, another Physical Volume can be added to the pool.
More importantly, many of these operations can be performed without taking the system offline.
That flexibility is why LVM continues to be so common on Linux servers and why it is worth understanding even if you do not use it every day.
After all, this whole blog started because one copied wiki page helped someone rescue a server.
Hopefully this version can do the same for someone else.
Much of the original version of this guide was compiled using the following sources:
The FreeIPA Master Class - Part 9
The FreeIPA Master Class - Part 8
The FreeIPA Master Class - Part 7
The FreeIPA Master Class - Part 6
There are no comments.