lvextend runs without error, genuinely increases the logical volume’s size as requested, and yet df -h keeps showing exactly the same size as before for the filesystem mounted on it. This isn’t a silent lvextend failure: the logical volume and the filesystem it contains are two distinct layers, and LVM never resizes the second one automatically.
Two layers, two different commands
LVM manages disk space at a block level, independent of the filesystem using it: lvextend changes the logical volume’s own size (the available block space), but the filesystem formatted inside it (ext4, xfs) keeps believing it occupies the old size until a filesystem-specific command explicitly tells it about the change.
# Step 1: grows the logical volume itself,
# the available block space genuinely increases
lvextend -L +10G /dev/vg-data/lv-data
# Step 2 (mandatory, separate): informs the
# ext4 filesystem of the new available size
resize2fs /dev/vg-data/lv-data
# Step 2 for XFS: the command and its behavior
# differ from ext4, xfs_growfs takes the mount
# point, not the device
xfs_growfs /data
Why df isn’t lying
df faithfully reports the filesystem’s size as it knows itself, not the underlying logical volume’s size: after an lvextend without the corresponding resize step, df shows exactly the truth, a filesystem that simply hasn’t been informed yet of the extra available space.
# Confirms the logical volume's actual size
lvdisplay /dev/vg-data/lv-data | grep "LV Size"
# Confirms (or disproves) that the filesystem
# has actually been informed of that new size
df -h /data
Combining both steps into one command
lvextend accepts an option that automatically triggers the corresponding filesystem resize, removing the risk of forgetting the second step.
# -r automatically triggers resize2fs or xfs_growfs
# depending on the detected filesystem type
lvextend -r -L +10G /dev/vg-data/lv-data
The connection to disk space already covered
This trap is the exact mirror of the one already documented on inode exhaustion: in both cases, a tool faithfully reports a real filesystem state that doesn’t match the operator’s first intuition, available block space being just one dimension worth checking explicitly rather than assumed resolved by a single command.
Takeaway
lvextend only grows the logical volume, never the filesystem it contains: df keeps showing the old size until a dedicated command (resize2fs for ext4, xfs_growfs for XFS) explicitly informs the filesystem of the change. lvextend’s -r option combines both steps into a single command, removing the risk of forgetting the second one. This two-layer behavior mirrors the same principle already seen with inode exhaustion: disk space has several independent dimensions, each deserving an explicit check rather than an assumption.