mkfs Command: Tutorial & Examples

Turn a raw, blank partition into a filesystem you can actually mount and use.

What It Is

mkfs is the command that takes a brand-new block device — a fresh disk, a partition, a USB stick — and lays down a filesystem on it, so the kernel can finally store named files and folders there instead of an undifferentiated ocean of bytes. You attach a new disk to a cloud server, carve it into partitions, and the disk is still useless: there's no map, no table of contents, nothing that knows where one file ends and the next begins. mkfs writes that map. After it runs, you can mount the device and treat it like any other folder.

If you've never done this, the whole "add storage to a Linux box" dance is exactly three commands in a row — partition with parted, format with mkfs, attach with mount — and mkfs is the middle one, the moment the raw space becomes a real place to keep things. It's also the one command in that trio you must respect, because it is gloriously destructive: pointed at the wrong device, it cheerfully erases the map to everything that was there. We'll cover the safety drill so thoroughly you'll never make that mistake — and along the way you'll understand what a filesystem actually is, which turns out to be one of the more beautiful ideas in computing.

Danger

Every command on this page that names a real device (/dev/sdb1, /dev/nvme0n1p1) writes to that device and is irreversible. Run mkfs on the wrong target and the data it held is gone. Read the device name three times before you press Enter. The examples here use a throwaway image file or a clearly-fake device on purpose.

Your First Look

mkfs itself is a thin front-end. The honest move is to call the filesystem-specific builder directly — mkfs.ext4, mkfs.xfs, and so on — but they all answer to the same mkfs umbrella, and seeing one run is the fastest way to learn. Here's a real format — and you can run it yourself right now, with zero risk, by formatting a regular file instead of a disk. mkfs treats a 256 MB file exactly like a 256 MB device, so the output is identical and no real storage is ever touched:

# Make a 256 MB throwaway file and format THAT — no real disk is touched
truncate -s 256M disk.img
mkfs.ext4 -L data disk.img
mke2fs 1.47.2 (1-Jan-2025)
Creating filesystem with 262144 1k blocks and 65536 inodes
Filesystem UUID: 9002d642-b2ad-4490-b994-a9d639d39c6c
Superblock backups stored on blocks:
	8193, 24577, 40961, 57345, 73729, 204801, 221185

Allocating group tables:  0/32     done
Writing inode tables:  0/32     done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information:  0/32     done

That handful of lines is the whole job, and every word of it tells you something real: how many blocks and inodes it carved, the unique UUID it stamped on the filesystem, where it tucked backup copies of the superblock (in case the main one is ever damaged), and that it built a journal so a crash mid-write doesn't corrupt everything. We'll unpack each of those. The command finished in well under a second — which should make you suspicious, and that suspicion is the doorway to the magic.

How I Use It

Adding a disk to a server is muscle memory once you've done it a few times, and mkfs sits dead-center in the routine. Here's the actual sequence in my head, on a fresh cloud box with a new volume attached.

First, I find the device — and I find it carefully. A new disk shows up as something like /dev/sdb or /dev/nvme1n1, and the single most dangerous mistake on this whole page is formatting the wrong one. So I look before I leap, with lsblk:

lsblk
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda       8:0    0   40G  0 disk
├─sda1    8:1    0 39.9G  0 part /
└─sda2    8:2    0  100M  0 part /boot/efi
sdb       8:16   0  100G  0 disk

sda has partitions and is mounted on / — that's the live system, do not touch. sdb is 100 GB, blank, mounted nowhere: that's my new disk. The rule that's saved me more than once: if a device already has a mountpoint, you're almost certainly about to make a horrible mistake. A blank MOUNTPOINTS column is the green light.

Second, I partition it (optional but tidy) with parted, turning /dev/sdb into /dev/sdb1. You can format a whole disk directly — mkfs.ext4 /dev/sdb works and is common for data volumes — but a partition table is good manners and lets you grow or split later.

