Filesystems & mounts
ext4, xfs, mount options, and repair.
A raw disk is a warehouse full of identical, numbered boxes. Nothing in it knows what a file is, which boxes belong together, or which ones are empty. A filesystem is the warehouse's inventory clerk. It keeps the ledger that says the file /etc/shadow lives in these blocks, was last written on Tuesday, and only root may read it. On Linux, the filesystem is the layer that turns a partition or logical volume (a slice of raw disk the system treats as one unit) into named files and directories you can actually open.
Ext4 And Xfs, And Why The Choice Rarely Bites
ext4 (the fourth extended filesystem, the long-standing general-purpose default on Debian and Ubuntu) is reliable and boringly well understood. If you do nothing special, this is what you get, and for most workloads that is the right answer. xfs (a high-performance filesystem that Silicon Graphics wrote for their workstations, now the default on Red Hat Enterprise Linux and its rebuilds) is built for large files and for many processes reading and writing at the same time. For a busy database or a box shuffling huge media files, xfs pulls ahead. For most servers either is fine, and the difference only shows at the extremes of size and concurrency.
Both are journaling filesystems. A journal here works like a chef who writes "about to move the roast from oven to counter" on a notepad before doing it. If the power dies mid-step, you read the last note and either finish the action or undo it cleanly, instead of finding a half-updated mess. The filesystem writes its intended change to a small log first, then performs it. After a crash, the kernel (the core of the operating system that talks directly to the hardware) replays or discards that log on the next mount, so you get a consistent filesystem back rather than a corrupt one. This is why you almost never run a manual repair on a modern box.
One practical difference is worth knowing before you commit. ext4 can grow and shrink. xfs can only grow, never shrink. If you might ever need to hand space back from a filesystem, that constraint alone can decide it for you.
Seeing What You Have
Before you touch anything, look. lsblk -f draws the block-device tree and hangs each filesystem's type, label, UUID (universally unique identifier, a stable random id written into the filesystem when it is created) and mount point off it. df (disk free) tells you how full each mounted filesystem is; the -T flag adds a Type column and -h makes the sizes human-readable. du answers the other question, which directories are actually eating the space. Between them you see the layout, the free space, and the hog, without guessing.
Mounting, And The File That Survives Reboots
A fresh filesystem is a room with no door. Mounting is hanging the door: you attach the filesystem to a point in the directory tree, and from then on everything under that point lives on that disk. The mount command does it right now, for this boot, and forgets it at reboot. To make a mount stick, you write it into /etc/fstab (the filesystem table), the list the system reads at every boot to decide what to attach where. First you need a filesystem to mount, which mkfs (make filesystem) creates, and its UUID, which blkid prints.
Each line in fstab has six fields: the device, where to mount it, the filesystem type, a comma-separated list of options, and two small numbers. Identify the device by UUID, not by /dev/sdb1. Kernel device names are assigned in the order disks are found, so add a drive and yesterday's sdb can come up as sdc today, while the UUID never moves. The fifth field (dump) is a leftover from an old backup tool and is 0 on every modern system. The sixth field (pass) sets the boot-time check order: 1 for the root filesystem, 2 for the rest, 0 to skip. xfs always uses 0 there, because it never checks at boot; it recovers its journal on mount instead.
# <device> <mountpoint> <type> <options> <dump> <pass>UUID=8f3a2b1c-4d5e-6f70-8a9b-0c1d2e3f4a5b / ext4 defaults,noatime 0 1UUID=b1c2d3e4-5f60-7182-93a4-b5c6d7e8f901 /srv/app xfs defaults,noatime 0 0UUID=c3d4e5f6-6071-8293-a4b5-c6d7e8f90123 /var/log ext4 defaults,nofail,nodev,nosuid 0 2UUID=d4e5f6a7-7182-93a4-b5c6-d7e8f9012345 /tmp ext4 defaults,nodev,nosuid,noexec 0 2# nofail: don't block boot if the disk is missing. Find a UUID with: blkid /dev/data-vg/app
After you edit fstab, do not reboot on faith. mount -a tries to mount everything in the file that is not already mounted, against the running system. If a line is wrong, you find out now, at a shell, instead of at the next boot with no shell. findmnt --verify goes further and parses the whole file for mistakes without mounting anything.
Mount Options Are A Security Control
Options are the house rules for a mounted filesystem, and some of them are security controls, not tuning knobs. Start with the tame one. noatime tells the filesystem to stop recording a "last read" timestamp every time a file is opened. By default Linux uses relatime, which already writes that timestamp rarely; noatime turns it off entirely, which on a busy filesystem is a real cut in write traffic. The cost lands on defenders: access times are one signal in an intrusion timeline, and noatime erases it, so weigh that on hosts you may have to investigate later.
The three that matter for hardening are nosuid, nodev, and noexec. Here is the attack they blunt. The setuid bit on a program tells the kernel to run it as the file's owner, so a program owned by root runs as root no matter who launches it. That is how sudo works, and it is also the backbone of a classic backdoor. An attacker who gets root even once can leave a root-owned copy of a shell with the setuid bit set sitting in a writable directory. From then on any user who runs it lands in a root shell, no password asked. Mount that directory nosuid and the kernel ignores the setuid bit there, so the backdoor is dead weight. nodev tells the kernel to ignore device nodes on the mount, which stops an attacker planting a fake /dev/sda in a writable directory to read the raw disk straight past file permissions. noexec refuses to run any binary from the mount at all. On the directories every user can write to (/tmp, /var/tmp, /dev/shm), those three together take away the easiest place to stage and launch a payload.
Check what is actually applied with findmnt, which shows the real options the kernel is using, not what you hoped you set. This is also how you find gaps. On a stock Ubuntu box, /dev/shm (a RAM-backed shared-memory filesystem) comes mounted nosuid,nodev but without noexec, which is exactly why some malware runs straight out of it. findmnt also reveals bind mounts and overlay mounts, the kind an attacker uses to shadow a legitimate path with their own file, so read it carefully on any host you suspect.
Keep noexec in perspective. It stops you running a binary from the mount directly, but an interpreter is itself a program the kernel is glad to load, and it will happily run a script you hand it. python3 /tmp/x.py, bash /tmp/x.sh, or pulling code in as a shared library all walk around the flag. Treat nodev, nosuid, and noexec on /tmp and its siblings as one layer that clears out the laziest attacks, not a guarantee that nothing runs from there.
Checking And Repairing
When a filesystem does get damaged, from a bad shutdown or a dying disk, the check-and-repair tools can only work safely on an unmounted filesystem. Repairing a mounted filesystem underneath the running kernel is like rebuilding an engine while the car is driving. So you unmount first, then check. For ext4 the tool is fsck (filesystem check), usually run as fsck -fy: -f forces a full check even if the superblock (the filesystem's header block that records its overall state) claims the filesystem is clean, and -y answers yes to every repair prompt so it runs unattended.
xfs does not work this way, and this catches people. Running fsck on an xfs filesystem does nothing useful: fsck.xfs is a stub that exits successfully without looking at anything, because xfs checks and repairs with a separate tool, xfs_repair. If someone unmounts an xfs volume, runs fsck, sees a clean exit and calls it fixed, they have inspected nothing. The real command is xfs_repair, also on an unmounted filesystem.
The root filesystem is the awkward case: you cannot unmount it while the system is running on it. You have two moves. To inspect it without unmounting, read the superblock: tune2fs -l on ext4, or xfs_info on xfs, both safe on a live mount, and tune2fs will report the filesystem state. To actually repair root, force a check on the next boot, before root is in full use. Add fsck.mode=force (and fsck.repair=yes) to the kernel command line from the boot menu (GRUB, the bootloader that loads the kernel), or on many systems create the old flag file and reboot into the check.
One habit ties this together: whenever you change storage, verify the result out of band. After mkfs, run lsblk -f and confirm the type and UUID. After editing fstab, run findmnt --verify, apply live changes with mount -o remount, and read back the real options with findmnt before you ever reboot. The reboot is the moment a quiet mistake turns into a downed host, and every one of these checks happens before it.
Try this
Work through “Checking And Repairing” yourself on a sandbox you can throw away, following the commands above in order. Then break one step deliberately and re-run, so you have seen the failure before it finds you.
Takeaway
The trap worth remembering here: a bad fstab line can leave a host unbootable. Check that on your own systems before you need to, because it is cheaper to find on a quiet afternoon than during an incident.