Linux - LVM
Logical Volume Manager
Overview
Physical Volume
A physical volume is a block device that has to be marked as such to take part in Logical Volume Management. This is the first step in setting up a volume group which we use to create logical volumes which can be used as 'regular' disks.
The physical volume does not have to be a full disk, it can be a partition of a disk. In fact it can be any blockdevice.
# pvcreate <BLOCK_DEVICE>
# pvs
PV VG Fmt Attr PSize PFree
/dev/sda3 cl lvm2 a-- 18.41g 0
# pvdisplay
--- Physical volume ---
PV Name /dev/sda3
VG Name cl
PV Size 18.41 GiB / not usable 2.00 MiB
Allocatable yes (but full)
PE Size 4.00 MiB
Total PE 4713
Free PE 0
Allocated PE 4713
PV UUID zaP4cW-tjgV-Wggs-RHmg-RZlh-PifQ-J1ULI4
Discovering physical volumes
In order to discover block devices on your system you could use
# cat /proc/partitions
# fdisk -l
# lsblk # tree view
# lsblk -l # list view
# fdisk -l
Disk /dev/sda: 20 GiB, 21474836480 bytes, 41943040 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
Disklabel type: gpt
Disk identifier: 1729418E-F806-434E-94DD-F9FE8948E3B4
Device Start End Sectors Size Type
/dev/sda1 2048 1230847 1228800 600M EFI System
/dev/sda2 1230848 3327999 2097152 1G Linux filesystem
/dev/sda3 3328000 41940991 38612992 18.4G Linux LVM
Disk /dev/mapper/cl-root: 16.4 GiB, 17620271104 bytes, 34414592 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/cl-swap: 2 GiB, 2147483648 bytes, 4194304 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
# cat /proc/partitions
major minor #blocks name
11 0 1048575 sr0
8 0 20971520 sda
8 1 614400 sda1
8 2 1048576 sda2
8 3 19306496 sda3
253 0 17207296 dm-0
253 1 2097152 dm-1
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
├─sda1 8:1 0 600M 0 part /boot/efi
├─sda2 8:2 0 1G 0 part /boot
└─sda3 8:3 0 18.4G 0 part
├─cl-root 253:0 0 16.4G 0 lvm /
└─cl-swap 253:1 0 2G 0 lvm [SWAP]
sr0 11:0 1 1024M 0 rom
# lsblk -l
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
sda1 8:1 0 600M 0 part /boot/efi
sda2 8:2 0 1G 0 part /boot
sda3 8:3 0 18.4G 0 part
sr0 11:0 1 1024M 0 rom
cl-root 253:0 0 16.4G 0 lvm /
cl-swap 253:1 0 2G 0 lvm [SWAP]
Volume Group (VG)
Now that we have physical volumes available we can create volume groups. We can think of a volume group as a pool of available storage space that we can use to create logical volumes (virtual disks).
# lsblk
# pvcreate /dev/sda /dev/sdb /dev/sdc
# vgcreate bigdisk /dev/sda /dev/sdb /dev/sdc
# vgs
# vgdisplay
Let's mark the block devices as physical volumes.
# pvcreate /dev/loop0 /dev/loop1 /dev/loop2
Physical volume "/dev/loop0" successfully created.
Physical volume "/dev/loop1" successfully created.
Physical volume "/dev/loop2" successfully created.
# pvs
PV VG Fmt Attr PSize PFree
/dev/loop0 pool lvm2 a-- 96.00m 96.00m
/dev/loop1 pool lvm2 a-- 96.00m 96.00m
/dev/loop2 pool lvm2 a-- 96.00m 96.00m
# pvdisplay
--- Physical volume ---
PV Name /dev/loop0
VG Name pool
PV Size 100.00 MiB / not usable 4.00 MiB
Allocatable yes
PE Size 4.00 MiB
Total PE 24
Free PE 24
Allocated PE 0
PV UUID t6JwEn-1YhG-MHBo-Atco-TNfF-bhPz-Sp4umx
--- Physical volume ---
PV Name /dev/loop1
VG Name pool
PV Size 100.00 MiB / not usable 4.00 MiB
Allocatable yes
PE Size 4.00 MiB
Total PE 24
Free PE 24
Allocated PE 0
PV UUID xXKauA-Ka73-mIt1-eQCP-vLym-BcqN-mufQBS
--- Physical volume ---
PV Name /dev/loop2
VG Name pool
PV Size 100.00 MiB / not usable 4.00 MiB
Allocatable yes
PE Size 4.00 MiB
Total PE 24
Free PE 24
Allocated PE 0
PV UUID fZcFEl-Jlrf-NEQS-JEwv-LE1e-4OaK-zx6Uis
Now that we have physical volumes we can create volume groups. Let's create a volume group named pool consisting of all three block devices we created previously.
# vgcreate pool /dev/loop0 /dev/loop1 /dev/loop2
Volume group "pool" successfully created
Logical Volume (LV)
Snapshots
Creating a snapshot
When creating a snapshot we actually create a new volume which gets marked as a snapshot volume and it has to reference an existing volume. You have to make sure there is enough space in your volume group to create the snapshot volume (just like a 'regular' logical volume).
# lvs
# lvcreate -s -n <NAME_OF_SNAPSHOT_VOLUME> -L <MAX_SIZE_OF_SNAPSHOT_VOLUME> <LVM_DEVICE_TO_TAKE_SNAPSHOT_OF>
# lvcreate -s -n centos8_snapshot -L 1G /dev/vms/centos8
Using default stripesize 64.00 KiB.
Logical volume "centos8_snapshot" created.
# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
centos8 vms owi-aos--- 20.00g
centos8_snapshot vms swi-a-s--- 1.00g centos8 0.00
Resizing Logical Volumes
lvextend
lvreduce
lvresize
Extending Logical Volumes
# lvextend -L+30M -r /dev/pool/data
Rounding size to boundary between physical extents: 32.00 MiB.
Phase 1 - find and verify superblock...
Phase 2 - using internal log
- zero log...
- scan filesystem freespace and inode maps...
- found root inode chunk
Phase 3 - for each AG...
- scan (but don't clear) agi unlinked lists...
- process known inodes and perform inode discovery...
- agno = 0
- agno = 1
- agno = 2
- agno = 3
- process newly discovered inodes...
Phase 4 - check for duplicate blocks...
- setting up duplicate extent list...
- check for inodes claiming duplicate blocks...
- agno = 0
- agno = 1
- agno = 2
- agno = 3
No modify flag set, skipping phase 5
Phase 6 - check inode connectivity...
- traversing filesystem ...
- traversal finished ...
- moving disconnected inodes to lost+found ...
Phase 7 - verify link counts...
No modify flag set, skipping filesystem flush and exiting.
Size of logical volume pool/data changed from 152.00 MiB (38 extents) to 184.00 MiB (46 extents).
Logical volume pool/data successfully resized.
meta-data=/dev/mapper/pool-data isize=512 agcount=4, agsize=9728 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=0
= reflink=1
data = bsize=4096 blocks=38912, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=1368, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
data blocks changed from 38912 to 47104