Linux LVM
Introduction
LVM, or Logical Volume Manager, provides a flexible way to manage storage on Linux systems.
Traditional disk management often connects a filesystem directly to a partition:
Disk
│
▼
Partition
│
▼
Filesystem
│
▼
Mount Point
LVM introduces additional abstraction layers:
Disk
│
▼
Partition
│
▼
Physical Volume (PV)
│
▼
Volume Group (VG)
│
▼
Logical Volume (LV)
│
▼
Filesystem
│
▼
Mount Point
This separation allows storage to be managed more flexibly.
For example, a Volume Group can combine storage from multiple Physical Volumes and provide that storage to multiple Logical Volumes.
Why Use LVM?
LVM is useful when storage needs to be managed independently from the physical disk layout.
Some common use cases include:
- servers
- virtualization hosts
- databases
- application servers
- backup systems
- container hosts
- infrastructure environments
One important benefit is that logical volumes do not have to map directly to physical disk partitions.
For example:
/dev/sdb1 ──┐
├── Volume Group
/dev/sdc1 ──┘
│
├── LV: database
├── LV: docker
└── LV: backup
The physical storage and logical storage layout are therefore separated.
The LVM Layers
LVM consists of three main concepts:
- Physical Volume (PV)
- Volume Group (VG)
- Logical Volume (LV)
A filesystem is then created on the Logical Volume.
The complete model is:
Physical Storage
│
▼
Physical Volume
│
▼
Volume Group
│
▼
Logical Volume
│
▼
Filesystem
│
▼
Mount Point
Understanding these layers is more important than memorizing the commands.
Physical Volume
A Physical Volume (PV) is storage initialized for use by LVM.
A Physical Volume can be created from a partition:
sudo pvcreate /dev/sdb1
After running the command, verify it:
sudo pvs
Example:
PV VG Fmt Attr PSize PFree
/dev/sdb1 lvm2 a-- 931.00g 931.00g
The partition is now an LVM Physical Volume.
The storage hierarchy is:
/dev/sdb
└── /dev/sdb1
└── Physical Volume
A Physical Volume can also be created directly on a disk but sometimes this is causing troubles so better create it on partition:
sudo pvcreate /dev/sdb
However, using a dedicated partition makes the intended storage layout explicit and is a common approach.
You can also use command:
sudo pvdisplay
- to see more details
If from some reason you do not see all Physical Volumes you can try command for scanning them:
sudo pvscan
Example:
[tomik@localhost ~]$ sudo pvscan
PV /dev/nvme0n1p2 VG almalinux lvm2 [<19.00 GiB / 0 free]
PV /dev/sda2 lvm2 [1023.00 MiB]
PV /dev/sdb2 lvm2 [1023.00 MiB]
PV /dev/sdc2 lvm2 [1023.00 MiB]
Total: 4 [21.99 GiB] / in use: 1 [<19.00 GiB] / in no VG: 3 [<3.00 GiB]
Volume Group
A Volume Group (VG) is a pool of storage made from one or more Physical Volumes.
Create a Volume Group:
sudo vgcreate vg_name device
sudo vgcreate vg_data /dev/sdb1
Verify it:
sudo vgs
Example:
VG #PV #LV #SN Attr VSize VFree
vg_data 1 0 0 wz--n- 931.00g 931.00g
The hierarchy is now:
/dev/sdb
└── /dev/sdb1
└── PV
└── VG: vg_data
Multiple Physical Volumes in One Volume Group
One of the useful properties of LVM is that a Volume Group can contain multiple Physical Volumes.
For example:
/dev/sdb1 ──┐
├── VG: vg_data
/dev/sdc1 ──┘
The Volume Group then provides a larger pool of storage.
The exact allocation and redundancy characteristics depend on how Logical Volumes are created.
LVM itself should not automatically be considered a RAID solution.
RAID is covered separately in the storage documentation.
Example:
[tomik@localhost ~]$ sudo vgcreate testgroup /dev/sda2 /dev/sdb2 /dev/sdc2
[sudo] password for tomik:
Volume group "testgroup" successfully created
[tomik@localhost ~]$
Now we can see our physical volumes are associtated to Volume Group
[tomik@localhost ~]$ sudo pvs
PV VG Fmt Attr PSize PFree
/dev/nvme0n1p2 almalinux lvm2 a-- <19.00g 0
/dev/sda2 testgroup lvm2 a-- 1020.00m 1020.00m
/dev/sdb2 testgroup lvm2 a-- 1020.00m 1020.00m
/dev/sdc2 testgroup lvm2 a-- 1020.00m 1020.00m
[tomik@localhost ~]$
You can also check it with other commands:
[tomik@localhost ~]$ sudo vgs
VG #PV #LV #SN Attr VSize VFree
almalinux 1 2 0 wz--n- <19.00g 0
testgroup 3 0 0 wz--n- <2.99g <2.99g
[tomik@localhost ~]$ sudo vgdisplay
--- Volume group ---
VG Name testgroup
System ID
Format lvm2
Metadata Areas 3
Metadata Sequence No 1
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 0
Open LV 0
Max PV 0
Cur PV 3
Act PV 3
VG Size <2.99 GiB
PE Size 4.00 MiB
Total PE 765
Alloc PE / Size 0 / 0
Free PE / Size 765 / <2.99 GiB
VG UUID O89qmS-Cddt-GOug-oVB8-pba0-I8H4-iPbsEr
--- Volume group ---
VG Name almalinux
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 3
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 2
Open LV 2
Max PV 0
Cur PV 1
Act PV 1
VG Size <19.00 GiB
PE Size 4.00 MiB
Total PE 4863
Alloc PE / Size 4863 / <19.00 GiB
Free PE / Size 0 / 0
VG UUID NiPtMp-Km2e-W5dS-erOR-gOit-v7GE-iCWSFe
[tomik@localhost ~]$ sudo vgscan
Found volume group "testgroup" using metadata type lvm2
Found volume group "almalinux" using metadata type lvm2
[tomik@localhost ~]$
Logical Volume
A Logical Volume (LV) is a virtual block device created inside a Volume Group.
For example:
sudo lvcreate -l 100%FREE -n lv_data vg_data
This creates:
/dev/vg_data/lv_data
Verify it:
sudo lvs
Example:
LV VG Attr LSize
lv_data vg_data -wi-a----- 931.00g
The complete LVM structure is now:
/dev/sdb
└── /dev/sdb1
└── PV
└── VG: vg_data
└── LV: lv_data
Logical Volume Size
Instead of using all available space, you can create a Logical Volume with a specific size.
For example:
sudo lvcreate -L 100G -n lv_data vg_data
This creates a 100 GB Logical Volume.
You can then use the remaining space for other Logical Volumes.
For example:
sudo lvcreate -L 100G -n lv_database vg_data
sudo lvcreate -L 200G -n lv_docker vg_data
sudo lvcreate -L 50G -n lv_backup vg_data
The result could look like:
VG: vg_data
│
├── LV: lv_database 100G
├── LV: lv_docker 200G
└── LV: lv_backup 50G
The remaining space stays available in the Volume Group.
Check it with:
sudo vgs
Creating a Filesystem
A Logical Volume is a block device. It does not automatically contain a filesystem.
For example, create an ext4 filesystem:
sudo mkfs.ext4 /dev/vg_data/lv_data
WARNING: Formatting a Logical Volume destroys existing data on that volume. Always verify the target before running
mkfs.
You can verify the filesystem with:
lsblk -f
Example:
NAME FSTYPE FSVER LABEL UUID MOUNTPOINTS
sdb
└─sdb1 LVM2_member ...
└─vg_data-lv_data ext4 1.0 ...
Mounting the Filesystem
Create a mount point:
sudo mkdir -p /mnt/data
Mount the Logical Volume:
sudo mount /dev/vg_data/lv_data /mnt/data
Verify it:
df -h
Example:
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_data-lv_data 916G 28K 870G 1% /mnt/data
The filesystem is now available at:
/mnt/data
Making the Mount Persistent
A manual mount command normally applies only to the current boot.
To mount the filesystem automatically after reboot, configure /etc/fstab.
First obtain the filesystem UUID:
sudo blkid /dev/vg_data/lv_data
Example:
/dev/vg_data/lv_data: UUID="12345678-abcd-1234-abcd-123456789abc" TYPE="ext4"
Add an entry to /etc/fstab:
UUID=12345678-abcd-1234-abcd-123456789abc /mnt/data ext4 defaults 0 2
Then test the configuration:
sudo mount -a
If there are no errors, the filesystem should be mountable using the /etc/fstab configuration.
LVM Commands
Several commands are particularly useful when working with LVM.
Physical Volumes
List Physical Volumes:
sudo pvs
Display detailed information:
sudo pvdisplay
Volume Groups
List Volume Groups:
sudo vgs
Display detailed information:
sudo vgdisplay
Logical Volumes
List Logical Volumes:
sudo lvs
Display detailed information:
sudo lvdisplay
These commands are useful for both administration and troubleshooting.
Extending a Logical Volume
One of the practical benefits of LVM is the ability to extend Logical Volumes when free space is available.
Check the available space in the Volume Group:
sudo vgs
For example:
VG VSize VFree
vg_data 931.00g 331.00g
This means that approximately 331 GB is still available in the Volume Group.
Extend the Logical Volume by 100 GB:
sudo lvextend -L +100G /dev/vg_data/lv_data
Check the new size:
sudo lvs
The Logical Volume has now grown, but the filesystem may still need to be expanded.
For ext4:
sudo resize2fs /dev/vg_data/lv_data
A common workflow is therefore:
Free space in VG
│
▼
Extend LV
│
▼
Extend filesystem
The exact filesystem command depends on the filesystem type.
Extending the Filesystem with lvextend
For supported filesystems, lvextend can also resize the filesystem automatically with the -r option.
For example:
sudo lvextend -r -L +100G /dev/vg_data/lv_data
This performs both operations:
Logical Volume
+
Filesystem
Always verify that the filesystem supports the intended resize operation.
Reducing a Logical Volume
Reducing an LV is more dangerous than extending one.
For filesystems such as ext4, the filesystem normally needs to be reduced before reducing the Logical Volume.
The order is important:
Filesystem
↓
Reduce filesystem
↓
Reduce Logical Volume
Never blindly run:
lvreduce
on a filesystem that still contains data beyond the new size.
Doing so can cause data loss.
sudo lvs
df -h /mnt/vgroup_backup
sudo umount /mnt/vgroup_backup
sudo e2fsck -f /dev/mapper/testgroup-backup
sudo resize2fs /dev/mapper/testgroup-backup 1G
sudo lvreduce -L 1G /dev/mapper/testgroup-backup
sudo lvs
sudo vgs
[tomik@localhost mnt]$ sudo lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root almalinux -wi-ao---- <17.00g
swap almalinux -wi-ao---- 2.00g
backup testgroup -wi-ao---- <1.99g
data1 testgroup -wi-ao---- 1.00g
[tomik@localhost mnt]$ lsblk -f
NAME FSTYPE LABEL UUID MOUNTPOINT
sda
├─sda1 ext4 711a9e40-37a5-4cff-9576-e97d414b798f /mnt/disk_a
└─sda2 LVM2_member TcNh9D-a9oY-C4EH-dwIQ-c3j4-lsBG-OjubBz
└─testgroup-data1 ext4 1c02d35a-4bf0-4faa-8498-8e7935e4089e /mnt/vgroup_data1
sdb
├─sdb1 ext4 5b7dceb5-fbc3-4a4a-b283-84581657db00 /mnt/disk_b
└─sdb2 LVM2_member rubpMX-o7Ir-1TMJ-xtui-kLpZ-Vu2M-MBsdl5
├─testgroup-data1 ext4 1c02d35a-4bf0-4faa-8498-8e7935e4089e /mnt/vgroup_data1
└─testgroup-backup ext4 5e688803-e77a-4533-85b1-aa2430b379c8 /mnt/vgroup_backup
sdc
├─sdc1 ext4 186df32e-516d-4a31-bb3b-cddf06e1b373 /mnt/disk_c
└─sdc2 LVM2_member cdIyxE-G6S2-XVlL-JgfX-FVut-BWOd-okgDzD
└─testgroup-backup ext4 5e688803-e77a-4533-85b1-aa2430b379c8 /mnt/vgroup_backup
sr0
nvme0n1
├─nvme0n1p1 xfs da318a00-f09f-4011-a953-bc53134e63be /boot
└─nvme0n1p2 LVM2_member PDobUG-lBPP-ivlA-klrL-VpKO-yJ2K-K120lO
├─almalinux-root xfs 79e9a10a-d166-4f92-a499-8be8a442b7ef /
└─almalinux-swap swap 80d58ae7-1412-407a-bfef-83e572b2cd38 [SWAP]
[tomik@localhost mnt]$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 351M 0 351M 0% /dev
tmpfs 370M 0 370M 0% /dev/shm
tmpfs 370M 5.4M 364M 2% /run
tmpfs 370M 0 370M 0% /sys/fs/cgroup
/dev/mapper/almalinux-root 17G 3.6G 14G 21% /
vmhgfs-fuse 930G 611G 320G 66% /mnt/hgfs
/dev/nvme0n1p1 1014M 301M 714M 30% /boot
/dev/sdb1 989M 24K 922M 1% /mnt/disk_b
/dev/sdc1 989M 24K 922M 1% /mnt/disk_c
/dev/sda1 989M 101M 823M 11% /mnt/disk_a
tmpfs 74M 0 74M 0% /run/user/1000
/dev/mapper/testgroup-data1 974M 24K 907M 1% /mnt/vgroup_data1
/dev/mapper/testgroup-backup 2.0G 28K 1.9G 1% /mnt/vgroup_backup
[tomik@localhost mnt]$ sudo lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root almalinux -wi-ao---- <17.00g
swap almalinux -wi-ao---- 2.00g
backup testgroup -wi-ao---- <1.99g
data1 testgroup -wi-ao---- 1.00g
[tomik@localhost mnt]$ sudo umount /mnt/vgroup_backup
[tomik@localhost mnt]$ sudo e2fsck -f /dev/mapper/testgroup-backup
e2fsck 1.45.6 (20-Mar-2020)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/mapper/testgroup-backup: 12/130304 files (0.0% non-contiguous), 17911/521216 blocks
[tomik@localhost mnt]$ sudo resize2fs /dev/mapper/testgroup-backup 1G
resize2fs 1.45.6 (20-Mar-2020)
Resizing the filesystem on /dev/mapper/testgroup-backup to 262144 (4k) blocks.
The filesystem on /dev/mapper/testgroup-backup is now 262144 (4k) blocks long.
[tomik@localhost mnt]$ sudo lvreduce -L 1G /dev/mapper/testgroup-backup
WARNING: Reducing active logical volume to 1.00 GiB.
THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce testgroup/backup? [y/n]: y
Size of logical volume testgroup/backup changed from <1.99 GiB (509 extents) to 1.00 GiB (256 extents).
Logical volume testgroup/backup successfully resized.
[tomik@localhost mnt]$ sudo lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root almalinux -wi-ao---- <17.00g
swap almalinux -wi-ao---- 2.00g
backup testgroup -wi-a----- 1.00g
data1 testgroup -wi-ao---- 1.00g
[tomik@localhost mnt]$ sudo vgs
VG #PV #LV #SN Attr VSize VFree
almalinux 1 2 0 wz--n- <19.00g 0
testgroup 3 2 0 wz--n- <2.99g 1012.00m
[tomik@localhost mnt]$ sudo pvs -o pv_name,pv_size,pv_free,pv_used
PV PSize PFree Used
/dev/nvme0n1p2 <19.00g 0 <19.00g
/dev/sda2 1020.00m 0 1020.00m
/dev/sdb2 1020.00m 1012.00m 8.00m
/dev/sdc2 1020.00m 0 1020.00m
[tomik@localhost mnt]$ sudo lvs -o lv_name,lv_size,vg_name,devices
LV LSize VG Devices
root <17.00g almalinux /dev/nvme0n1p2(512)
swap 2.00g almalinux /dev/nvme0n1p2(0)
backup 1.00g testgroup /dev/sdc2(0)
backup 1.00g testgroup /dev/sdb2(1)
data1 1.00g testgroup /dev/sda2(0)
data1 1.00g testgroup /dev/sdb2(0)
[tomik@localhost mnt]$ sudo vgdisplay testgroup
--- Volume group ---
VG Name testgroup
System ID
Format lvm2
Metadata Areas 3
Metadata Sequence No 6
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 2
Open LV 1
Max PV 0
Cur PV 3
Act PV 3
VG Size <2.99 GiB
PE Size 4.00 MiB
Total PE 765
Alloc PE / Size 512 / 2.00 GiB
Free PE / Size 253 / 1012.00 MiB
VG UUID O89qmS-Cddt-GOug-oVB8-pba0-I8H4-iPbsEr
Removing LVM Components
LVM components should normally be removed in the reverse order in which they were created.
Conceptually:
Filesystem
↓
Logical Volume
↓
Volume Group
↓
Physical Volume
↓
Partition
For example, after unmounting a filesystem:
sudo umount /mnt/data
the Logical Volume can be removed:
sudo lvremove /dev/vg_data/lv_data
The Volume Group can then be removed:
sudo vgremove vg_data
The Physical Volume can then be removed from LVM:
sudo pvremove /dev/sdb1
Finally, the partition can be removed using fdisk or parted.
WARNING: These operations are destructive. Make sure the storage is no longer needed before removing any LVM layer.
Complete Practical Example
Assume that:
/dev/sdb
is a new 1 TB disk.
The disk has already been partitioned and contains:
/dev/sdb1
marked as Linux LVM.
Step 1: Create the Physical Volume
sudo pvcreate /dev/sdb1
Verify:
sudo pvs
Step 2: Create the Volume Group
sudo vgcreate vg_data /dev/sdb1
Verify:
sudo vgs
Step 3: Create the Logical Volume
Use all available space:
sudo lvcreate -l 100%FREE -n lv_data vg_data
Verify:
sudo lvs
Step 4: Create the Filesystem
sudo mkfs.ext4 /dev/vg_data/lv_data
Step 5: Create the Mount Point
sudo mkdir -p /mnt/data
Step 6: Mount the Filesystem
sudo mount /dev/vg_data/lv_data /mnt/data
Step 7: Verify
Check the block devices:
lsblk -f
Check the mounted filesystem:
df -h
The final layout is:
/dev/sdb
└── /dev/sdb1
└── PV
└── VG: vg_data
└── LV: lv_data
└── ext4
└── /mnt/data
Understanding the Complete Storage Stack
The complete process can be visualized as:
Physical Disk
/dev/sdb
│
▼
Partition
/dev/sdb1
│
▼
Physical Volume
PV
│
▼
Volume Group
vg_data
│
▼
Logical Volume
lv_data
│
▼
Filesystem
ext4
│
▼
Mount Point
/mnt/data
Each layer has a different responsibility.
| Layer | Purpose |
|---|---|
| Disk | Physical storage device |
| Partition | Divides the disk |
| PV | Makes storage available to LVM |
| VG | Provides a storage pool |
| LV | Provides a logical block device |
| Filesystem | Organizes files and directories |
| Mount point | Makes the filesystem accessible in Linux |
LVM vs RAID
LVM and RAID are related to storage, but they solve different problems.
LVM primarily provides:
- flexible storage management
- logical volumes
- storage pooling
- volume resizing
- abstraction from physical disk layout
RAID primarily addresses:
- redundancy
- availability
- performance
- combining physical disks into arrays
They can also be used together.
For example:
Physical Disks
│
▼
RAID
│
▼
Storage Device
│
▼
LVM
│
▼
Logical Volumes
The next storage chapter covers RAID separately.
LVM and DevOps
Understanding LVM is useful for DevOps and infrastructure work because storage frequently sits underneath other technologies.
A simplified infrastructure stack might look like:
Physical Disk
│
▼
Partition
│
▼
LVM
│
▼
Filesystem
│
▼
Container Runtime
│
▼
Application Data
On virtualization hosts, database servers, CI/CD infrastructure, and container hosts, understanding the storage layers makes troubleshooting much easier.
For example, if a filesystem reports that it is full, you need to determine which layer is actually out of space:
Filesystem full?
│
├── Filesystem capacity?
│
├── Logical Volume capacity?
│
├── Free space in Volume Group?
│
└── Physical storage capacity?
The commands introduced in this chapter help identify these layers.
Key Takeaways
Remember the three main LVM components:
PV → Physical Volume
VG → Volume Group
LV → Logical Volume
The complete storage model is:
Disk
↓
Partition
↓
PV
↓
VG
↓
LV
↓
Filesystem
↓
Mount Point
The most important commands are:
# Physical Volumes
sudo pvcreate /dev/sdb1
sudo pvs
sudo pvdisplay
# Volume Groups
sudo vgcreate vg_data /dev/sdb1
sudo vgs
sudo vgdisplay
# Logical Volumes
sudo lvcreate -L 100G -n lv_data vg_data
sudo lvs
sudo lvdisplay
# Filesystem
sudo mkfs.ext4 /dev/vg_data/lv_data
# Mount
sudo mkdir -p /mnt/data
sudo mount /dev/vg_data/lv_data /mnt/data
The key idea is that LVM separates physical storage from logical storage.
Once this concept is understood, commands such as pvcreate, vgcreate, and lvcreate become parts of one logical process rather than unrelated commands.
Replacing a Physical Disk with pvmove
One of the useful features of LVM is the ability to move data from one Physical Volume to another.
This can be useful when:
- a disk needs to be replaced
- a disk is showing signs of failure
- a larger disk is being introduced
- a disk needs to be removed from a Volume Group
- storage needs to be reorganized
The key command for this operation is:
pvmove
pvmove moves allocated Physical Extents from one Physical Volume to another.
Important:
pvmoveis not a replacement for RAID or backups. If a disk has already completely failed and the data on it is inaccessible,pvmovecannot recover that data.
The Basic Idea
Imagine a Volume Group containing two Physical Volumes:
VG: vg_data
│
├── /dev/sdb1
│
└── /dev/sdc1
If /dev/sdb needs to be replaced, we first add a new Physical Volume:
/dev/sdb1 old disk
/dev/sdc1 existing disk
/dev/sdd1 new disk
The goal is:
Before:
VG: vg_data
│
├── /dev/sdb1 ← old disk
└── /dev/sdc1
After:
VG: vg_data
│
├── /dev/sdc1
└── /dev/sdd1 ← new disk
The data previously stored on /dev/sdb1 is moved to /dev/sdd1.
Important Requirement
The destination Physical Volume must have enough free space to hold the allocated extents from the source Physical Volume.
For example:
Old PV:
Size: 1 TB
Used: 600 GB
New PV:
Size: 700 GB
Free: 700 GB
This can be sufficient because only the allocated 600 GB needs to be moved.
Example Environment
Assume the current system contains:
/dev/sdb1
/dev/sdc1
inside:
vg_data
We want to replace:
/dev/sdb
with:
/dev/sdd
The new disk will eventually become:
/dev/sdd1
Step 1: Check the Current LVM Configuration
List Physical Volumes:
sudo pvs
Example:
PV VG Fmt Attr PSize PFree
/dev/sdb1 vg_data lvm2 a-- 931.00g 50.00g
/dev/sdc1 vg_data lvm2 a-- 931.00g 400.00g
Check the Volume Group:
sudo vgs
Check the Logical Volumes:
sudo lvs
For more detailed Physical Volume information:
sudo pvdisplay
Step 2: Prepare the New Disk
Identify the new disk:
lsblk
Example:
NAME SIZE TYPE
sdb 931G disk
└─sdb1 931G part
sdc 931G disk
└─sdc1 931G part
sdd 1T disk
In this example:
/dev/sdd
is the new disk.
WARNING: Always verify the device name before partitioning. Selecting the wrong disk can destroy existing data.
Step 3: Create a Partition on the New Disk
Using parted:
sudo parted /dev/sdd
Inside parted:
mklabel gpt
mkpart primary 0% 100%
set 1 lvm on
print
quit
The new partition should now be:
/dev/sdd1
Verify it:
lsblk
Step 4: Create a Physical Volume
Initialize the new partition:
sudo pvcreate /dev/sdd1
Verify:
sudo pvs
The new PV should appear without a Volume Group initially.
Step 5: Add the New PV to the Volume Group
Add /dev/sdd1 to vg_data:
sudo vgextend vg_data /dev/sdd1
Verify:
sudo vgs
sudo pvs
The Volume Group now contains three Physical Volumes:
VG: vg_data
│
├── /dev/sdb1 ← old PV
├── /dev/sdc1
└── /dev/sdd1 ← new PV
Step 6: Move the Data with pvmove
Move the allocated extents from the old PV to the new PV:
sudo pvmove /dev/sdb1 /dev/sdd1
This tells LVM to move allocated Physical Extents from /dev/sdb1 to /dev/sdd1.
The operation can take significant time depending on:
- amount of data
- disk speed
- storage type
- system load
The Logical Volumes can generally remain online while the move is performed.
You can also let LVM select suitable free space automatically:
sudo pvmove /dev/sdb1
When replacing a specific disk, explicitly specifying the destination is often clearer:
sudo pvmove /dev/sdb1 /dev/sdd1
Step 7: Verify That the Old PV Is Empty
After pvmove completes:
sudo pvs
The old PV should show no allocated space.
For example:
PV VG PSize PFree
/dev/sdb1 vg_data 931.00g 931.00g
/dev/sdc1 vg_data 931.00g 400.00g
/dev/sdd1 vg_data 931.00g 931.00g
The important part is:
/dev/sdb1
PFree = PSize
You can also check:
sudo pvdisplay /dev/sdb1
Step 8: Remove the Old PV from the Volume Group
Once the old PV is completely empty:
sudo vgreduce vg_data /dev/sdb1
Verify:
sudo pvs
The old /dev/sdb1 should no longer belong to vg_data.
Step 9: Remove LVM Metadata
Remove the LVM metadata from the old PV:
sudo pvremove /dev/sdb1
Verify:
sudo pvs
Remove partition and LVM set bit via parted or fdisk - completely clear the disk
The old disk can now be removed from the system.
Step 10: Physically Replace the Disk
The old disk:
/dev/sdb
can now be physically removed.
The resulting architecture is:
Before:
/dev/sdb1 ──┐
│
/dev/sdc1 ──┼── VG: vg_data
│
/dev/sdd1 ──┘
After:
/dev/sdc1 ──┐
├── VG: vg_data
/dev/sdd1 ──┘
The Logical Volumes remain part of the same Volume Group.
Complete pvmove Workflow
1. Identify the old PV
│
▼
2. Add the replacement disk - if it is possible. If not start with pvmove and removal procedure of old disk first and replace new
│
▼
3. Partition the new disk
│
▼
4. pvcreate /dev/sdd1
│
▼
5. vgextend vg_data /dev/sdd1
│
▼
6. pvmove /dev/sdb1 /dev/sdd1
│
▼
7. Verify /dev/sdb1 is empty
│
▼
8. vgreduce vg_data /dev/sdb1
│
▼
9. pvremove /dev/sdb1
│
▼
10. Remove the old disk
The key commands are:
sudo pvcreate /dev/sdd1
sudo vgextend vg_data /dev/sdd1
sudo pvmove /dev/sdb1 /dev/sdd1
sudo pvs
sudo vgreduce vg_data /dev/sdb1
sudo pvremove /dev/sdb1
What If the New Disk Is Larger?
The replacement disk does not need to have exactly the same size.
For example:
Old disk: 1 TB
New disk: 2 TB
After the move, the additional capacity becomes available in the Volume Group.
Check it with:
sudo vgs
The additional free space can then be used to extend existing Logical Volumes or create new ones.
What If the New Disk Is Smaller?
The replacement disk can potentially be smaller than the original disk, but only if it has enough free capacity for the data currently allocated on the old PV.
For example:
Old PV:
1 TB total
300 GB allocated
New PV:
500 GB total
500 GB free
This can work because only approximately 300 GB needs to be moved.
Check the current usage with:
sudo pvs
and:
sudo pvdisplay
What If the Disk Has Already Failed?
pvmove works only while the source PV is accessible.
If /dev/sdb has completely failed:
/dev/sdb
X
LVM cannot read the extents stored on it.
In that situation, pvmove cannot simply recover the missing data.
Recovery depends on the LVM configuration, redundancy, filesystem, backups, and the nature of the disk failure.
LVM is not a backup solution.
LVM by itself does not provide protection against complete disk failure.
RAID is a separate technology designed to provide storage redundancy.
Important Safety Considerations
Before performing a disk replacement:
Verify the Source
Make sure that:
/dev/sdb1
is the PV you want to evacuate.
Use:
sudo pvs
sudo pvdisplay
Verify the Destination
Make sure the destination PV has enough free space:
sudo pvs
Do Not Remove the PV Before pvmove
The correct order is:
pvmove
↓
verify
↓
vgreduce
↓
pvremove
Do not remove the PV from the Volume Group while it still contains allocated extents.
Have a Backup
Even when using pvmove, maintain backups of important data.
A disk replacement is a storage operation with real risk.
Visual Summary
BEFORE
/dev/sdb1 ───────────┐
│
/dev/sdc1 ───────────┼── VG: vg_data
│
└── Logical Volumes
ADD NEW DISK
/dev/sdb1 ───────────┐
/dev/sdc1 ───────────┼── VG: vg_data
/dev/sdd1 ───────────┘
PVMOVE
/dev/sdb1 ────────────────┐
│
pvmove
│
▼
/dev/sdd1
AFTER
/dev/sdc1 ───────────┐
├── VG: vg_data
/dev/sdd1 ───────────┘
│
└── Logical Volumes
/dev/sdb1 → removed
The important concept is:
pvmove
moves the data allocated on a Physical Volume.
The Volume Group and Logical Volumes can remain in place while the underlying Physical Volume is evacuated.
Key Takeaways
The most important commands for replacing a healthy LVM disk are:
sudo pvcreate /dev/sdd1
sudo vgextend vg_data /dev/sdd1
sudo pvmove /dev/sdb1 /dev/sdd1
sudo pvs
sudo vgreduce vg_data /dev/sdb1
sudo pvremove /dev/sdb1
The conceptual workflow is:
New Disk
↓
Partition
↓
PV
↓
Add PV to VG
↓
pvmove
↓
Verify old PV is empty
↓
Remove old PV from VG
↓
Remove LVM metadata
↓
Replace old disk
This is one of the practical reasons LVM is useful in Linux infrastructure: a healthy Physical Volume can be evacuated and removed from a Volume Group without rebuilding the Logical Volumes from scratch.
Guide: Creating an Encrypted LVM Volume using LUKS
This guide covers how to isolate a disk partition, encrypt it using LUKS, set up an LVM structure inside the encrypted container, and manage its state (locking and unlocking).
Part 1: Initializing and Encrypting the Drive
Step 1: Remove the partition from the old Volume Group
If the partition (e.g., /dev/sdb2) is currently part of an active unencrypted Volume Group, it must be completely removed first.
sudo vgreduce testgroup /dev/sdb2
sudo pvremove /dev/sdb2
Step 2: Format the partition with LUKS Encryption
This step initializes the encryption layer. You will be prompted to type YES (must be uppercase) and enter a secure passphrase.
Warning: If you lose this passphrase, your data cannot be recovered.*
sudo cryptsetup luksFormat /dev/sdb2
Step 3: Open (Unlock) the Encrypted Container
Before you can create layout partitions or file systems, you must unlock the device. This creates a virtual decrypted mapping under /dev/mapper/sdb2_encrypted.
sudo cryptsetup luksOpen /dev/sdb2 sdb2_encrypted
Part 2: Configuring LVM Inside the Encrypted Container
Step 4: Create Physical Volume, Volume Group, and Logical Volume
Now we treat the open decrypted container as a raw device and build the LVM architecture on top of it.
sudo pvcreate /dev/mapper/sdb2_encrypted
sudo vgcreate vg_secure /dev/mapper/sdb2_encrypted
sudo lvcreate -l +100%FREE -n lv_secret vg_secure
Step 5: Create File System and Mount
Format your new secure logical volume with the ext4 file system and mount it to your desired directory.
sudo mkfs.ext4 /dev/vg_secure/lv_secret
sudo mkdir -p /mnt/secure_data
sudo mount /dev/vg_secure/lv_secret /mnt/secure_data
At this stage, you can safely write data into /mnt/secure_data. Everything is automatically encrypted on the fly.
Part 3: Management and Maintenance
How to Safely Lock the Vault (e.g., before shutting down)
To lock the drive and hide your data, unmount the file system, deactivate the inner Volume Group, and close the LUKS mapper device.
sudo umount /mnt/secure_data
sudo vgchange -an vg_secure
sudo cryptsetup luksClose sdb2_encrypted
How to Unlock and Remount the Vault
Whenever you boot the computer and need access to your files again, run the following sequence to supply your passphrase and restore the mounts:
sudo cryptsetup luksOpen /dev/sdb2 sdb2_encrypted
sudo vgchange -ay vg_secure
sudo mount /dev/vg_secure/lv_secret /mnt/secure_data
Verification
To check your active layout and verify that the encryption container is properly recognized by the kernel, run:
lsblk -f
(You will see a tree-like hierarchy showing sdb2 -> type crypt -> vg_secure-lv_secret -> mounted on /mnt/secure_data)