Third, the format itself. For a general-purpose Linux data disk I reach for ext4, give it a label so I can recognize it later, and let every other default ride:

mkfs.ext4 -L data /dev/sdb1

Fourth, I never mount by device name — I mount by UUID. The format printed one; I grab it with blkid and put that in /etc/fstab, not /dev/sdb1. Why? Because device letters are assigned in boot-time discovery order, and the day you add a second disk, today's sdb can become tomorrow's sdc — and an fstab that mounts by letter will then mount the wrong disk, or refuse to boot. The UUID is welded to the filesystem itself and never moves. (This bites everyone exactly once; let it bite you here, on paper, instead.)

That's the craft: lsblk to be sure, partition, format, mount by UUID. The format is the easy part. Aiming it correctly is the whole job.

What Actually Happens: A Filesystem Is Just an Index

Here's the idea that makes mkfs click, and it's genuinely lovely. Go back to that format finishing in under a second on a disk that might be terabytes in size. If mkfs were erasing or zeroing the whole drive, it would take hours. It doesn't, because it never touches the bulk of the disk at all.

A raw disk is just a vast, flat row of numbered blocks — block 0, block 1, block 2, all the way to the end — and the hardware will happily store a byte in any of them. What it won't do is tell you "blocks 4,000 through 4,200 are a file called report.pdf." That knowledge — the names, the folder tree, who-owns-what, which blocks belong to which file — has to be written down somewhere on the disk itself. That bookkeeping is the filesystem. A filesystem is nothing more than an index written into the disk's own blocks: a table of contents for the bytes.

So all mkfs actually does is write a small, fresh, empty index near the front of the device:

  • a superblock — the master record: filesystem type, total size, block size, where everything else lives (so important that mkfs scatters backup copies across the disk — those Superblock backups stored on blocks lines from the output);
  • an inode table — one slot per future file, holding its size, owner, permissions, timestamps, and the list of blocks it occupies (the 65536 inodes from the output is the ceiling on how many files this filesystem can ever hold — set once, at format time, never changeable);
  • allocation bitmaps — one bit per block saying "used" or "free", so the kernel can find space fast;
  • and on a modern filesystem, a journal — a scratchpad where pending changes are written before they're applied, so a power cut mid-write leaves a recoverable note instead of a corrupted mess.

Write those few megabytes of structure and you're done. The other 99.99% of the disk — the data region — mkfs leaves exactly as it found it.

Which leads to the genuinely surprising part, and I'll show it to you rather than just claim it. The old data on a disk is not erased by a format — only orphaned. Watch. I wrote a recognizable string deep into a blank 64 MB image, then formatted the image with ext4 (using -E nodiscard so the builder skips its optional zeroing pass), then went looking for my string in the raw bytes:

printf 'SECRET-DATA-STILL-HERE' | dd of=disk.img seek=50000000 conv=notrunc
mkfs.ext4 -q -F -E nodiscard disk.img
grep -a -o 'SECRET-DATA-STILL-HERE' disk.img
SECRET-DATA-STILL-HERE

There it is — after the format. The fresh filesystem has no file pointing at those blocks, so to the operating system the data is simply gone: invisible, unreachable, ready to be overwritten the next time something needs the space. But the bytes themselves sit there untouched, perfectly readable to anyone who looks at the raw device instead of the filesystem. A quick format burns the table of contents, not the book. Two things fall straight out of that, and both matter:

Danger

"I formatted it by accident" is sometimes recoverable, because the data is still physically there — tools like testdisk and photorec rummage the raw blocks for it. But "I formatted it, panicked, and started writing to it" usually is not, because new writes land on those orphaned blocks. If you mkfs the wrong disk: stop, unmount, touch nothing, and call in recovery. The clock is the enemy.

