There’s a very specific kind of dread that comes with a boot process stopping at Give root password for maintenance because fsck found problems it couldn’t fix automatically. I’ve been on the other side of that prompt more than once, usually after a power loss on a server without a UPS. fsck is the tool that got me out of it every time, and understanding how it actually works turned that dread into a fairly mechanical troubleshooting process. Here’s everything I know about it.
What fsck Does
fsck (File System Consistency checK) inspects a filesystem’s internal metadata — superblocks, inode tables, directory structures, block allocation bitmaps — and verifies they’re internally consistent. If it finds inconsistencies (orphaned inodes, bad block pointers, directory entries pointing nowhere, incorrect free-block counts), it can repair them, either automatically or interactively.
Like mkfs, fsck is a dispatcher, not the actual checker. Running fsck /dev/sdb1 inspects the filesystem type and calls the matching filesystem-specific checker: fsck.ext4 (technically e2fsck), fsck.xfs, fsck.vfat, fsck.btrfs, and so on. Each has its own logic because each filesystem’s on-disk structure is different.
Syntax
Verified from fsck --help on util-linux 2.39.3:
Usage:
fsck [options] -- [fs-options] [<filesystem> ...]
Check and repair a Linux filesystem.
Options:
-A check all filesystems
-C [<fd>] display progress bar; file descriptor is for GUIs
-l lock the device to guarantee exclusive access
-M do not check mounted filesystems
-N do not execute, just show what would be done
-P check filesystems in parallel, including root
-R skip root filesystem; useful only with '-A'
-r [<fd>] report statistics for each device checked
-s serialize the checking operations
-T do not show the title on startup
-t <type> specify filesystem types to be checked
-V explain what is being done
-?, --help display this help
--version display version
Key Parameters
| Option | Purpose |
|---|---|
-A | Check every filesystem listed in /etc/fstab with a non-zero fsck pass number |
-a / -p | Automatically repair without prompting (used by boot scripts) |
-r | Interactively prompt for confirmation before each repair |
-y | Assume “yes” to all repair prompts — the most common flag for unattended runs |
-n | Assume “no” to all prompts — safe, read-only inspection mode |
-f | Force a check even if the filesystem appears clean (ext-family) |
-C | Show a progress bar |
-M | Skip mounted filesystems, avoiding the dangerous case of checking a live mounted fs |
-t TYPE | Restrict checking to a specific filesystem type |
-N | Dry run — show what would run without executing |
For ext2/3/4 specifically, the real work is done by e2fsck, which adds its own rich flag set, most notably -f (force check on a clean fs), -p (preen — auto-fix safe issues, abort on anything requiring a human), and -b superblock (use an alternate/backup superblock if the primary is corrupted).
Tested Example
I built a throwaway ext4 image, checked it clean, then walked through the standard verification pattern:
$ dd if=/dev/zero of=/home/claude/test.img bs=1M count=50
$ mkfs.ext4 -F /home/claude/test.img
$ losetup -fP /home/claude/test.img
$ losetup -j /home/claude/test.img
/dev/loop0: [...] (/home/claude/test.img)
$ fsck -N /dev/loop0
fsck from util-linux 2.39.3
[/usr/sbin/fsck.ext4 (1) -- /dev/loop0] fsck.ext4 /dev/loop0
-N shows exactly which checker fsck would invoke without running it — useful for confirming dispatch before committing to a real check.
$ fsck -f -y /dev/loop0
fsck from util-linux 2.39.3
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
/dev/loop0: 11/12800 files (9.1% non-contiguous), 1840/12800 blocks
That output walking through five numbered passes is the exact structure e2fsck always follows, and it’s worth understanding each one.
The Five e2fsck Passes Explained
- Pass 1 — Inode and block checking: scans every inode, validating block pointers, file sizes, and mode bits. Detects illegal or duplicate block claims.
- Pass 2 — Directory structure: verifies directory entries point to valid inodes and directory contents are well-formed.
- Pass 3 — Directory connectivity: confirms every directory can be reached from the root, reattaching orphaned directories into
lost+foundif not. - Pass 4 — Reference counts: ensures each inode’s link count matches the number of directory entries actually referencing it.
- Pass 5 — Group summary information: recalculates free block/inode counts per block group and compares them against what the superblock and group descriptors claim, fixing mismatches.
Errors found early (Pass 1) often cascade into apparent errors in later passes, which is why a badly corrupted filesystem can report a long list of fixes in a single run — most stem from the same root cause.
Running fsck Safely
The single most important rule: never run fsck on a mounted, actively-written filesystem in repair mode. Read-write repair on a live filesystem races against the kernel’s own view of that filesystem and can cause worse corruption than what you started with. The safe patterns are:
- Unmount first:
umount /dev/sdb1 && fsck -y /dev/sdb1 - Boot from a rescue/live image and check the target disk that isn’t mounted at all
- For the root filesystem specifically,
fscknormally can’t run against it live; this is handled either at boot before it’s mounted read-write, or by scheduling a forced check on next boot
Forcing a Filesystem Check on Next Boot
sudo touch /forcefsck
On many ext-family setups this legacy flag file, checked by the init scripts, forces a check on the next boot before the root filesystem is mounted read-write. On modern systemd systems, the equivalent is:
sudo systemctl reboot --force
# or, more directly:
fsck.mode=force fsck.repair=yes # kernel boot parameter added via grub
I also frequently just directly schedule it via tune2fs mount-count-based checks:
sudo tune2fs -c 30 /dev/sda1 # force a check every 30 mounts
sudo tune2fs -l /dev/sda1 | grep -i "mount count"
Real-World Recovery Workflow
This is the sequence I actually follow when a server won’t boot after an unclean shutdown and drops to an emergency shell:
# 1. Identify the affected filesystem
lsblk -f
# 2. Confirm it's unmounted (rescue shells usually mount root read-only or not at all)
mount | grep sda1
# 3. If mounted read-write, remount read-only or unmount
mount -o remount,ro /dev/sda1
# 4. Run a forced, interactive check first to see the scope of damage
fsck -f -n /dev/sda1
# 5. If the issues look like standard, safe-to-fix inconsistencies, rerun with auto-repair
fsck -f -y /dev/sda1
# 6. Reboot and confirm system comes up clean
reboot
Running the -n (no-repair) pass first is a habit I picked up after fixing something the “wrong” way early in my career — a dry look at what’s wrong lets you judge whether this is routine post-crash cleanup or something more serious (failing disk, mismatched superblock) that deserves a backup pass before you let fsck start moving things into lost+found.
Automation Example: Scheduled Health Check Across All Mounts
#!/bin/bash
set -euo pipefail
LOGFILE="/var/log/fsck-report-$(date +%F).log"
echo "Starting non-destructive filesystem check: $(date)" | tee -a "$LOGFILE"
for fs in $(lsblk -rno NAME,MOUNTPOINT | awk '$2!="" {print "/dev/"$1}'); do
if mount | grep -q "^$fs "; then
echo "Skipping $fs (currently mounted, live check unsafe)" | tee -a "$LOGFILE"
continue
fi
echo "Checking $fs ..." | tee -a "$LOGFILE"
fsck -n "$fs" >> "$LOGFILE" 2>&1 || echo "Issues found on $fs" | tee -a "$LOGFILE"
done
echo "Completed: $(date)" | tee -a "$LOGFILE"
This intentionally only runs -n (dry, no-repair) checks on unmounted devices, generating a report I can review before ever authorizing a repair pass — that separation between “detect” and “fix” is deliberate for anything touching production data.
Troubleshooting
“UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY” — the automatic boot-time check found something it won’t fix without confirmation; boot into single-user/rescue mode and run fsck by hand with -y.
Bad superblock / “fsck.ext4: Superblock invalid” — the primary superblock is corrupted. ext4 keeps backups; find one with mke2fs -n /dev/sdX (dry run shows expected backup superblock locations) and repair with fsck -b 32768 /dev/sdX (or whichever offset applies).
fsck loops, reporting the same errors every run — usually indicates underlying hardware failure (bad sectors) rather than a simple metadata inconsistency; check smartctl -a /dev/sdX and dmesg for I/O errors before trusting further repairs.
System stuck at boot on fsck for a very large filesystem — this is expected for multi-terabyte volumes with heavy fragmentation; consider -C for progress visibility, and long-term, disable forced periodic checks on large data volumes (tune2fs -c 0 -i 0) if you rely on other integrity mechanisms (RAID scrubbing, backups) instead.
Performance Optimization
- Skip full inode scans when unnecessary — a normal
fsckrun on a cleanly unmounted ext4 filesystem exits almost instantly because the superblock’s “clean” flag is set; only pass-fwhen you specifically need to force a full pass. - Use
-Pfor parallel checks across multiple independent devices during boot or maintenance windows, cutting wall-clock time significantly on multi-disk servers. - Disable periodic forced checks on large SSD-backed volumes with
tune2fs -c 0 -i 0, since the checks were originally designed around spinning-disk failure patterns and now mostly just add downtime for volumes protected by RAID/redundant storage or frequent backups. - XFS note:
xfs_repair(fsck.xfs’s actual worker) does not run online consistency checks the way e2fsck does; XFS relies more heavily on its journal for crash recovery, and fullxfs_repairruns are comparatively rare and reserved for real corruption, not routine boot checks.
fsck vs Related Commands
| Command | Purpose |
|---|---|
fsck / fsck.* | Checks and repairs an existing filesystem’s metadata consistency |
e2fsck | The actual ext2/3/4 checker invoked by fsck.ext4 |
xfs_repair | XFS’s equivalent checker/repair tool, invoked via fsck.xfs (which mostly just defers) |
badblocks | Scans for physical bad sectors, a lower layer than filesystem metadata |
smartctl | Reads drive health/SMART data, useful to rule out hardware failure before blaming the filesystem |
mkfs | Creates a fresh filesystem; the opposite operation of repairing an existing one |
Security Implications
Automatic, unattended -y repairs are convenient but not risk-free: badly timed automatic repairs on a filesystem with real corruption can silently relocate or delete data into lost+found without a human reviewing what was lost. On systems holding data you can’t afford to lose, I always keep verified backups current enough that an aggressive fsck -y run is never itself the single point of failure. Also worth noting: fsck typically requires root, since arbitrary read/write access to raw block devices is inherently privileged — treat any account with permission to run it against production disks as having effectively full data access.
Distribution Compatibility
fsck and its ext-family backend e2fsck (from e2fsprogs) ship on every major distribution by default, since virtually every distro needs to check its own root filesystem at boot. XFS tooling (xfsprogs) and Btrfs tooling (btrfs-progs) may need explicit installation on minimal images. Boot-time integration differs slightly: systemd-based distros (Ubuntu, Fedora, Debian, Arch, RHEL 8+) use systemd-fsck units gating mount ordering, while older SysV-init systems used /etc/init.d scripts calling fsck -A directly — functionally similar outcomes, different orchestration.
fsck and Journaling: Why Modern Filesystems Need It Less Often
A question I get asked often: if ext4, XFS, and Btrfs all maintain a metadata journal specifically to survive unclean shutdowns, why does fsck still exist and matter? The journal handles the common case — replaying incomplete transactions after a crash so metadata returns to a consistent state, which happens automatically at mount time without any explicit fsck invocation needed. What the journal does not protect against is corruption from causes outside its scope entirely: failing storage hardware silently returning bad data, bugs in the filesystem driver itself, bit flips from unreliable RAM (which is exactly why ECC memory matters more on storage servers than people often assume), or manual/administrative mistakes like a botched dd or partition table edit. fsck‘s full structural walk exists precisely to catch that broader class of problem that journal replay was never designed to address, which is why periodic full checks still have value even on modern, robustly-journaled filesystems, particularly on hardware you have reason to distrust.
Checking Filesystem Status Without a Full Scan
Before committing to a potentially long fsck -f run on a large volume, dumpe2fs gives a fast, read-only look at an ext4 filesystem’s recorded state, including whether it was cleanly unmounted:
dumpe2fs -h /dev/sda1 | grep -i state
Filesystem state: clean
If this reports clean, a routine fsck without -f will exit almost instantly, since the filesystem itself is asserting no repair is needed — useful context before scheduling a maintenance window around what you assume will be a lengthy check.
fsck Exit Codes for Scripting
fsck‘s exit code is a bitmask, not a simple success/failure boolean, and any automation branching on its result needs to account for this:
| Bit value | Meaning |
|---|---|
| 0 | No errors |
| 1 | Filesystem errors corrected |
| 2 | System should be rebooted |
| 4 | Filesystem errors left uncorrected |
| 8 | Operational error |
| 16 | Usage or syntax error |
| 32 | Fsck canceled by user request |
| 128 | Shared library error |
A script checking $? -eq 0 alone will miss the meaningfully different case of “errors were corrected but a reboot is now required” (exit code 2) — worth handling explicitly in any automated boot-time or maintenance-window fsck orchestration rather than treating every non-zero result identically.
Summary
fsck is the safety net underneath every Linux filesystem, and understanding its five-pass model, the difference between dry-run inspection and destructive repair, and the hard rule against checking mounted filesystems turns what feels like an emergency into a routine, predictable procedure. I treat a clean fsck -n pass as a diagnostic first step, and only escalate to -y once I understand what’s actually wrong.
References
- util-linux —
fsck(8): https://man7.org/linux/man-pages/man8/fsck.8.html - e2fsprogs —
e2fsck(8): https://man7.org/linux/man-pages/man8/e2fsck.8.html - XFS Documentation —
xfs_repair(8): https://man7.org/linux/man-pages/man8/xfs_repair.8.html - Red Hat Documentation — Filesystem Recovery: https://access.redhat.com/documentation/
- Ubuntu Server Guide — Storage Administration: https://ubuntu.com/server/docs