LVM and Disk Partitioning
Disk Fundamentals
Section titled “Disk Fundamentals”Block Devices
Section titled “Block Devices”Linux exposes storage devices as block device files under /dev/. Block devices support random Access by fixed-size blocks ( 512 bytes or 4096 bytes), unlike character devices which are Accessed as a stream of bytes.
Definition. A block device is a storage device that supports reading and writing data in Fixed-size blocks, addressed by a linear block number. The kernel caches block device I/O in the Page cache.
Naming conventions:
| Device Type | Path Pattern | Example | Notes |
|---|---|---|---|
| SCSI/SATA | /dev/sdX | /dev/sda | Letters assigned in detection order |
| NVMe | /dev/nvmeXnY | /dev/nvme0n1 | X = controller, Y = namespace |
| Virtio (VM) | /dev/vdX | /dev/vda | Paravirtualized disks |
| MMC/eMMC | /dev/mmcblkX | /dev/mmcblk0 | Embedded devices |
| Loop | /dev/loopX | /dev/loop0 | Loopback-mounted files |
| Device Mapper | /dev/dm-X | /dev/dm-0 | LVM, crypt, multipath |
| MD RAID | /dev/mdX | /dev/md0 | Software RAID arrays |
Partitions are numbered after the device name:
/dev/sda # entire disk/dev/sda1 # first partition/dev/sda15 # 15th partition (GPT allows many)/dev/nvme0n1p1 # first partition on first namespace of NVMe controller 0/dev/nvme0n1p2 # second partitionPartition Tables
Section titled “Partition Tables”Definition. A partition table is a data structure stored at the beginning of a disk that Describes the layout of partitions — their starting sectors, sizes, types, and status flags.
MBR (Master Boot Record)
Section titled “MBR (Master Boot Record)”MBR uses a 512-byte boot sector at LBA 0 containing a 446-byte bootstrap code area, a 64-byte Partition table (four 16-byte entries), and a 2-byte signature (0x55AA).
| Property | MBR |
|---|---|
| Max disk size | 2 TiB (32-bit sector count) |
| Max partitions | 4 primary, or 3 + 1 extended (with logical) |
| Sector addressing | 32-bit LBA |
| Boot method | Legacy BIOS only |
| Partition ID | 1-byte type code |
MBR is obsolete. Use it only when you need legacy BIOS boot on hardware that lacks UEFI.
GPT (GUID Partition Table)
Section titled “GPT (GUID Partition Table)”GPT is part of the UEFI specification. It stores partition entries in a linked list structure with a Protective MBR at LBA 0 for backward compatibility.
| Property | GPT |
|---|---|
| Max disk size | 8 ZiB (2^64 bytes) |
| Max partitions | 128 by default (configurable) |
| Sector addressing | 64-bit LBA |
| Boot method | UEFI (with protective MBR for compat) |
| Partition ID | 128-bit GUID type + 128-bit GUID name |
| Redundancy | Backup partition table at end of disk |
GPT disk layout: LBA 0: Protective MBR (512 bytes) LBA 1: GPT header (92 bytes) LBA 2-33: Partition entries (128 entries x 128 bytes each) LBA 34+: First usable sector (partition data starts here) Last LBA - 33: Backup partition entries Last LBA - 1: Backup GPT headerAlways use GPT unless you have a specific reason not to. The 2 TiB MBR limit is hit with Modern disks, and GPT”s backup table provides redundancy against corruption at the start of the Disk.
Sector Size
Section titled “Sector Size”| Sector Size | Common On | Notes |
|---|---|---|
| 512 bytes | Older HDDs, SATA SSD | Traditional physical sector size |
| 4096 bytes | Modern HDDs, many SSDs | 4K native (4Kn) or 512e (emulated) for compatibility |
512e drives present 512-byte logical sectors to the OS but use 4096-byte physical sectors Internally. Misaligned writes on 512e drives cause read-modify-write cycles, degrading performance. Modern partitioning tools handle alignment automatically.
# Check logical and physical sector sizecat /sys/block/sda/queue/logical_block_sizecat /sys/block/sda/queue/physical_block_size
# lsblk shows sector sizeslsblk -o NAME,LOG-SEC,PHY-SEC /dev/sdaPartition Types
Section titled “Partition Types”MBR Partition Types
Section titled “MBR Partition Types”| Type | Description |
|---|---|
| Primary | One of the four entries in the MBR table |
| Extended | A primary partition that acts as a container for logical partitions |
| Logical | Created inside an extended partition using an EBR chain |
GPT Partition Types (GUIDs)
Section titled “GPT Partition Types (GUIDs)”| GUID | Type |
|---|---|
C12A7328-F81F-11D2-BA4B-00A0C93EC93B | EFI System Partition |
0657FD6D-A4AB-43C4-84E5-0933C84B4F4F | Linux filesystem |
44479540-F297-41B2-9AF7-D131D5F0458A | Linux root (x86-64) |
933AC7E1-2EB4-4F13-B844-0E14E2AEF915 | Linux swap |
E3C9E316-0B5C-4DB8-817D-F92DF00215AE | Microsoft reserved |
EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 | Windows data |
# View partition type GUIDssgdisk -i 1 /dev/sda
# List all known partition typessgdisk -LUUID vs Device Names
Section titled “UUID vs Device Names”Device names are assigned in kernel detection order and are not stable across reboots. A SATA Disk that was /dev/sda today may become /dev/sdb after a hardware change. Never use device names In /etc/fstab for persistent mounts.
Definition. A UUID (Universally Unique Identifier) is a 128-bit number assigned to a filesystem At creation time. It is globally unique and does not change when the disk is moved between systems.
# View UUIDs for all block devicesblkid
# View UUID for a specific deviceblkid /dev/sda1
# Use UUID in fstab (preferred)UUID=abc12345-6789-def0-1234-567890abcdef /mnt/data ext4 defaults 0 2
# Use PARTUUID for partition-level identification (works even without filesystem)PARTUUID=12345678-1234-1234-1234-123456789abc /mnt/data ext4 defaults 0 2Prefer PARTUUID over UUID for partition identification. PARTUUID is stored in the partition Table itself (not the filesystem), so it survives filesystem recreation and works on raw partitions. Modern distributions use PARTUUID in their default fstab entries.
Partitioning Tools
Section titled “Partitioning Tools”fdisk is an interactive MBR/GPT partitioning tool. It is the most commonly used tool for quick Partitioning tasks.
# Start interactive partitioningfdisk /dev/sdb
# Common fdisk commands inside the interactive prompt:# n - new partition# d - delete partition# p - print partition table# t - change partition type# l - list known partition types# w - write changes to disk# q - quit without saving# x - extra functionality (experts only)
# Create a partition non-interactively (scriptable)echo -e "n\np\n1\n\n+100G\nw" | fdisk /dev/sdb
# List partitions (read-only, no interactive prompt)fdisk -l /dev/sdbparted
Section titled “parted”parted supports both MBR and GPT and is scriptable, making it suitable for automation.
# Start interactive modeparted /dev/sdb
# Common parted commands:# mklabel gpt - create new GPT table# mklabel msdos - create new MBR table# mkpart primary ext4 1MiB 100GiB - create partition# print - show partition table# rm 1 - remove partition 1# resizepart 1 200GiB - resize partition 1 to 200 GiB# set 1 boot on - set boot flag# unit s - switch to sector units# unit GiB - switch to GiB units
# Scriptable (non-interactive) usage:parted /dev/sdb --script mklabel gptparted /dev/sdb --script mkpart primary ext4 1MiB 100GiBparted /dev/sdb --script set 1 boot on
# Align to 1 MiB boundaries (default for GPT in modern parted)parted /dev/sdb --script align-check optimal 1ordered mode is the default and the correct choice for virtually all workloads. journal mode is Used for databases requiring absolute data integrity guarantees. writeback mode is marginally Faster but can leave stale data in files after a crash (zero-length files can appear to have old Content).
LVM Architecture
Section titled “LVM Architecture”Definition. The Logical Volume Manager (LVM) is a storage management framework that abstracts Physical storage into logical volumes. It provides a layer of indirection between physical disks and Filesystems, enabling flexible resizing, snapshots, and pooling of storage across multiple devices.
The Three-Layer Model
Section titled “The Three-Layer Model”Physical Disks / Partitions | v Physical Volumes (PV) <-- pvcreate | v Volume Groups (VG) <-- vgcreate | v Logical Volumes (LV) <-- lvcreate | v Filesystem (ext4, XFS, ...) <-- mkfsPhysical Volume (PV): A partition or whole disk that has been initialized for LVM use. Each PV Contains a header with LVM metadata and is divided into fixed-size Physical Extents (PEs). The Default PE size is 4 MiB.
Volume Group (VG): A pool of storage created from one or more PVs. The VG aggregates all PEs From its member PVs into a single addressable space. Think of a VG as a virtual disk that can span Multiple physical disks.
Logical Volume (LV): A virtual block device carved from a VG. An LV is made up of Logical Extents (LEs) that map to PEs on the underlying PVs. Filesystems are created on LVs, not on raw Partitions.
Physical Extent (PE): The smallest unit of allocation in LVM. Default size is 4 MiB. A PE on a PV maps 1:1 to a Logical Extent (LE) on an LV. When you extend an LV, you allocate additional PEs From the VG.
LVM Metadata
Section titled “LVM Metadata”LVM metadata is stored at the start of each PV (in the first few MiB). It describes:
- The VG configuration (name, UUID, extent size, attribute flags)
- The PV layout (which PEs are allocated, which are free)
- The LV definitions (name, UUID, which PEs belong to each LE)
- Snapshot relationships
Metadata is stored in circular text format at two locations on each PV for redundancy. If one copy Is corrupted, LVM can recover from the backup copy.
# View raw LVM metadata from a PVpvdisplay --maps /dev/sdb1 # show PE mappingsvgcfgrestore --list vg_name # list available metadata backups
# Metadata backups are stored here by default:ls /etc/lvm/archive/ # historical backups (vg_name_*.vg)ls /etc/lvm/backup/ # latest backup (vg_name.vg)How LVM Layers on Partitions
Section titled “How LVM Layers on Partitions”A typical production layout:
/dev/sdb (1 TiB disk) /dev/sdb1 (100 GiB partition, type 8e00 "Linux LVM") --> pvcreate --> PV /dev/sdc (1 TiB disk) /dev/sdc1 (100 GiB partition, type 8e00 "Linux LVM") --> pvcreate --> PV
VG "vg_data" = PV(sdb1) + PV(sdc1) = 200 GiB total
LV "lv_mysql" = 80 GiB from vg_data LV "lv_logs" = 40 GiB from vg_data LV "lv_backup" = 60 GiB from vg_data (with 20 GiB free in VG)You can use whole disks as PVs (pvcreate /dev/sdb) instead of partitions, but using partitions Provides a layer of protection — if LVM metadata is corrupted, partition boundaries remain visible To non-LVM tools for recovery.
LVM Operations
Section titled “LVM Operations”Physical Volume Management
Section titled “Physical Volume Management”# Initialize a partition or disk as a PVpvcreate /dev/sdb1pvcreate /dev/sdc # whole disk (wipes partition table)
# Wipe existing signatures before pvcreatewipefs -a /dev/sdb1pvcreate -ff /dev/sdb1 # -ff = force (double confirmation required)
# Display PV informationpvdisplay /dev/sdb1pvs # concise summarypvs -o+pv_name,vg_name,pe_count,free_pe # custom columns
# Remove a PV (must be freed from VG first)pvremove /dev/sdb1pvremove -ff -y /dev/sdb1 # force, no prompts
# Resize a PV after growing the underlying partitionpvresize /dev/sdb1 # auto-detect new sizepvresize --setphysicalvolumesize 200G /dev/sdb1 # set specific sizeVolume Group Management
Section titled “Volume Group Management”# Create a VG from one or more PVsvgcreate vg_data /dev/sdb1vgcreate vg_data /dev/sdb1 /dev/sdc1 /dev/sdd1
# Set PE size at creation (4 MiB default, can be 1 MiB to 64 GiB)vgcreate -s 8M vg_data /dev/sdb1 # 8 MiB PE size
# Add a PV to an existing VG (extend the VG)vgextend vg_data /dev/sdc1
# Remove a PV from a VG (must move data off it first)pvmove /dev/sdc1 # migrate all data to other PVsvgreduce vg_data /dev/sdc1 # then remove the PV
# Display VG informationvgdisplay vg_datavgs # concise summaryvgs -o+vg_name,vg_size,vg_free,pv_count # custom columns
# Activate/deactivate a VGvgchange -a y vg_data # activate (default)vgchange -a n vg_data # deactivate (LVs become unavailable)
# Rename a VG (must be inactive)vgrename old_name new_name
# Split a VG (move some PVs to a new VG)vgsplit vg_data vg_backup /dev/sdd1
# Merge two VGsvgmerge vg_data vg_backup # merge vg_backup into vg_dataLogical Volume Management
Section titled “Logical Volume Management”# Create an LVlvcreate -L 50G -n lv_mysql vg_data # 50 GiB LVlvcreate -l 100%FREE -n lv_logs vg_data # use all free spacelvcreate -l 50%FREE -n lv_temp vg_data # half of free spacelvcreate -L 100G -n lv_web -i 2 -I 64 vg_data # striped across 2 PVs, 64 KiB stripe
# Display LV informationlvdisplay /dev/vg_data/lv_mysqllvs # concise summarylvs -o+lv_name,vg_name,lv_size,lv_attr # custom columns
# Change LV namelvrename vg_data lv_mysql lv_production
# Remove an LVlvremove /dev/vg_data/lv_templvremove -f /dev/vg_data/lv_temp # force (no confirmation)
# Activate/deactivate an LVlvchange -a y /dev/vg_data/lv_mysqllvchange -a n /dev/vg_data/lv_mysql
# Set LV to active on bootlvchange --activationmode partial /dev/vg_data/lv_mysql # activate even if PVs missing
# Change LV attributeslvchange -ay -K /dev/vg_data/lv_mysql # ignore monitoring (for broken VG)LVM Command Summary
Section titled “LVM Command Summary”| Task | PV Command | VG Command | LV Command |
|---|---|---|---|
| Create | pvcreate | vgcreate | lvcreate |
| Display | pvs``pvdisplay | vgs``vgdisplay | lvs``lvdisplay |
| Extend/Grow | pvresize | vgextend | lvextend |
| Reduce/Shrink | pvresize | vgreduce | lvreduce |
| Remove | pvremove | vgremove | lvremove |
| Rename | N/A | vgrename | lvrename |
| Move data | N/A | pvmove | N/A |
| Backup metadata | N/A | vgcfgbackup | N/A |
| Restore metadata | N/A | vgcfgrestore | N/A |
Resizing
Section titled “Resizing”Extending Filesystems (Online)
Section titled “Extending Filesystems (Online)”Extending is safe to do online (while mounted). The general process is: extend the underlying Storage, then extend the LV, then extend the filesystem. Order matters — the filesystem cannot be Larger than the LV.
# Scenario: extend lv_mysql from 50 GiB to 100 GiB
# Step 1: Extend the LVlvextend -L +50G /dev/vg_data/lv_mysql # add 50 GiBlvextend -L 100G /dev/vg_data/lv_mysql # set to 100 GiBlvextend -l +100%FREE /dev/vg_data/lv_mysql # use all free space in VG
# Step 2: Resize the filesystem# For ext4:resize2fs /dev/vg_data/lv_mysql # auto-detect and fill LVresize2fs /dev/vg_data/lv_mysql 100G # specific size
# For XFS:xfs_growfs /mnt/mysql # specify mount point, not device
# Shortcut: lvextend with --resizefs does both stepslvextend --resizefs -L +50G /dev/vg_data/lv_mysql # ext4 onlylvextend -r -L +50G /dev/vg_data/lv_mysql # -r = --resizefsUse superblock version 1.0 for /boot (needed by GRUB) and 1.2 for all other arrays. Version 1.2 Places metadata at the 4 KiB offset, avoiding conflicts with partition tables and making it easy to Use whole disks as array members.
Swap Management
Section titled “Swap Management”Swap Partitions
Section titled “Swap Partitions”# Create a swap partition (type 8200 in GPT, type 82 in MBR)# Then format it:mkswap /dev/sdb1mkswap -L swap_volume /dev/sdb1 # set labelmkswap -U abc12345 /dev/sdb1 # set UUID
# Enable swapswapon /dev/sdb1swapon /dev/sdb1 -p 10 # priority -32767 to 32767 (higher = preferred)
# Enable all swap defined in /etc/fstabswapon -a
# Disable swapswapoff /dev/sdb1swapoff -a # disable all swap
# View swap usageswapon --showcat /proc/swapsfree -hSwap Files
Section titled “Swap Files”Swap files are often preferred over swap partitions because they are easier to resize and do not Require a dedicated partition.
# Create a 4 GiB swap filefallocate -l 4G /swapfile# or:dd if=/dev/zero of=/swapfile bs=1M count=4096
# Set correct permissions (swap files must be root-only)chmod 600 /swapfile
# Format as swapmkswap /swapfile
# Enableswapon /swapfile
# Persistent entry in /etc/fstab:# /swapfile none swap sw 0 0
# Verifyswapon --showZram is most useful on systems with limited RAM (embedded devices, VMs with small allocations). On Systems with ample RAM, zram adds CPU overhead for compression/decompression with little benefit. Use disk swap (or no swap) on systems with 16+ GiB of RAM.
Disk Monitoring
Section titled “Disk Monitoring”iostat
Section titled “iostat”iostat (from sysstat package) reports CPU and I/O statistics.
# Basic I/O stats (updated every 2 seconds, 5 reports)iostat 2 5
# Extended device statsiostat -x 2 5
# Human-readable outputiostat -h 2 5
# Specific deviceiostat -x /dev/sda 2 5
# Key columns in -x output:# %util - percentage of time the device was busy# await - average I/O time (ms) including queue time# r_await - average read wait time (ms)# w_await - average write wait time (ms)# svctm - average service time (ms)# aqu-sz - average queue depth# r/s, w/s - read/write operations per second# rkB/s, wkB/s - read/write throughput in KiB/s
# Persistent counter stats (since boot)iostat -x --humaniotop shows real-time I/O usage by process (requires root).
# Interactive I/O monitoriotop
# Non-interactive (batch mode)iotop -b -o -n 3# -b = batch, -o = only show processes doing I/O, -n = 3 iterations
# Show only threads (not processes)iotop -P
# Show accumulated I/O since iotop startediotop -asmartctl
Section titled “smartctl”smartctl (from smartmontools package) reads S.M.A.R.T. (Self-Monitoring, Analysis and Reporting Technology) data from disks.
# View overall healthsmartctl -H /dev/sda
# View all S.M.A.R.T. attributessmartctl -a /dev/sdasmartctl -x /dev/sda # extended (includes logs)
# Run a self-testsmartctl -t short /dev/sda # short test (1-2 minutes)smartctl -t long /dev/sda # long/extended test (hours)smartctl -t conveyance /dev/sda # vendor-specific transport test
# View test resultssmartctl -l selftest /dev/sda
# Enable SMART (if disabled)smartctl -s on /dev/sda
# View error logsmartctl -l error /dev/sda
# Automated monitoring# /etc/smartd.conf:# /dev/sda -a -m admin@example.com -M exec /usr/local/bin/smart-alertsmartctl -a /dev/sda | grep -E "Reallocated_Sector|Current_Pending|Offline_Uncorrectable"nvme-cli
Section titled “nvme-cli”For NVMe devices, use nvme-cli instead of smartctl for NVMe-specific health data.
# View NVMe device infonvme id-ctrl /dev/nvme0nvme id-ns /dev/nvme0n1
# View SMART healthnvme smart-log /dev/nvme0nvme smart-log /dev/nvme0 | grep -E "critical|temperature|percentage_used"
# View error lognvme error-log /dev/nvme0
# Get firmware versionnvme get-feature -f 2 /dev/nvme0 # firmware slot
# Format/secure erase (DESTRUCTIVE)nvme format /dev/nvme0 -s 1 -l 1 # secure erase, block erase
# Flush the namespacenvme flush /dev/nvme0n1df and du
Section titled “df and du”# Filesystem usage (human-readable)df -hdf -Th # with filesystem typedf -ih # show inodes instead of blocks
# Show specific filesystemdf -h /mnt/data
# Show only specific typedf -h -t ext4
# Directory sizesdu -sh /var/log # total sizedu -h --max-depth=1 /var # one level deepdu -ah /var/log | sort -rh | head # largest files
# ncdu — interactive disk usage analyzerncdu /varncdu -x / # stay on same filesystemncdu -e /var # enable extended infoEncryption
Section titled “Encryption”LUKS1 vs LUKS2
Section titled “LUKS1 vs LUKS2”Definition. LUKS (Linux Unified Key Setup) is a disk encryption standard that provides a Platform-independent on-disk format for encrypted block devices.
| Feature | LUKS1 | LUKS2 |
|---|---|---|
| Header version | 1 | 2 |
| Key slots | 8 | Up to 32 |
| Anti-forensic | No | Yes (memory-hard key derivation) |
| Metadata | Binary header only | JSON metadata area |
| PBKDF2 | Yes | Yes, plus Argon2i/Argon2id (stronger) |
| Token support | No | Yes (systemd, keyring, etc.) |
| Integrity | No | Optional (dm-integrity) |
| Header backup | luksHeaderBackup | luksHeaderBackup (larger header) |
# Check LUKS versioncryptsetup luksDump /dev/sdb1 | grep "Version"Creating Encrypted Volumes
Section titled “Creating Encrypted Volumes”# Format a partition as LUKS2cryptsetup luksFormat --type luks2 /dev/sdb1# WARNING: This will overwrite data on /dev/sdb1 irreversibly.
# With specific parameterscryptsetup luksFormat --type luks2 \ --cipher aes-xts-plain64 \ --key-size 512 \ --hash sha512 \ --iter-time 3000 \ /dev/sdb1
# Open (decrypt) the volumecryptsetup luksOpen /dev/sdb1 crypt_data# Creates /dev/mapper/crypt_data
# Create filesystem on the decrypted devicemkfs.ext4 /dev/mapper/crypt_data
# Mountmount /dev/mapper/crypt_data /mnt/data
# Unmount and closeumount /mnt/datacryptsetup luksClose crypt_dataKey Management
Section titled “Key Management”# Add a passphrase (key slot 0 is used at creation, this adds to slot 1)cryptsetup luksAddKey /dev/sdb1
# Remove a passphrasecryptsetup luksRemoveKey /dev/sdb1
# Change passphrasecryptsetup luksChangeKey /dev/sdb1
# Add a keyfiledd if=/dev/urandom of=/root/luks-key bs=4096 count=1chmod 400 /root/luks-keycryptsetup luksAddKey /dev/sdb1 /root/luks-key
# Open with a keyfilecryptsetup luksOpen /dev/sdb1 crypt_data --key-file /root/luks-key
# Backup LUKS header (critical — losing header means losing data)cryptsetup luksHeaderBackup /dev/sdb1 --header-backup-file /root/sdb1.header
# Restore LUKS headercryptsetup luksHeaderRestore /dev/sdb1 --header-backup-file /root/sdb1.header/etc/crypttab
Section titled “/etc/crypttab”The crypttab file defines encrypted block devices to be unlocked at boot:
# <name> <device> <keyfile> <options>crypt_root UUID=abc12345-... /crypto_key luks,discardcrypt_data /dev/disk/by-id/ata-ST5000 none lukscrypt_swap /dev/disk/by-uuid/def67890 /dev/urandom swap,cipher=aes-xts-plain64,size=256| Field | Description |
|---|---|
| Name | Mapper name (appears as /dev/mapper/<name>) |
| Device | UUID, device path, or /dev/disk/by-id/ identifier |
| Keyfile | Path to key file, none for passphrase prompt, /dev/urandom for swap |
| Options | Comma-separated: luks``discard``timeout=X``try-empty-password |
LVM on LUKS vs LUKS on LVM
Section titled “LVM on LUKS vs LUKS on LVM”Two common architectures for combining LVM and LUKS:
LVM on LUKS (recommended for full-disk encryption): /dev/sda (partitioned) /dev/sda1 (boot, unencrypted) /dev/sda2 (LUKS encrypted partition) crypt_root (decrypted block device) vg_root (LVM volume group on the decrypted device) lv_root (filesystem: /) lv_swap (swap) lv_home (filesystem: /home)
LUKS on LVM: /dev/sda (partitioned) /dev/sda1 (boot) /dev/sda2 (Linux LVM partition) vg_root lv_crypt (LUKS encrypted LV) crypt_data (decrypted block device, filesystem: /data) lv_root (unencrypted, filesystem: /)| Aspect | LVM on LUKS | LUKS on LVM |
|---|---|---|
| Security | Better (entire VG is encrypted) | LV-level granularity |
| Flexibility | Cannot have unencrypted LVs on same disk | Can mix encrypted and plain LVs |
| Snapshots | On encrypted data (transparent) | Snapshots of encrypted LVs |
| Key management | Single key unlocks entire VG | Per-LV keys |
| Boot complexity | Higher (need initramfs with cryptsetup) | Lower (root can be unencrypted) |
| Typical use case | Laptops, full-disk encryption | Servers with selective encryption |
Troubleshooting
Section titled “Troubleshooting”Recovering from LVM Metadata Loss
Section titled “Recovering from LVM Metadata Loss”# List available metadata backupsvgcfgrestore --list vg_data
# Restore from the latest backupvgcfgrestore -f /etc/lvm/archive/vg_data_00001-xxxxxx.vg vg_data
# Restore from the backup directoryvgcfgrestore --backup vg_data
# Restore from the archive directory (specific backup)vgcfgrestore -f /etc/lvm/archive/vg_data_00005-1234567.vg vg_data
# If no backups exist, attempt manual recovery# Scan for LVM physical volumespvscan --cachevgscanlvscan
# Activate all volume groupsvgchange -ay
# If a PV header is corrupted:# Attempt to restore the PV header (last resort)pvcreate --uuid <original-uuid> --restorefile /etc/lvm/archive/<file>.vg \ --force /dev/sdb1Repairing Partition Tables
Section titled “Repairing Partition Tables”# Verify GPT consistencysgdisk --verify /dev/sda
# Recover GPT from backup (at end of disk)sgdisk --load-backup=/root/sda-backup.gpt /dev/sda
# If no backup exists, rebuild GPT from disk scansgdisk --recompute-chs /dev/sda
# For MBR: use fdisk to check and fixfdisk -l /dev/sda
# Use gdisk to convert MBR to GPT (non-destructive if enough space)gdisk /dev/sda# Command: w (write, converts MBR protective to GPT)testdisk
Section titled “testdisk”testdisk is a powerful data recovery tool for recovering lost partitions and files.
# Start testdisktestdisk
# Common workflow:# 1. Select the disk# 2. Choose partition type (Intel/Mac/None)# 3. Select [Analyse] to scan for lost partitions# 4. Review found partitions# 5. Select [Write] to save recovered partition table# 6. Quit
# Recover specific files from a damaged filesystemtestdisk /dev/sdb# Navigate to [Advanced] -> [Filesystem Utils] -> [List]# Select files to copy to another diskgpart guesses lost partition types by scanning for filesystem signatures.
# Scan a disk for lost partitionsgpart /dev/sda
# Write the guessed partition tablegpart -W /dev/sda_output.txt /dev/sdaBoot Failures Related to Disks
Section titled “Boot Failures Related to Disks”# Common scenario: kernel cannot find root filesystem# Boot into recovery shell or live system, then:
# Check if VG is visiblevgscanvgchange -ay
# Check if root LV existslvs
# Mount root and check fstabmount /dev/vg_root/lv_root /mntcat /mnt/etc/fstab
# If initramfs is missing cryptsetup for LUKS:chroot /mntupdate-initramfs -u -k all # Debian/Ubuntudracut --force # RHEL/Fedora
# If /boot is on a separate partition, verify it is mounted correctly:ls /mnt/boot/vmlinuz-*LVM Activation Failures
Section titled “LVM Activation Failures”# If a VG fails to activate because a PV is missing:vgchange -ay --partial vg_data
# List missing PVspvs -a -o+missing
# Remove missing PVs from VG (data on missing PV is lost)vgreduce --removemissing --force vg_data
# If an LV is stuck in inactive state:lvchange -ay --activationmode partial /dev/vg_data/lv_mysqllvchange -ay -K /dev/vg_data/lv_mysql # ignore monitoringCommon Pitfalls
Section titled “Common Pitfalls”Shrinking in the Wrong Direction
Section titled “Shrinking in the Wrong Direction”When shrinking an LV and filesystem, the filesystem must be shrunk first, then the LV. Shrinking The LV before the filesystem truncates the filesystem and causes corruption.
CORRECT ORDER for shrinking: 1. umount 2. e2fsck -f 3. resize2fs /dev/vg/lv 50G (shrink filesystem first) 4. lvreduce -L 50G /dev/vg/lv (then shrink LV)
WRONG ORDER (will corrupt data): 1. lvreduce -L 50G /dev/vg/lv (LV shrinks, filesystem still thinks it's larger) 2. resize2fs /dev/vg/lv 50G (too late. Filesystem metadata may be beyond LV boundary)