And the security flip side: deleting a file or formatting a disk does not destroy the data — it just removes the index entry. Hand an old drive to a stranger after a "format" and you've handed them every file on it. To actually erase data you must overwrite the blocks, with shred, blkdiscard on an SSD, or full-disk encryption from day one so the orphaned bytes are ciphertext anyway. (BTW, this is the same reason the FBI can recover "deleted" files, and the same reason your phone encrypts storage by default: on flash memory, true overwriting is unreliable, so the only honest way to "erase" is to make the data meaningless in the first place.)

ext4 or xfs? Choosing the Filesystem

mkfs is really a family. The front-end just dispatches to a builder named mkfs.<type>, and on a typical box you'll find a small zoo of them in /sbin:

mkfs.ext2  mkfs.ext3  mkfs.ext4   # the ext family (ext2/3/4 share one builder, mke2fs)
mkfs.xfs                          # high-throughput, big-server default
mkfs.btrfs                        # snapshots + checksums, copy-on-write
mkfs.vfat  mkfs.exfat             # FAT, for USB sticks and cross-OS drives
mkfs.ntfs                         # Windows filesystem, for shared drives

Ninety percent of the time the real decision is just ext4 vs xfs, and here's how I actually choose:

  • ext4 — the safe default. Battle-tested for over a decade, on every distro, understood by every tool, and uniquely able to shrink (xfs and btrfs can grow but never shrink). For a root disk, a database volume, a general-purpose server — reach for ext4 and stop thinking. It's the Honda Civic of filesystems: unglamorous, everywhere, never lets you down.
  • xfs — when throughput is the story. It shines with large files and heavy parallel writes (think media storage, big databases, log farms), scales to enormous volumes gracefully, and is the default on Red Hat / Rocky / Alma for exactly that reason. Its one quirk: you can grow an xfs but you can never shrink it, so size up only when you mean it.
  • btrfs and zfs — when you want snapshots and self-healing checksums. Powerful, copy-on-write, but a bigger commitment, and btrfs in particular can get slow and load-heavy with very large numbers of files. Choose deliberately, not by default.
  • vfat / exfat — only for portability. A USB stick that must work on Windows and a Mac wants exFAT. Never put a Linux system on FAT — it has no permissions, no ownership, no symlinks, none of the things Linux relies on.

Pro Tip

When in doubt, mkfs.ext4. The number of servers that genuinely needed something fancier than ext4 and got bitten by choosing it is small; the number that chose something exotic, hit a sharp edge at 2 a.m., and wished they'd stayed boring is large. Boring is a feature in storage.

The Output, Explained

