Day 11 - Disks and Filesystems

2025-10-017 min read

linuxstoragediskspartitionsfilesystemsmountfstabdfduswap

Day11 lsblk

This lesson builds a mental model of Linux storage and teaches the daily tools for working with disks and filesystems. It uses a virtual machine example so the workflow is safe to practice.

Key terms

Block device is a disk or partition exposed under /dev. Partition divides a disk into sections. Filesystem organizes files on a partition or device. Mount attaches a filesystem to a directory so it becomes part of the tree.

Prerequisites

  • Day 1 through Day 10 completed
  • A VM where an extra virtual disk can be added, or permission to create a loopback device

Inspect devices and layout

bash
lsblk -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINT,LABEL,UUID

# tree view of mounts by source and target
findmnt -A | head -30

# kernel messages for storage
sudo dmesg | grep -iE 'sd[a-z]|nvme|virtio' | tail -20

Typical device names:

  • SATA or SCSI: /dev/sda, /dev/sdb and partitions /dev/sda1, /dev/sda2
  • NVMe: /dev/nvme0n1 and partitions /dev/nvme0n1p1
  • Virtual disks under KVM or QEMU: vda, vdb

Add a new virtual disk in a VM (safe path)

  1. Shut down the VM and add a second disk in the hypervisor UI, for example 5 GB.
  2. Boot and confirm it appears as an unpartitioned device.
bash
lsblk -o NAME,TYPE,SIZE,FSTYPE | grep -E 'disk|part'

If adding a real disk is not possible, create a loopback device from a file for practice.

bash
# create a 2 GiB sparse file as a demo disk
sudo fallocate -l 2G /var/tmp/disk.img
sudo losetup --find --show /var/tmp/disk.img   # prints /dev/loopX
lsblk -o NAME,TYPE,SIZE /dev/loop*
Be careful with device names

Verify the target device carefully. Formatting the wrong device destroys data. Double check with lsblk and size column before running any command that writes structures.

Partition the disk

Use parted for a quick guided setup. GPT is recommended for modern systems.

bash
DISK=/dev/sdb   # replace with your device or the loop device
sudo parted -s $DISK mklabel gpt
sudo parted -s $DISK mkpart primary ext4 1MiB 100%
sudo parted -s $DISK print

The new partition appears as $DISK1 such as /dev/sdb1 or /dev/loop0p1.

Alternative with fdisk (interactive):

bash
sudo fdisk /dev/sdb
# n (new) p (primary) 1, accept defaults, w (write)

Make a filesystem and mount it

Create an ext4 filesystem and a mount point.

bash
PART=/dev/sdb1   # adjust to match your partition
sudo mkfs.ext4 -L data1 $PART
sudo mkdir -p /mnt/data1
sudo mount $PART /mnt/data1

# confirm
lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT $PART
findmnt /mnt/data1

Test write access.

bash
sudo sh -c 'echo test > /mnt/data1/hello.txt'
sudo ls -l /mnt/data1

Unmount when done or before making it persistent.

bash
sudo umount /mnt/data1
Common filesystems

ext4 is a solid default. XFS performs well on large files and servers. Btrfs adds snapshots and checksums. Choose based on needs and distribution defaults.

Persistent mounts with /etc/fstab

Mounts added at runtime vanish after reboot. Use /etc/fstab for persistence, preferably by UUID or label.

Find the UUID and label.

bash
blkid $PART

Add a line to /etc/fstab.

bash
# backup first
sudo cp /etc/fstab /etc/fstab.bak

# example using UUID and ext4 defaults
UUID=$(blkid -s UUID -o value $PART)
LINE="UUID=$UUID /mnt/data1 ext4 defaults,nofail 0 2"
echo "$LINE" | sudo tee -a /etc/fstab

# test without reboot
sudo mount -a
findmnt /mnt/data1

Notes:

  • nofail allows boot to continue if the device is not present.
  • The final 2 enables fsck order. Root is usually 1, others 2.
fstab mistakes can block boot

