Local storage: partitions, filesystems and volume management
Partitions, LVM volumes, filesystems: the layers of a local disk and the resize order.

Local storage on a server is built in layers, and each layer is created, grown and inspected with its own tools. A disk carries a partition table; a partition — or a whole disk — can be turned into a physical volume for LVM; physical volumes are pooled into a volume group; a logical volume is carved out of that pool; the filesystem is written on the volume; the filesystem is mounted into the directory tree. A disk that “did not grow” has almost always had one of these layers changed while the others were left alone.
disk
└─ partition table parted — mklabel, mkpart, print (Layer 1)
└─ physical volume pvcreate ┐
└─ volume group vgcreate — extents, 4 MiB default │ LVM
└─ logical volume lvcreate ┘ (Layer 2)
└─ filesystem mkfs.ext4 / mkfs.xfs (Layer 3)
└─ mount findmnt / df
grow: extend the container first, then the filesystem — lvextend -r does both
shrink: resize the filesystem first, then the container — ext4 only; XFS has no general shrink
Layer 1 — the partition table
parted creates and inspects partition tables. mklabel sets the type (msdos for MBR, gpt for a GUID table), mkpart creates a partition, and print shows the current layout. A partition is nothing more than a range of blocks recorded in that table: it does not contain a filesystem by itself, and creating one changes no data on the disk.
parted also reports alignment: align-check minimal|optimal asks whether a partition starts on a boundary the device likes. A partition that starts off the natural boundary costs performance on the media underneath, so the tool’s default alignment is the one to keep.
Layer 2 — LVM: physical volumes, volume groups and logical volumes
LVM inserts a mapping layer between the partitions and the filesystems.
pvcreateinitialises a device or partition as a physical volume (PV).vgcreatepools one or more PVs into a volume group (VG) — one address space assembled from several devices.lvcreateallocates a logical volume (LV) out of the pool’s free space, and the filesystem goes on the LV.
Inside a VG, space is handed out in extents, the smallest allocatable unit. Physical and logical extents default to 4 MiB and can be chosen when the VG is created; changing the size later means re-creating the volume group. When an LV is created, LVM finds free physical extents across the PVs and assembles them, so an LV can be larger than any one PV and can span several disks.
The whole point of the layer is flexibility: a logical volume can be grown or shrunk without destroying the data on it, unlike a standard partition, and a VG can be extended by adding another PV. Inspect with pvdisplay, vgdisplay and lvdisplay, or pvs, vgs and lvs for one line per object.
Layer 3 — the filesystem
mke2fs (invoked as mkfs.ext4) writes an ext2/ext3/ext4 filesystem, usually on a partition or an LV; mkfs.xfs writes XFS. XFS defaults to a 4096-byte block and enables metadata CRCs by default. On RHEL 9, XFS is the default filesystem and Red Hat’s recommendation for local storage, with ext4 as the familiar alternative; the practical difference for administration is that XFS only grows.
mkfs.xfs notices when its target is a logical volume and queries it for stripe geometry, so a filesystem created on an LV is aligned to the underlying layout by default; noalign disables that detection. The alignment question from Layer 1 reappears one level up.
Growing and shrinking, and the order that matters
Two rules decide almost every resize:
- XFS can only grow, and it must be mounted to be grown.
xfs_growfstakes the mount point (or the device name of a mounted XFS filesystem) and expands the filesystem into the space already available. - ext4 can grow or shrink.
resize2fsenlarges or shrinks an unmounted ext4 filesystem, and can enlarge a mounted one when the kernel supports on-line resizing. Shrinking ext4 is therefore an unmount-and-check operation.
Then the order, which is the part people get wrong:
- Growing: extend the container first, then the filesystem.
lvextend -L +10G vg/lvgrows the logical volume;lvextend -ralso resizes the filesystem in the same command. - Shrinking: shrink the filesystem first, then the container.
If the logical volume is extended without resizing the filesystem, the LV really is bigger but df still shows the old size — the free space is there and unusable. That single mismatch is a common “the disk did not grow” report.
Verifying every layer
lsblkprints the device and partition tree;lsblk --fsadds the filesystem type, label, UUID and current mount point.pvdisplay,vgdisplayandlvdisplayshow the three LVM objects, withvgs/lvsas the one-line summaries.findmntshows what is actually mounted, anddf -hshows the used and free space — the number that proves the filesystem resize happened.
Read them bottom-up: partition present, PV in the VG, LV allocated, filesystem sized, mount in place — a resize that changed only one layer shows up as a gap between two of these views.
Limits and the common error
The common error is confusing a partition with a logical volume. An LV lives on a PV, and the PV on a partition; growing the partition does not grow the LV, and growing the LV does not grow the filesystem. Each layer has its own command, and a resize is complete only when every layer under the filesystem has grown. This is why LVM earns its place — for an administrator who remembers that three layers are involved, not one.
Second, the one-way doors: XFS has no general shrink operation, so shrinking means backing up, re-creating and restoring; and mkfs destroys whatever was on the device. Extending a volume is routine; reducing one is a decision.
Level and prerequisites
L2 — operational: understand the layering, resize a volume correctly, and verify each layer. Prerequisites are the L1 block-device and filesystem model; mounting and /etc/fstab are a separate sheet. Networked storage, snapshots and RAID are out of scope here.
Where to go next
- Knowledge — the index.
- Server and virtualization — the area this sheet belongs to.
- Storage — this sheet’s node.
- Operating systems — mounting,
/etc/fstaband the permissions an application needs on the volume.
References
- util-linux — lsblk(8) — https://man7.org/linux/man-pages/man8/lsblk.8.html — the block-device tree and the
--fscolumns (FSTYPE,LABEL,UUID,MOUNTPOINTS) for verifying the layers. - util-linux — parted(8) — https://man7.org/linux/man-pages/man8/parted.8.html — the
mklabel,mkpartandprintoperations, the partition-table types, andalign-check minimal|optimalfor alignment. - Linux man-pages — mke2fs(8) — https://man7.org/linux/man-pages/man8/mke2fs.8.html — “mke2fs is used to create an ext2, ext3, or ext4 file system, usually in a disk partition”, and the
-mreserved-blocks option. - SGI/Linux man-pages — mkfs.xfs(8) — https://man7.org/linux/man-pages/man8/mkfs.xfs.8.html — the 4096-byte default block size, metadata CRCs enabled by default, and the automatic
sunit/swidthdetection on a logical volume withnoalignto disable it. - Linux man-pages — xfs_growfs(8) — https://man7.org/linux/man-pages/man8/xfs_growfs.8.html — “expand an XFS filesystem”; the filesystem must be mounted to be grown and the existing contents are undisturbed.
- e2fsprogs — resize2fs(8) — https://man7.org/linux/man-pages/man8/resize2fs.8.html — enlarging or shrinking an unmounted ext2/ext3/ext4 filesystem and enlarging a mounted one with on-line resize support.
- LVM2 — vgcreate(8) — https://man7.org/linux/man-pages/man8/vgcreate.8.html — creating a volume group from block devices and the
-s/--physicalextentsizeoption. - LVM2 — lvextend(8) — https://man7.org/linux/man-pages/man8/lvextend.8.html — extending a linear LV,
-L [Size]/-l [extents]and-r/--resizefsto resize the filesystem with the volume. - LVM2 — pvdisplay(8) — https://man7.org/linux/man-pages/man8/pvdisplay.8.html — displaying physical-volume attributes and their membership.
- LVM2 — vgdisplay(8) — https://man7.org/linux/man-pages/man8/vgdisplay.8.html — displaying volume-group attributes, size and free space.
- LVM2 — lvdisplay(8) — https://man7.org/linux/man-pages/man8/lvdisplay.8.html — displaying logical-volume paths, size and activation state.
- util-linux — findmnt(8) — https://man7.org/linux/man-pages/man8/findmnt.8.html — listing the mounted filesystems and searching for a device or mount point, the final check after a resize.
- GNU coreutils — df(1) — https://man7.org/linux/man-pages/man1/df.1.html — used and free space per mounted filesystem,
-hfor human-readable units; the number that proves a filesystem resize happened. - Red Hat — Configuring and managing logical volumes, RHEL 9: Chapter 3, Managing LVM volume groups — https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/configuring_and_managing_logical_volumes/managing-lvm-volume-groups_configuring-and-managing-logical-volumes — extents as the smallest allocatable unit with a 4 MiB default for PE/LE,
vgcreate -sto choose the extent size, and that changing it requires re-creating the VG. - Red Hat — Configuring and managing logical volumes, RHEL 9: Chapter 5, Managing LVM logical volumes — https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/configuring_and_managing_logical_volumes/managing-lvm-logical-volumes_configuring-and-managing-logical-volumes — “an administrator can grow or shrink logical volumes without destroying data, unlike standard disk partitions”,
lvcreate -n … -L …, andlvs -o lv_name,lv_size,vg_name,vg_size,vg_freebefore extending. - Red Hat — Managing file systems, RHEL 9: Chapter 1, Overview of available file systems — https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/managing_file_systems/overview-of-available-file-systems_managing-file-systems — “XFS is the default file system in RHEL” and the recommendation to deploy XFS as the local filesystem, with ext4 as the familiar alternative.
- Red Hat — Configuring and managing logical volumes, RHEL 9: Chapter 4, Basic logical volume management — https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/configuring_and_managing_logical_volumes/basic-logical-volume-management_configuring-and-managing-logical-volumes — the
lvcreate --name … --size …procedure (no size suffix defaults to MB), extending linear LVs withlvextend, andlvs -o …/vgs -o …before an extension.