The Three Layers of LVM

LVM has exactly three concepts. Once these click, everything else follows naturally.


The full picture

LVM ARCHITECTURE — FULL STACK PHYSICAL DISKS — what your machine actually has /dev/sda 500 GB — SSD /dev/sdb 1 TB — HDD /dev/sdc 2 TB — HDD pvcreate pvcreate pvcreate PHYSICAL VOLUMES (PV) — tagged so LVM owns them PV: /dev/sda 500 GB available PV: /dev/sdb 1 TB available PV: /dev/sdc 2 TB available vgcreate VOLUME GROUP (VG) — one unified storage pool vg_storage 3.5 TB total · all three drives unified · allocate as needed lvcreate LOGICAL VOLUMES (LV) — what you actually format and mount lv_home 200 GB → ext4 → /home lv_var 800 GB → ext4 → /var lv_data 2.5 TB → xfs → /data

Layer 1 — Physical Volume (PV)

A Physical Volume is a disk or partition that LVM has claimed. Nothing more. You’re just stamping it with an LVM header that says “I own this — don’t use it for regular partitions.”

pvcreate /dev/sda

LVM writes a small metadata header to the beginning of the disk. The rest of the space becomes a pile of Physical Extents (PEs) — fixed-size chunks (usually 4 MB each) that LVM uses as its basic unit of allocation. Think of PEs as the individual Lego bricks.

What a PV looks like:

/dev/sda  ──────────────────────────────────────────────────
          │ LVM header │ PE  │ PE  │ PE  │ PE  │ PE  │ ... │
          ──────────────────────────────────────────────────
                          ↑ 4 MB chunks, ~125,000 of them on a 500 GB disk

Key PV commands:

pvcreate /dev/sda          # Create a PV from /dev/sda
pvs                        # List all PVs (quick summary)
pvdisplay                  # Detailed PV info
pvremove /dev/sda          # Remove LVM from a disk (destroys data)

You can create a PV from a whole disk (/dev/sda) or from a single partition (/dev/sda1). Using whole disks is simpler and more flexible.


Layer 2 — Volume Group (VG)

A Volume Group is one or more PVs combined into a single pool. Once you have a VG, you forget about the individual disks — to LVM and to you, it’s just one big pile of space.

vgcreate vg_storage /dev/sda /dev/sdb /dev/sdc

This pools all three disks into vg_storage. LVM now has 3.5 TB to allocate as it sees fit. If you later plug in a fourth disk, you add it to the same VG — no reformatting, no data movement.

What a VG looks like internally:

vg_storage (3.5 TB)
┌──────────────────────────────────────────────────────────────────┐
│ PEs from /dev/sda  │ PEs from /dev/sdb  │   PEs from /dev/sdc   │
│ ░░░░░░░░░░░░░░░░░░ │ ░░░░░░░░░░░░░░░░░░ │ ░░░░░░░░░░░░░░░░░░░░░ │
└──────────────────────────────────────────────────────────────────┘
  500 GB               1 TB                 2 TB

Key VG commands:

vgcreate vg_storage /dev/sda /dev/sdb   # Create VG from PVs
vgextend vg_storage /dev/sdc            # Add another disk later
vgs                                      # Quick VG summary
vgdisplay vg_storage                    # Detailed info
vgremove vg_storage                     # Delete VG (destroys data)

Name your VG something meaningful (vg_data, vg_storage, ubuntu-vg). You’ll be typing it a lot.


Layer 3 — Logical Volume (LV)

A Logical Volume is a chunk of space carved from the VG — this is what you actually format with a filesystem (ext4, xfs) and mount.

lvcreate -L 200G -n lv_home vg_storage

This creates a 200 GB LV named lv_home from vg_storage. LVM finds 200 GB worth of PEs in the VG (from whichever disk has them free) and assigns them to this LV. To the filesystem above, it looks exactly like a regular block device at /dev/vg_storage/lv_home.

Logical Volumes can span multiple physical disks seamlessly:

lv_home (200 GB) — could be spread across sda and sdb — you don't care, LVM handles it

Key LV commands:

lvcreate -L 200G -n lv_home vg_storage  # Create 200 GB LV
lvcreate -l 100%FREE -n lv_data vg_storage  # Use all remaining space
lvs                                      # Quick LV summary
lvdisplay                               # Detailed info
lvremove /dev/vg_storage/lv_home        # Delete LV (destroys data)

Before and after LVM

Here’s why this matters in practice:

WITHOUT LVM                             WITH LVM
──────────────────────────────────      ────────────────────────────────────

 /dev/sda (500 GB)                       /dev/sda  /dev/sdb  /dev/sdc
 ┌────────┬────────┬────────┬──────┐         │         │         │
 │/dev/   │/dev/   │/dev/   │/dev/ │         └────────┬┘         │
 │sda1    │sda2    │sda3    │sda4  │                  │          │
 │/boot   │/       │swap    │/home │         ┌────────▼──────────▼────────┐
 │500 MB  │100 GB  │4 GB    │395 GB│         │         vg_storage         │
 └────────┴────────┴────────┴──────┘         │           3.5 TB           │
                                             └──────────────────────────┬─┘
 6 months later:                                                         │
   /home is 90% full                         ┌──────┬──────────┬────────▼──┐
   /     has 60 GB free                      │lv_   │lv_var    │lv_home    │
                                             │root  │100 GB    │200 GB     │
 You can't resize /home — it's              │100 GB│(growable)│(growable) │
 physically fixed on the disk.              └──────┴──────────┴───────────┘

 Your only option: backup everything,
 repartition, restore. Hours of work.        6 months later — /home 90% full?
                                             lvextend -L +100G /dev/vg_storage/lv_home
                                             resize2fs /dev/vg_storage/lv_home
                                             Done. 30 seconds. No downtime.

The device path for LVs

When you create lv_home in vg_storage, it appears at two equivalent paths:

/dev/vg_storage/lv_home   ← the symlink (easier to read)
/dev/mapper/vg_storage-lv_home   ← the actual device (both work)

Use whichever you prefer — they point to the same thing.


Summary table

Concept Role Command Example result
Physical Volume Marks a disk for LVM pvcreate /dev/sda /dev/sda is LVM-ready
Volume Group Pools PVs into one vgcreate vg_data /dev/sda /dev/sdb vg_data = 1.5 TB
Logical Volume Slices from the pool lvcreate -L 200G -n lv_home vg_data /dev/vg_data/lv_home exists
Format Puts a filesystem on it mkfs.ext4 /dev/vg_data/lv_home Ready to mount
Mount Makes it accessible mount /dev/vg_data/lv_home /home Files in /home