Anders Tall

XFS, end to end: grow it, repair it, and why it can't shrink

3 min read

XFS is the default on RHEL, AlmaLinux and Rocky, and the filesystem of choice for large files and parallel I/O. It’s also the clearest example of an asymmetric filesystem: it grows beautifully and, in practice, never shrinks. The videos show the commands; this page explains why they work.

Same model as always: disk → partition → filesystem, on a disposable 2 GB scratch disk.

Create it

sudo parted -s /dev/sdb mklabel gpt
sudo parted -s /dev/sdb mkpart primary xfs 1MiB 1GiB
sudo mkfs.xfs -f -L data /dev/sdb1
sudo mkdir -p /mnt/xfslab
sudo mount /dev/sdb1 /mnt/xfslab

mkfs.xfs prints the geometry (block size, allocation groups, log); -L sets the label; -f forces it over an existing signature. Prove it with the same round-trip as any filesystem: write, unmount, mount, read.

On GPT, the first mkpart argument (primary) is the partition’s name, not a type. data would be a clearer name; either works.

echo 'hello from xfs' | sudo tee /mnt/xfslab/hello.txt
sudo umount /mnt/xfslab
sudo mount /dev/sdb1 /mnt/xfslab
sudo cat /mnt/xfslab/hello.txt
sudo xfs_info /mnt/xfslab
sudo blkid /dev/sdb1

Watch on YouTube →

Grow it

XFS grows online, while mounted:

sudo growpart /dev/sdb 1        # grow the partition first
sudo xfs_growfs /mnt/xfslab     # then the mounted filesystem

xfs_growfs takes the mountpoint, not the device. It extends the filesystem to fill the partition. This is the normal XFS growth path: add space, grow the partition, grow the mount.

growpart is not always installed: on Debian/Ubuntu it comes from cloud-guest-utils, on the RHEL family from cloud-utils-growpart.

Watch on YouTube →

Check and repair it

xfs_repair is an offline tool. Unmount first, check without modifying, then repair:

sudo umount /mnt/xfslab
sudo xfs_repair -n /dev/sdb1     # check only
sudo xfs_repair /dev/sdb1        # repair
sudo mount /dev/sdb1 /mnt/xfslab

On a clean filesystem the repair is a no-op with a full phase report — which is exactly what you want to see before you trust it. Never run xfs_repair on a mounted filesystem.

If the filesystem was not unmounted cleanly, xfs_repair refuses to run and points at -L, which zeroes the log. That can lose the last transactions, so mount and unmount the filesystem first and let the log replay; use -L only as a last resort.

Watch on YouTube →

Why XFS can’t shrink

This is the part of the series that matters most. Trying is the proof:

sudo xfs_growfs -D 262144 /mnt/xfslab; echo exit: $?
# xfs_growfs: XFS_IOC_FSGROWFSDATA xfsctl failed: Invalid argument
# exit: 1

The filesystem stays exactly the size it was. XFS is built around allocation groups and a design that favours parallel allocation and large files. There is no practical in-place shrink path: newer kernels and xfsprogs can trim unused space from the tail of the last allocation group (still experimental), but they can’t remove a whole AG — which is exactly what a 2 GB → 1 GiB shrink asks for. The practical alternatives are:

  1. Back up, recreate smaller, restore. xfsdump/xfsrestore, or rsync into a new, smaller filesystem.
  2. Pick a filesystem that can shrink (ext4 or Btrfs) when you know the disk will need to get smaller.

That asymmetry is not a bug to work around; it is a property to plan for.

Watch on YouTube →

What to remember

Part of Filesystems, end to end.

#xfs #filesystem #linux #storage #homelab #devops #terminal