Keep a backup and test with mount -a. If a system fails to boot, use a rescue shell to comment out bad lines or fix the device names.

Space and usage checks

bash
# filesystem space and type
df -hT

# disk usage by directory, current level
du -sh * | sort -h

# restrict to one filesystem and go two levels deep
du -h -x --max-depth=2 /var | sort -h | tail -20
Quick big files finder

Combine find with size tests.

bash
sudo find / -xdev -type f -size +1G -printf '%p %s bytes\n' 2>/dev/null | head

Labels and tuning

Labels and tunables help identify and optimize filesystems.

bash
# set or change an ext4 label
sudo e2label $PART projects

# show and tweak ext4 parameters
tune2fs -l $PART | head -20

Mount options influence performance and safety.

  • noatime reduces write amplification on frequently read files
  • nodev, nosuid, noexec reduce risk on untrusted media

Example temporary mount with options:

bash
sudo mount -o noatime,nodev /dev/sdb1 /mnt/data1

Persist options by adding them in the fstab options column.

Create and manage a swapfile (optional)

A swapfile is flexible and avoids repartitioning.

bash
# create a 2 GiB swapfile
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# persist across reboots
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# verify
swapon --show
free -h
Swap on SSDs

Swap writes frequently. On modern SSDs this is acceptable, but monitor wear on systems with heavy swapping. Prefer more RAM if possible.

Check and repair filesystems

For ext filesystems, fsck checks integrity when a filesystem is unmounted.

bash
sudo umount /mnt/data1
sudo fsck -f $PART

Do not run fsck on a mounted, writable filesystem.

Journaled filesystems

Ext4 journals metadata. After an unclean shutdown, the journal replays changes quickly. fsck still runs periodically based on mount counts or intervals.

Practical lab

  1. Create a new partition and ext4 filesystem on a secondary disk or loop device, then mount it at /mnt/data1.
bash
# substitute your device
DISK=/dev/sdb
PART=/dev/sdb1
sudo parted -s $DISK mklabel gpt
sudo parted -s $DISK mkpart primary ext4 1MiB 100%
sudo mkfs.ext4 -L data1 $PART
sudo mkdir -p /mnt/data1
sudo mount $PART /mnt/data1
  1. Make the mount persistent by UUID with safe options.
bash
UUID=$(blkid -s UUID -o value $PART)
echo "UUID=$UUID /mnt/data1 ext4 defaults,nofail 0 2" | sudo tee -a /etc/fstab
sudo mount -a
findmnt /mnt/data1
  1. Generate space and measure it.
bash
sudo dd if=/dev/zero of=/mnt/data1/bigfile bs=100M count=5 status=progress
sudo du -sh /mnt/data1
sudo df -hT | grep data1
  1. Optional: create a 1 GiB swapfile and verify it is active.
bash
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
swapon --show
  1. Clean up the practice environment if using a loop device.
bash
sudo swapoff /swapfile && sudo rm -f /swapfile || true
sudo umount /mnt/data1 || true
sudo losetup -D || true
sudo rm -f /var/tmp/disk.img || true

Troubleshooting

  • device is busy when unmounting. Close terminals, stop services using the mount, or use lsof +f -- /mnt/data1 to find holders.
  • unknown filesystem type after creating a filesystem. Confirm the correct mkfs tool was used and that the kernel supports the type.
  • Mount fails on boot. Use nofail in /etc/fstab, verify UUIDs, and test with mount -a. Check logs with journalctl -b -u systemd-fsck and journalctl -b.
  • Permission issues on shared data directories. Use correct ownership and group settings, for example sudo chown -R root:developers /mnt/data1/projects && sudo chmod -R 2775 /mnt/data1/projects.
  • Swapfile cannot be enabled. Ensure file mode is 600 and that a sparse file is not on a filesystem with nocow options that block swap on some filesystems.

Next steps

Day 12 begins text processing with grep, cut, sort, uniq, wc, and tee. It focuses on searching and shaping logs and command output into quick reports.