Filesystems, end to end: create, grow, shrink, verify
Most filesystem tutorials are one command: mkfs.ext4 /dev/sdb1 and done. That
gets you a filesystem, but not the model behind it. The model is what you need
when the disk is full, the partition is wrong, or the filesystem is on fire.
This is the hub for a series about the operations that matter, each one demonstrated on a real block device in a disposable lab:
- Create it on a partition (or a pool).
- Inspect it: geometry, UUID, label, free space.
- Grow it — online if the filesystem allows it.
- Shrink it — in the safe order, offline where the filesystem demands it.
- Check and repair it.
- Snapshot, replicate and compress it.
- Verify it with a scrub.
Each part is a set of short, silent videos, and this page is the written companion. The point is not to memorise flags; it’s to know which of these operations your filesystem can do, in which order, and what it costs.
The model: device, partition, filesystem
Almost every mistake in this area comes from mixing up three layers:
disk /dev/sdb
└── partition /dev/sdb1
└── filesystem ext4 / xfs / btrfs / ufs / ntfs
A filesystem lives inside something: a partition, an LVM volume, or a whole disk. Growing the filesystem without growing the container does nothing; growing the container without growing the filesystem leaves free space unused. Shrinking is the reverse order, and some filesystems are designed so they can’t do it at all.
ZFS is the main exception: it does not use partitions the same way. You give it
devices (or partitions) and it builds a pool; datasets are the filesystems
inside the pool. APFS is the other: a container holds volumes. That is why
the ZFS page starts with zpool create, not mkfs, and the APFS page with
diskutil eraseDisk.
The matrix
| Operation | ext4 | XFS | Btrfs | ZFS | UFS | NTFS | APFS |
|---|---|---|---|---|---|---|---|
| Create | mkfs.ext4 | mkfs.xfs | mkfs.btrfs | zpool create + zfs create | newfs | Format-Volume | diskutil eraseDisk |
| Grow | growpart + resize2fs (online) | growpart + xfs_growfs (online) | btrfs filesystem resize (online) | grow the pool; datasets follow | gpart resize + growfs (online) | Resize-Partition (online) | resizeContainer (online) |
| Shrink | resize2fs (offline) + partition | can’t | btrfs filesystem resize (online) | only via zpool remove (no raidz) | can’t (growfs only) | Resize-Partition (online) | resizeContainer (online) |
| Check / repair | e2fsck (offline) | xfs_repair (offline) | btrfs check (offline) + scrub (online) | zpool scrub (online) | fsck_ufs (offline) | Repair-Volume -Scan (online) / chkdsk /f (offline) | verifyVolume (online) / fsck_apfs -n (offline) |
| Snapshots | via LVM | via LVM | native (subvolume) | native (dataset) | mksnap_ffs (limited) | VSS | Time Machine local |
| Compression | — | — | zstd | zstd | — | compact (per file/folder) | per file (ditto --hfsCompression; no diskutil switch) |
| Replicate | rsync | rsync | btrfs send/receive | zfs send/receive | rsync | robocopy / rsync | rsync |
Two asymmetries are worth internalising:
- XFS and UFS can’t shrink, and ZFS only via
zpool remove. XFS and UFS will refuse; ZFS can only shrink by evacuating a whole vdev withzpool remove, and not at all in raidz pools. The practical answer is backup, recreate smaller, restore — or pick a filesystem that can shrink. - Snapshots are not backups. They live on the same storage as the data. They are for experiments and instant rollbacks; 3-2-1 is still your job.
The filesystems
- ext4 — the default Linux filesystem: create, reclaim the 5% root reservation, grow, shrink. · playlist
- XFS — grow online, repair offline, and why it can’t shrink. · playlist
- Btrfs — subvolumes, snapshots, zstd compression, scrub. · playlist
- ZFS — pools and datasets, snapshots and rollback, send/receive, compression, scrub. · playlist
- FreeBSD — UFS (gpart, newfs, growfs, fsck_ufs) and native ZFS on the same disk. · playlist
- Windows — NTFS: Initialize-Disk, Resize-Partition both ways, compact, Repair-Volume. · playlist
- macOS — APFS: containers and volumes, resizeContainer,
clones with
cp -c, verify. · playlist
Each page links to its videos when they are published, and each video links back here.
Where this ends
That’s the full set for now: four Linux filesystems, FreeBSD, Windows and macOS. The model stays the same across all of them; only the commands change.
The one rule throughout: run it on a scratch disk first. A lab you can destroy is what makes the dangerous operations teachable.