Every line of that first format is worth knowing — it's a status report on the index mkfs just built:

  • mke2fs 1.47.2 — the version of the builder. (mkfs.ext4 is a symlink to mke2fs, the program that builds the whole ext2/3/4 family; the name it's invoked as tells it which to make.)
  • Discarding device blocks — on an SSD or thin-provisioned volume, mkfs issues a discard/TRIM telling the hardware "these blocks are free now," which both speeds up the SSD and zeroes the region as a side effect. (This is why my orphaned-data demo needed -E nodiscard to switch it off.)
  • 262144 1k blocks and 65536 inodes — the disk is divided into fixed-size blocks (the smallest unit it allocates) and a fixed pool of inodes (one per file). That inode count is a hard ceiling: run out of inodes and you get "No space left on device" even with gigabytes free, because you've used up file slots, not file space — the classic "disk full but df says 40% used" head-scratcher. Lots of tiny files? See -i below.
  • Filesystem UUID — a permanent, globally-unique name stamped into the superblock. This is what belongs in /etc/fstab, not the fickle /dev/sdb1.
  • Superblock backups stored on blocks — copies of the master record, scattered across the disk. If the primary superblock is ever clobbered, fsck can rebuild from one of these. Cheap insurance the filesystem gives you for free.
  • Allocating group tables / Writing inode tables — laying down the bookkeeping structures themselves.
  • Creating journal (8192 blocks) — the journal, the crash-safety scratchpad. The single biggest reason ext4 survives a power cut where the much older ext2 would have needed a long, scary fsck on every reboot.

The Flags, Explained

mkfs.ext4 (i.e. mke2fs) has a deep options list; here are the ones that actually earn their keep, plus the obscure ones worth half-remembering. (Generic flags like -t belong to the mkfs front-end; the rest are passed straight through to the builder.)

  • -t type — the front-end flag selecting the filesystem (mkfs -t ext4 /dev/sdb1 is identical to mkfs.ext4 /dev/sdb1).
  • -L label — a human-friendly name (up to 16 bytes), so lsblk -f and /dev/disk/by-label/ show data instead of a hex UUID. Always worth setting.
  • -U uuid — force a specific UUID, or -U random / -U clear. Handy when cloning a disk and you need to avoid two filesystems sharing a UUID (which confuses fstab badly).
  • -m percent — reserved-for-root percentage, default 5%. On the root disk this 5% is what lets you still log in and clean up when a runaway log fills the disk — without it, even root can't write and you're locked out of your own fix. But on a big data-only disk, 5% of 10 TB is 500 GB held hostage for nothing; set -m 0 or -m 1 there and reclaim it.
  • -b size — block size in bytes (1024/2048/4096). 4k is the near-universal default and matches the CPU page size; smaller blocks waste less on tiny files but cap the maximum filesystem size.
  • -i bytes-per-inode — how many bytes of disk get one inode. Lower it to create more inodes for a filesystem that'll hold millions of tiny files (a mail spool, a cache). Unchangeable after format — get it right now or reformat later.
  • -N count — set the inode count directly instead of via the -i ratio.
  • -I size — inode size in bytes (default 256). Don't go to 128: those inodes can't store timestamps past January 19, 2038, the Unix Y2038 cliff. The default already protects you.
  • -j — create with an ext3-style journal (implied for ext4 anyway).
  • -O feature[,...] — toggle filesystem features, e.g. -O ^has_journal to build with no journal at all (the ^ means "off"). Occasionally wanted on a flash device where journal writes wear the cells — but you're trading crash-safety for it.
  • -E extended-options — the grab-bag: -E nodiscard (skip the TRIM/zeroing pass, what my demo used), -E lazy_itable_init (defer inode-table zeroing to first mount, which is why formats are so fast), -E stride=/stripe_width= (align metadata to a RAID array's geometry for performance).
  • -c — scan the device for bad blocks before formatting (slow), so they're marked unusable. -c -c does a thorough read-write test. Rarely needed on modern drives, which remap bad sectors internally.
  • -T usage-type — pick a tuning profile from /etc/mke2fs.conf (small, largefile, largefile4); a largefile profile makes fewer inodes for a disk holding a few enormous files.
  • -q quiet · -v verbose.

And three flags that aren't about making a filesystem at all — they're the safety rails:

  • -n — the most important flag on this page: dry run. It prints exactly what it would do and writes nothing. Run this first, every time, on a device you're not 100% sure about. (It's also the documented way to find your backup superblock locations.)
  • -Fforce. mkfs refuses by default to format a device that's mounted or already holds a filesystem; -F overrides that. Specifying it twice overrides even "this is mounted right now," which the man page calls, with admirable bluntness, "a truly dangerous thing to do." If you're typing -F -F, stop and reread the device name.
  • -V — version / verbose.

Reading It by Example

Format outputs and what they're quietly telling you:

/dev/sdb1 is mounted; will not make a filesystem here!mkfs just saved you. The device is in active use, and it refused rather than scribble over a live filesystem. Do not reach for -F until you've confirmed with lsblk that this isn't a disk you care about. This message is a friend, not an obstacle.

/dev/sdb1 contains a ext4 file system labelled 'data'... Proceed anyway? (y,N) — there's already a filesystem here with data on it. The default answer is N for a reason. Type y only if you are certain you want it gone.

Discarding device blocks: done — you're on an SSD or thin volume and the TRIM worked; the drive knows these blocks are free. Healthy and normal.

Format finishes in milliseconds on a multi-terabyte disk — correct and expected, now that you know mkfs writes only the index, not the whole disk. If it instead grinds for an hour, you've probably asked for a full bad-block scan (-c) or a non-lazy build.

Could not stat /dev/sdb1 --- No such file or directory — the device name is wrong, or the partition doesn't exist yet. Recheck with lsblk. (Better to mistype it into this error than into a real device.)

Gotchas

  • The wrong-device catastrophe. mkfs.ext4 /dev/sda1 instead of /dev/sdb1 reformats your system disk. This is the single most expensive typo in system administration. Always lsblk first; a blank MOUNTPOINTS is your green light; when unsure, -n for a dry run.
  • Formatting the whole disk vs a partition. mkfs.ext4 /dev/sdb (no number) formats the entire disk and obliterates its partition table. Sometimes intended (single-purpose data volumes), often not. Know which you typed.
  • "No space left on device" with space free — you ran out of inodes, not bytes. df -i shows the inode count; the fix is to reformat with a lower -i (more inodes). Plan for it before formatting a disk of millions of tiny files.
  • Mounting by /dev/sdX in fstab — works until you add another disk, the letters shuffle, and your server mounts the wrong thing or won't boot. Use the UUID. Always.
  • A "format" is not an erase. As shown above, the old bytes survive. Reselling or returning a drive? shred, blkdiscard, or encrypt — don't just mkfs.
  • -i and -I are permanent. Bytes-per-inode and inode size can't be changed after the fact. The only fix is reformat (and reformat means restore-from-backup). Decide once.

History & Philosophy

The split you see today — a tiny generic mkfs that just dispatches to mkfs.ext4, mkfs.xfs, mkfs.vfat — is pure Unix philosophy crystallized. The man page even calls the front-end "deprecated in favour of filesystem-specific mkfs.<type> utils," which is delightfully honest: the umbrella exists mostly for old habits and scripts. Each filesystem brings its own builder because each is a genuinely different design — different on-disk layout, different trade-offs, different authors — and bolting them all into one monolith would have been madness. So instead there's a convention (mkfs.<anything>) and a thin launcher that finds the right tool on your PATH. Add a brand-new filesystem to Linux tomorrow, ship a mkfs.coolfs binary, and mkfs -t coolfs works on day one with no change to anything. That's the Unix bet — small composable tools over one big program — paying off forty years later.

And the deeper idea worth carrying away: the filesystem is one of computing's great acts of imagination. The hardware offers you nothing but a numbered row of blocks — no files, no folders, no names, no permissions, none of it. Every comforting thing about "files on a disk" is a fiction the filesystem paints on top of that flat array, and mkfs is the moment the fiction is first written down. Once you see that — that "a file" is a story the inode table tells about some blocks, and a "folder" is just a special file listing other files — the whole machine turns transparent. Pull the thread further and you'll find fsck repairing that story when it tears, journaling keeping it consistent through a crash, and copy-on-write filesystems letting two stories share the same blocks until one of them changes. It's stories all the way down, and mkfs writes the first page.

See Also

  • mount — attach the filesystem you just made
  • lsblk — list devices safely before you format anything
  • parted — partition the disk first (the step before mkfs)
  • blkid — read a filesystem's UUID and label
  • fsck — check and repair the filesystem when it tears
  • shred — actually destroy data, since a format does not
  • filesystem — the index-over-raw-blocks idea, in depth
  • inode — the per-file record at the heart of it all
  • /etc/fstab — mount your new disk automatically at boot
  • disk full — including the "out of inodes" variant

Worried the disk you just added is quietly filling up — or running out of inodes — while you're not looking?

CleverUptime watches disk usage on every filesystem you mount, trends it over time, and warns you in plain language before "No space left on device" wakes you at 3 a.m. — so the storage you went to the trouble of formatting never silently runs dry.

Want to see your own server's health right now? One command, no signup, no install.

Check your server →