Andrey's Blog

Linux: Devices, Disks & Filesystems

Table of Contents

  1. Devices
  2. Disks and Partitions
  3. Filesystems
  4. Swap
  5. LVM (Logical Volume Manager)
  6. How the Kernel Boots
  7. How User Space Starts (systemd)
  8. Cheat Sheet

1. Devices

Device files in /dev

Most hardware is exposed to user space as device files (device nodes) in /dev. The first character of ls -l output tells you the type:

CharTypeExampleNotes
bBlock device/dev/sda, /dev/nvme0n1Fixed-size blocks, random access (disks)
cCharacter device/dev/null, /dev/tty1Data streams, no fixed size
pNamed pipe (FIFO)—Like a character device, but the other end is a process
sSocket/dev/logInterprocess communication
$ ls -l /dev/sda /dev/null
brw-rw----. 1 root disk 8, 0 ... /dev/sda
crw-rw-rw-. 1 root root 1, 3 ... /dev/null
                        ^  ^
                        |  └─ minor number (which device)
                        └──── major number (which driver)

Common naming:

Device nameMeaning
/dev/sd*SATA/SCSI/USB disks (sda, sdb, …); partitions are sda1, sda2
/dev/nvme*NVMe SSDs (nvme0n1); partitions are nvme0n1p1
/dev/tty*Virtual terminals / consoles
/dev/null, /dev/zero, /dev/randomPseudo-devices

sysfs (/sys)

sysfs is a pseudo-filesystem that exports information (and sometimes configuration) about kernel subsystems, hardware devices and their drivers to user space as virtual files. It is mounted at /sys.

ls /sys/block                 # block devices the kernel knows about
cat /sys/block/sda/size       # size in 512-byte sectors

udev and udevadm

udev is the device manager. When hardware is added or removed, the kernel sends a uevent; the systemd-udevd daemon receives it, applies rules (from /usr/lib/udev/rules.d and /etc/udev/rules.d), and creates/removes nodes and symlinks in /dev (e.g. /dev/disk/by-uuid/…).

 Hardware plugged in
        │
        ▼
 ┌──────────────┐   uevent    ┌───────────────┐   rules   ┌──────────────────┐
 │ Linux kernel │ ──────────► │ systemd-udevd │ ────────► │ /dev nodes and   │
 │ (driver)     │             │               │           │ symlinks created │
 └──────────────┘             └───────────────┘           └──────────────────┘

udevadm is the CLI for udev: query device info, trigger events, monitor uevents, control the daemon.

udevadm info --query=all --name=/dev/sda              # everything udev knows about sda
udevadm monitor                                       # watch kernel + udev events live
udevadm monitor --kernel                              # only kernel uevents
udevadm monitor --kernel --subsystem-match=scsi       # only SCSI kernel events
sudo udevadm trigger                                  # replay events (e.g. after changing rules)

Other device tools

CommandPurpose
lsblkList block devices as a tree (name, size, type, mountpoints, RO). -l = flat list, -f = show filesystems/UUIDs
lsscsiList SCSI and NVMe devices (type, vendor, model, node path)
sudo chvt NSwitch the foreground virtual terminal to /dev/ttyN
fgconsolePrint the number of the active VT

dd — copy raw data

dd reads from an input and writes to an output in blocks. Nicknamed “disk destroyer” because a wrong of= silently overwrites whatever it points at.

dd if=/dev/zero of=new_file bs=1024 count=1          # 1 block of 1024 zero bytes
# write an ISO to a USB stick
sudo dd if=image.iso of=/dev/sdX bs=4M status=progress conv=fsync
OptionMeaning
if=Input file
of=Output file
bs=Block size
count=Number of blocks to copy
skip= / seek=Skip blocks in input / output
status=progressShow progress

2. Disks and Partitions

Disk layout

A disk contains a partition table that describes partitions (subdivisions of the whole disk). Each partition usually holds a filesystem: filesystem data structures (metadata, inodes, directories) that point to the actual file data.

┌──────────────────────────────────────────────────────────────┐
│ Whole disk (/dev/sda)                                        │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Partition Table (MBR or GPT)                             │ │
│ └───────────────┬──────────────────────────────┬───────────┘ │
│                 ▼                              ▼             │
│ ┌──────────────────────────────┐ ┌─────────────────────────┐ │
│ │ Partition (/dev/sda1)        │ │ Partition (/dev/sda2)   │ │
│ │ ┌──────────────────────────┐ │ │                         │ │
│ │ │ Filesystem               │ │ │  (swap, another         │ │
│ │ │    ┌───────────────────┐ │ │ │   filesystem, LVM PV,   │ │
│ │ │    │ FS Data Structures│ │ │ │   or unused)            │ │
│ │ │    └─────────┬─────────┘ │ │ │                         │ │
│ │ │              ▼           │ │ │                         │ │
│ │ │ ┌──────────────────────┐ │ │ │                         │ │
│ │ │ │ File Data            │ │ │ │                         │ │
│ │ │ └──────────────────────┘ │ │ │                         │ │
│ │ └──────────────────────────┘ │ │                         │ │
│ └──────────────────────────────┘ └─────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘

How the kernel accesses a disk

User processes normally go through the filesystem. Tools like dd, fdisk or mkfs bypass it and use raw (direct) device access via device files.

┌───────────────────────────────────────────────────────────┐
│                     User Processes                        │
└─────────────────────────────┬─────────────────────────────┘
                              │
┌─────────────────────────────┼─────────────────────────────┐
│ Linux Kernel                ▼                             │
│  ┌──────────────┐      ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐    │
│  │ System Calls │◄────►  Raw (direct) device access       │
│  └──────┬───────┘      │ ┌─────────────────────────┐ │    │
│         │                │ Device Files (nodes)    │      │
│         ▼              │ └────────────┬────────────┘ │    │
│  ┌──────────────┐       ─ ─ ─ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ─ ─     │
│  │  Filesystem  │                     │                   │
│  └──────┬───────┘                     │                   │
│         ▼                             ▼                   │
│  ┌─────────────────────────────────────────────────────┐  │
│  │   Block Device Interface and Partition Mapping      │  │
│  └──────────────────────────┬──────────────────────────┘  │
│                             ▼                             │
│  ┌─────────────────────────────────────────────────────┐  │
│  │        SCSI Subsystem and Other Drivers             │  │
│  └──────────────────────────┬──────────────────────────┘  │
└─────────────────────────────┼─────────────────────────────┘
                              ▼
┌───────────────────────────────────────────────────────────┐
│                     Storage Device                        │
└───────────────────────────────────────────────────────────┘

(All arrows are bidirectional — data flows both ways.)

Partition tables: MBR vs GPT

MBR (DOS)GPT
Max disk size2 TiBEffectively unlimited (8 ZiB)
Partitions4 primary (or 3 + extended with logical)128 by default
RedundancySingle copy at sector 0Primary + backup header at end of disk
FirmwareClassic BIOSUEFI (standard)

Partitioning tools

sudo parted -l          # view all partition tables
sudo fdisk -l           # same idea with fdisk
sudo fdisk /dev/sdd     # interactively edit /dev/sdd

fdisk interactive commands (nothing is changed on disk until w):

KeyAction
mHelp
pPrint the current table
nCreate a new partition
dDelete a partition
tChange partition type
g / oCreate a new empty GPT / MBR table
wWrite changes and exit
qQuit without writing

3. Filesystems

Common filesystem types

TypeNotes
ext4Fourth Extended filesystem; current member of Linux’s native ext line. Mature, journaling, the safe default
BtrfsB-tree filesystem; newer native Linux FS designed to scale beyond ext4. Copy-on-write, snapshots, subvolumes, checksums. Default on Fedora
XFSHigh-performance journaling FS; default on RHEL 7+
FAT (msdos, vfat, exfat)Microsoft filesystems. msdos = primitive monocase MS-DOS; vfat = long filenames; exfat = large files, common on flash media. Required for the UEFI EFI System Partition (FAT32)
HFS+ (hfsplus)Older Apple standard (modern macOS uses APFS)
ISO 9660 (iso9660)CD-ROM standard
tmpfs, proc, sysfsVirtual filesystems living in memory / kernel

Creating a filesystem

mkfs is a front end that calls mkfs.<type>.

sudo mkfs -t ext4 /dev/sdf2       # same as: mkfs.ext4 /dev/sdf2

Mounting and unmounting

Mounting attaches a filesystem on a device to a directory (the mount point) in the single directory tree.

mount                                   # list current mounts (findmnt is nicer)
sudo mount -t type device mountpoint    # general form
sudo mount -t ext4 /dev/sdf2 /mnt/data
sudo mount UUID=1234-ABCD /mnt/data     # mount by UUID (stable across reboots)
sudo mount -o remount,ro /mnt/data      # remount read-only
sudo umount /mnt/data                   # detach (use the mount point)

Useful -o options: ro, rw, noexec, nosuid, remount, loop (mount an image file).

Why UUIDs? Device names like /dev/sdb can change between boots when disks are added or detected in a different order. UUIDs belong to the filesystem and stay stable.

blkid              # devices, their filesystem types and UUIDs
lsblk -f           # same info as a tree

/etc/fstab — mounts at boot

