Filesystems¶
A filesystem organizes a block device into files, directories and metadata. The choice between ext4, XFS and Btrfs decides how a volume can be resized, checked and repaired later.
Track: Core · Interview weight: Med
Must-Know Facts¶
| Fact | Value | Verify with |
|---|---|---|
| Defaults | RHEL: XFS; Ubuntu and Debian: ext4 | findmnt -no FSTYPE / |
| Create | mkfs.ext4, mkfs.xfs, mkfs.vfat -F 32, mkfs.btrfs; -L sets a label | lsblk -f |
| Existing signature | mkfs.xfs and mkfs.btrfs refuse without -f; mke2fs asks on a terminal | wipefs <dev> |
| Resize | ext4: resize2fs, grows online, shrinks offline; XFS: xfs_growfs <mountpoint> grows only (apart from an experimental trim of the last allocation group) | df -h |
| Check and repair | ext4: e2fsck (unmounted); XFS: xfs_repair (unmounted; -n checks only) | exit status |
| Inspect and label | tune2fs -l, dumpe2fs -h, xfs_info; tune2fs -L, xfs_admin -L (unmounted), fatlabel | blkid |
| Reserved blocks | ext4 keeps 5% for root; tune2fs -m 1 lowers it | tune2fs -l |
| Inodes | ext4 fixes the count at creation (mkfs.ext4 -i, -N); XFS allocates them dynamically | df -i |
| Backup superblocks | ext4 keeps copies; mke2fs -n lists them, e2fsck -b <block> uses one | dumpe2fs <dev> |
| Btrfs | Copy-on-write, subvolumes, snapshots, checksums; Fedora and SUSE default; removed from RHEL 8 | btrfs filesystem show |
Creating Filesystems¶
The partitions from Partitioning get ext4, XFS and FAT32:
sudo mkfs.ext4 -L appdata /dev/loop0p3
sudo mkfs.xfs -L logs /dev/loop1p2
sudo mkfs.vfat -F 32 -n EFI /dev/loop1p1
lsblk -f /dev/loop0 /dev/loop1
sudo mkfs.xfs /dev/loop0p1; echo "rc=$?"
Output:
mke2fs 1.47.1 (20-May-2024)
# ... (trimmed)
Creating filesystem with 307200 1k blocks and 76912 inodes
Filesystem UUID: 683f9429-6087-4267-a91e-79c8e5787e21
# ... (trimmed)
Creating journal (8192 blocks): done
# ... (trimmed)
meta-data=/dev/loop1p2 isize=512 agcount=4, agsize=65536 blks
# ... (trimmed)
mkfs.fat 4.2 (2021-01-31)
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
loop0
├─loop0p3 ext4 1.0 appdata 683f9429-6087-4267-a91e-79c8e5787e21
├─loop0p1 ext4 1.0 bba51a4b-2c75-451f-82d9-e24645d02771
└─loop0p2
loop1
├─loop1p1 vfat FAT32 EFI 7C6C-49E7
├─loop1p2 xfs logs 875008e0-8369-4a85-b33f-06333db4f59d
└─loop1p3
mkfs.xfs: /dev/loop0p1 appears to contain an existing filesystem (ext4).
mkfs.xfs: Use the -f option to force overwrite.
rc=1
mke2fs chose 1 KiB blocks because the partition is small; volumes above 512 MiB get 4 KiB blocks. XFS divided the volume into four allocation groups (agcount=4), which it can update in parallel. mkfs.xfs refused to overwrite the existing ext4 signature on loop0p1.
Inspecting and Tuning¶
sudo tune2fs -l /dev/loop0p3 | grep -E '^(Filesystem volume name|Filesystem state|Inode count|Block count|Reserved block count|Block size|Filesystem features)'
sudo tune2fs -m 1 -L appdata2 /dev/loop0p3
sudo xfs_admin -L weblogs /dev/loop1p2
sudo blkid /dev/loop0p3 /dev/loop1p2
Output:
Filesystem volume name: appdata
Filesystem features: has_journal ext_attr resize_inode dir_index filetype extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Filesystem state: clean
Inode count: 76912
Block count: 307200
Reserved block count: 15360
Block size: 1024
tune2fs 1.47.1 (20-May-2024)
Setting reserved blocks percentage to 1% (3072 blocks)
writing all SBs
new label = "weblogs"
/dev/loop0p3: LABEL="appdata2" UUID="683f9429-6087-4267-a91e-79c8e5787e21" BLOCK_SIZE="1024" TYPE="ext4" PARTUUID="285f8258-03"
/dev/loop1p2: LABEL="weblogs" UUID="875008e0-8369-4a85-b33f-06333db4f59d" BLOCK_SIZE="512" TYPE="xfs" PARTLABEL="data" PARTUUID="b7beaffc-d0cc-4a24-b644-b424ca268294"
PARTUUID and PARTLABEL belong to the partition table entry, UUID and LABEL to the filesystem. The 5% reserve (15360 blocks) lets root processes and the allocator work when users have filled the volume; on a large data volume, 1% is usually enough.
Checking and Repairing¶
Repair tools need the filesystem unmounted. With it mounted, e2fsck -n only reads and xfs_repair refuses:
sudo mkdir -p /srv/app /srv/logs
sudo mount /dev/loop0p3 /srv/app
sudo mount /dev/loop1p2 /srv/logs
df -i /srv/app /srv/logs
sudo e2fsck -n /dev/loop0p3; echo "rc=$?"
sudo xfs_repair -n /dev/loop1p2; echo "rc=$?"
Output:
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/loop0p3 76912 11 76901 1% /srv/app
/dev/loop1p2 524288 3 524285 1% /srv/logs
e2fsck 1.47.1 (20-May-2024)
Warning! /dev/loop0p3 is mounted.
Warning: skipping journal recovery because doing a read-only filesystem check.
appdata2: clean, 11/76912 files, 29591/307200 blocks
rc=0
xfs_repair: /dev/loop1p2 contains a mounted and writable filesystem
fatal error -- couldn't initialize XFS library
rc=1
df -i shows the fixed ext4 inode count next to the XFS count, which grows with use. After unmounting the ext4 volume:
sudo umount /srv/app
sudo e2fsck -f /dev/loop0p3; echo "rc=$?"
sudo e2fsck -f -y /dev/loop0p3; echo "rc=$?"
Output:
e2fsck 1.47.1 (20-May-2024)
e2fsck: need terminal for interactive repairs
rc=8
e2fsck 1.47.1 (20-May-2024)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
appdata2: 11/76912 files (0.0% non-contiguous), 29591/307200 blocks
rc=0
e2fsck exit codes are a bit mask: 0 clean, 1 errors corrected, 4 errors left, 8 operational error. xfs_repair without -n repairs; -L zeroes a damaged log and loses its last transactions, so it is the last resort after a mount has failed to replay the log.
Never repair a mounted filesystem
Writing to structures the kernel is also changing corrupts the volume. Unmount it, or check the root filesystem from rescue mode or at boot (fsck.mode=force on the kernel command line).
Shrinking¶
The ext4 volume is unmounted and freshly checked, which resize2fs requires before shrinking; XFS stays mounted at /srv/logs:
sudo resize2fs /dev/loop0p3 200M; echo "rc=$?"
sudo xfs_growfs -D 200000 /srv/logs 2>&1 | tail -1
sudo xfs_growfs -D 150000 /srv/logs >/dev/null; echo "rc=$?"
Output:
resize2fs 1.47.1 (20-May-2024)
Resizing the filesystem on /dev/loop0p3 to 204800 (1k) blocks.
The filesystem on /dev/loop0p3 is now 204800 (1k) blocks long.
rc=0
data blocks changed from 262144 to 200000
[EXPERIMENTAL] try to shrink unused space 150000, old size is 200000
xfs_growfs: XFS_IOC_FSGROWFSDATA xfsctl failed: Invalid argument
rc=1
XFS shrank only while the new end stayed inside the last allocation group (4 groups of 65536 blocks, so the last one starts at block 196608); the kernel refuses to remove a whole group.
Shrink the filesystem before the partition or volume under it
Reducing the device first cuts off the end of the filesystem. For XFS, the supported way to get a smaller volume is to back up, recreate and restore.
Recovering from a Damaged Superblock¶
The first command zeroes the ext4 primary superblock on purpose:
sudo dd if=/dev/zero of=/dev/loop0p3 bs=1024 seek=1 count=1 status=none
sudo mount /dev/loop0p3 /srv/app; echo "rc=$?"
sudo dumpe2fs /dev/loop0p3 2>&1 | head -3
sudo mke2fs -n /dev/loop0p3 | tail -3
sudo e2fsck -y -b 8193 /dev/loop0p3 | tail -4; echo "rc=${PIPESTATUS[0]}"
sudo mount /dev/loop0p3 /srv/app && df -h /srv/app
Output:
mount: /srv/app: wrong fs type, bad option, bad superblock on /dev/loop0p3, missing codepage or helper program, or other error.
dmesg(1) may have more information after failed mount system call.
rc=32
dumpe2fs 1.47.1 (20-May-2024)
dumpe2fs: Bad magic number in super-block while trying to open /dev/loop0p3
Couldn't find valid filesystem superblock.
mke2fs 1.47.1 (20-May-2024)
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729, 204801, 221185
e2fsck 1.47.1 (20-May-2024)
FIXED.
appdata2: ***** FILE SYSTEM WAS MODIFIED *****
appdata2: 11/50600 files (0.0% non-contiguous), 22461/204800 blocks
rc=1
Filesystem Size Used Avail Use% Mounted on
/dev/loop0p3 179M 14K 173M 1% /srv/app
mke2fs -n prints what it would do without writing, so its backup locations are right only with the same options as the original mkfs. Exit status 1 means errors were corrected, and the kernel log shows that mount also probed the device as XFS (XFS (loop0p3): Invalid superblock magic number).
Common Errors¶
e2fsck: need terminal for interactive repairs¶
Cause: e2fsck -f wants to ask before each fix, and no terminal is attached (a script, cloud-init or Ansible).
Fix: -p repairs safe problems automatically, -y answers yes to everything, -n only checks.
Interview Checkpoints¶
L1: What is the difference between ext4 and XFS?
Say first: both are journaling filesystems; ext4 can shrink and fixes its inode count at creation, while XFS scales better for large files and parallel I/O, allocates inodes dynamically and cannot shrink.
Proof: df -i on both; xfs_info shows allocation groups.
Follow-up: Which one does RHEL install by default, and what does that mean for reducing a logical volume?
L1: What does the journal protect?
Say first: it records metadata changes before they are applied, so after a crash the kernel replays the journal instead of scanning the whole filesystem.
Proof: tune2fs -l lists has_journal; xfs_info shows the internal log.
Follow-up: Why does ext4's default data=ordered mode not journal file contents?
L2: Format a new partition with XFS, label it and find its UUID.
Say first: mkfs.xfs -L, then read the UUID with blkid or lsblk -f.
Proof: sudo mkfs.xfs -L logs /dev/sdb2; sudo blkid /dev/sdb2.
Follow-up: How do you change the label later? (xfs_admin -L, unmounted.)
L2: Check an ext4 filesystem non-interactively from a script.
Say first: unmount it and run e2fsck -f -p, or -y when every fix should be accepted.
Proof: sudo e2fsck -f -p /dev/sdb1; echo $?.
Follow-up: What does exit status 4 mean? (Errors were left uncorrected.)
L3: An ext4 volume will not mount: wrong fs type, bad superblock. What do you do?
Say first: confirm the type with blkid, read the kernel message, then check the filesystem against a backup superblock.
Proof: sudo dmesg | tail; sudo mke2fs -n <dev>; sudo e2fsck -b 32768 <dev>.
Follow-up: Why must mke2fs -n get the same options as the original mkfs?
L3: df shows free space, but creating files fails with No space left on device. Why?
Say first: the ext4 volume has run out of inodes.
Proof: df -i shows IUse% 100%; find <mount> -xdev -type f | cut -d/ -f2-3 | sort | uniq -c | sort -n finds the directory with the most files.
Follow-up: How do you prevent it on a volume for small files? (mkfs.ext4 -i with a smaller bytes-per-inode ratio, or XFS.)
Related¶
- Partitioning: the partitions formatted here
- Mounting and fstab: mounting by UUID or label
- Resizing and Cloud Disks: growing filesystems online
- Disk Usage: blocks and inodes running out
Captured on Rocky Linux 10.2 (iximiuz Labs microVM, kernel 6.1.167, xfsprogs 6.16.0, e2fsprogs 1.47.1), 2026-09.