# <device>                                 <mountpoint> <type> <options>        <dump> <fsck>
UUID=a1b2c3d4-...                          /            ext4   defaults         0      1
UUID=e5f6...                               /home        ext4   defaults,noatime 0      2
UUID=ABCD-1234                             /boot/efi    vfat   umask=0077       0      2
UUID=9f8e...                               none         swap   sw               0      0

Last column: 1 = check first (root), 2 = check after root, 0 = never check. On systemd systems, each fstab line becomes a mount unit automatically.

Disk usage

df -h              # size and usage of mounted filesystems (human-readable)
du -sh dir/        # -s = summary: grand total only
du -h --max-depth=1 / | sort -h    # find the space hogs

Checking a filesystem: fsck

sudo fsck /dev/sdf2       # check and repair
sudo fsck -n /dev/sdf2    # check only, change nothing (safe first step)

Never run fsck on a mounted filesystem. The kernel may change the disk while fsck works, causing mismatches that can crash the system and corrupt files. Only exception: the root partition mounted read-only in single-user mode.

Btrfs and XFS use their own tools instead (btrfs check, xfs_repair).


4. Swap

Swap is disk space (a partition or a file) where the kernel moves inactive memory pages when RAM runs low. The system keeps running instead of killing processes, but swapping is much slower than RAM.

free -h                     # RAM and swap usage
swapon --show               # active swap areas
sudo mkswap /dev/sdX3       # format a partition as swap
sudo swapon /dev/sdX3       # enable it
sudo swapoff /dev/sdX3      # disable it

Swap file example:

sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
sudo chmod 600 /swapfile
sudo mkswap /swapfile && sudo swapon /swapfile

(Btrfs needs special handling for swap files. Many distros, including Fedora, also use zram — compressed swap in RAM.)


5. LVM (Logical Volume Manager)

LVM adds a flexible layer between disks and filesystems: you can resize volumes, span disks and take snapshots.

  Filesystems       ┌──────────┐    ┌──────────┐
  (ext4, xfs, …)    │   /      │    │  /home   │
                    └────┬─────┘    └────┬─────┘
                         │               │
  Logical Volumes   ┌────┴─────┐    ┌────┴─────┐
  (LV)              │ lv_root  │    │ lv_home  │
                    └────┬─────┘    └────┬─────┘
                         └───────┬───────┘
  Volume Group      ┌────────────┴────────────┐
  (VG)              │         vg_main         │   ← pool of storage
                    └─────┬─────────────┬─────┘
  Physical Volumes  ┌─────┴────┐   ┌────┴─────┐
  (PV)              │ /dev/sda2│   │ /dev/sdb1│
                    └──────────┘   └──────────┘
LevelShort summaryDetailed view
Physical volumespvspvdisplay
Volume groupsvgsvgdisplay
Logical volumeslvslvdisplay

LVs appear as /dev/<vg>/<lv> or /dev/mapper/<vg>-<lv>.


6. How the Kernel Boots

BIOS or UEFI?

efibootmgr              # list of boot entries → UEFI; "EFI variables not supported" → BIOS
ls /sys/firmware/efi    # directory exists → UEFI

Boot sequence

┌────────────────────────┐
│ 1. Firmware (BIOS/UEFI)│  power-on self-test, finds a boot loader
└───────────┬────────────┘
            ▼
┌────────────────────────┐
│ 2. Boot loader (GRUB,  │  loads kernel image (+ initramfs) into
│    systemd-boot)       │  memory, passes kernel parameters
└───────────┬────────────┘
            ▼
┌────────────────────────┐
│ 3. Kernel init         │  initializes CPU, memory, devices, drivers
└───────────┬────────────┘
            ▼
┌────────────────────────┐
│ 4. Mount root FS       │  (often via initramfs first)
└───────────┬────────────┘
            ▼
┌────────────────────────┐
│ 5. Start init (PID 1)  │  ◄── USER SPACE STARTS HERE
└───────────┬────────────┘
            ▼
┌────────────────────────┐
│ 6. init starts the     │  services, networking, …
│    rest of the system  │
└───────────┬────────────┘
            ▼
┌────────────────────────┐
│ 7. Login prompt / GUI  │  usually at or near the end of boot
└────────────────────────┘

initramfs — a small temporary root filesystem loaded by the boot loader along with the kernel. It contains drivers and tools needed to find and mount the real root (e.g. for LVM, RAID, encryption), then hands over.

Inspecting the boot

cat /proc/cmdline        # kernel parameters used for this boot
dmesg | less             # kernel ring buffer (boot messages)
journalctl -k            # kernel messages via the journal
journalctl -b -1         # logs from the previous boot

7. How User Space Starts (systemd)

Order of user-space startup

  1. init (systemd, PID 1)
  2. Essential low-level services — udevd, syslogd/journald
  3. Network configuration
  4. Mid- and high-level services — cron, printing, …
  5. Login prompts, GUIs, high-level apps (e.g. web servers)

Unit types

systemd manages units. The most important types for boot:

Unit typeSuffixPurpose
Service.serviceControls service daemons
Target.targetGroups other units (like “runlevels”)
Socket.socketIncoming connection endpoints; can start a service on demand
Mount.mountAttachment of filesystems (generated from fstab)

Others: .timer (cron replacement), .path, .device, .swap, .slice.

Unit dependency graph

                 ┌──────────────────┐
                 │  default.target  │
                 └────────┬─────────┘
                          ▼
                 ┌──────────────────┐
                 │multi-user.target │
                 └───┬─────┬─────┬──┘
           ┌─────────┘     │     └─────────┐
           ▼               ▼               ▼
  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
  │ basic.target │ │ cron.service │ │ dbus.service │
  └──────┬───────┘ └──────────────┘ └──────────────┘
         ▼
  ┌──────────────┐
  │sysinit.target│
  └──────────────┘

default.target is usually a symlink to multi-user.target (server/text) or graphical.target (desktop).

systemctl get-default                      # which target boots by default
systemd-analyze dot | dot -Tsvg > deps.svg # render the real graph (needs graphviz)
systemd-analyze blame                      # which units took longest to start
systemd-analyze critical-chain             # the slowest dependency chain

Where unit files live

systemctl -p UnitPath show                           # full unit search path
pkg-config systemd --variable=systemdsystemunitdir   # package units, e.g. /usr/lib/systemd/system
pkg-config systemd --variable=systemdsystemconfdir   # admin units,  e.g. /etc/systemd/system

/etc/systemd/system overrides /usr/lib/systemd/system. Don’t edit package files — use systemctl edit unit to create a drop-in override.

Anatomy of a unit file

Example: the D-Bus system daemon (dbus-daemon.service):

[Unit]
Description=D-Bus System Message Bus
Documentation=man:dbus-daemon(1)
Requires=dbus.socket
RefuseManualStart=yes

[Service]
ExecStart=/usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
ExecReload=/usr/bin/dbus-send --print-reply --system --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig

Service Type=

Typesystemd considers the service ready when…
simple (default)Immediately; the process doesn’t fork and stays the main process
forkingThe original process forks and exits (classic daemons)
notifyThe service sends a systemd-specific readiness notification (sd_notify)
dbusThe service registers its name on D-Bus
oneshotThe process finishes (for one-time setup tasks)
systemctl show -p Type unit      # check a unit's type

Dependencies

DirectiveMeaning
RequiresStrict. Activating this unit activates the dependency; if the dependency fails, this unit is deactivated too
WantsActivation only. Dependencies are started, but their failure doesn’t matter
RequisiteThe dependency must already be active; otherwise activation of this unit fails
ConflictsNegative. Activating this unit stops the conflicting one; simultaneous activation fails

Dependencies don’t define order. Use Before= / After= for that. Requires=b without After=b means both start in parallel.

Everyday systemctl / journalctl

systemctl list-units              # active units
systemctl list-units --failed     # failed units
systemctl list-jobs               # jobs currently queued/running
systemctl status unit             # state + recent log lines
systemctl start unit              # start now
systemctl stop unit               # stop now
systemctl restart unit
systemctl reload unit             # reload config (uses ExecReload)
systemctl enable unit             # start at boot (--now to also start)
systemctl disable unit
systemctl daemon-reload           # re-read unit files after editing
journalctl --unit=unit_name       # logs for one unit (short: -u)
journalctl -u unit_name -f        # follow logs live

8. Cheat Sheet

TaskCommand
List block deviceslsblk, lsblk -f
List SCSI/NVMe deviceslsscsi
Device details from udevudevadm info --query=all --name=/dev/sda
Watch device eventsudevadm monitor
Show partition tablessudo parted -l / sudo fdisk -l
Edit partitionssudo fdisk /dev/sdX
Create filesystemsudo mkfs -t ext4 /dev/sdX1
Show UUIDsblkid
Mount / unmountmount -t type dev dir / umount dir
Free spacedf -h
Directory sizedu -sh dir
Check filesystem (dry run)fsck -n /dev/sdX1
Swap statusswapon --show, free -h
LVM overviewpvs, vgs, lvs
BIOS or UEFI?efibootmgr / ls /sys/firmware/efi
Kernel parameterscat /proc/cmdline
Boot time analysissystemd-analyze blame
Service logsjournalctl -u unit