Storage & Filesystems¶
This page walks through the full storage stack: identifying disks, partitioning, creating filesystems, mounting them (temporarily and persistently), managing swap, and using LVM for flexible, resizable storage.
Tested on
AlmaLinux 9.4 (default filesystem XFS) and Ubuntu 22.04 LTS (default ext4). LVM and the partitioning tools behave identically across both.
These commands destroy data
Partitioning (fdisk, parted) and formatting (mkfs.*) erase whatever is on the target device. There is no undo. Always confirm the device name with lsblk first, and never operate on a disk you can't afford to wipe. In this guide /dev/sdb is an example empty disk — substitute your real device carefully.
Block devices¶
Disks and partitions are block devices under /dev (/dev/sda, /dev/nvme0n1, etc.).
NAME FSTYPE LABEL UUID MOUNTPOINTS
sda
├─sda1 xfs a1b2c3d4-... /boot
└─sda2 LVM2_member e5f6...
├─vg0-root xfs 11aa... /
└─vg0-swap swap 22bb... [SWAP]
sdb
# Detailed partition tables for all disks (needs root)
sudo fdisk -l
# Show the UUID, label, and filesystem type of devices
sudo blkid
sudo blkid /dev/sda1
Why UUIDs matter
Device names like /dev/sdb can change between boots (depending on detection order). UUIDs are stable identifiers tied to the filesystem — always use them in /etc/fstab.
Partitioning¶
A disk needs a partition table. Two formats:
- MBR (msdos): legacy, max 2 TiB per disk, up to 4 primary partitions. Use only for very old/BIOS-only systems.
- GPT: modern standard, supports huge disks and 128 partitions. Use GPT for anything new.
fdisk (interactive)¶
fdisk now handles both MBR and GPT.
Inside fdisk, common commands: g (new GPT table), o (new MBR table), n (new partition), p (print), t (change type), d (delete), w (write and exit), q (quit without saving).
Command (m for help): g # create a GPT label
Command (m for help): n # new partition
Partition number (1-128, default 1): <Enter>
First sector ...: <Enter>
Last sector ...: +20G # 20 GiB partition
Command (m for help): w # commit
Nothing is written until you press w
fdisk only modifies the on-disk table when you type w. If you make a mistake, press q to bail out with no changes.
parted (scriptable)¶
parted can be driven non-interactively — handy for automation.
# Create a GPT table and a single partition spanning the whole disk
sudo parted -s /dev/sdb mklabel gpt
sudo parted -s /dev/sdb mkpart primary xfs 1MiB 100%
# Inspect
sudo parted /dev/sdb print
After partitioning, re-read the table if the kernel didn't pick it up:
Creating filesystems¶
A partition is just space until you put a filesystem on it.
# XFS (RHEL/AlmaLinux default — great general-purpose choice)
sudo mkfs.xfs /dev/sdb1
# ext4 (Debian/Ubuntu default)
sudo mkfs.ext4 /dev/sdb1
# Add a label while formatting
sudo mkfs.xfs -L data /dev/sdb1
sudo mkfs.ext4 -L data /dev/sdb1
mkfs wipes the partition
mkfs.* creates a brand-new, empty filesystem, destroying any existing data on that partition. Triple-check the device path.
XFS cannot shrink
XFS can grow online but cannot be shrunk. ext4 can shrink (offline). If you expect to reduce a filesystem later, choose ext4 — or better, use LVM so you can manage space at the volume level.
Mounting and unmounting¶
Mounting attaches a filesystem to a directory (a mount point).
# Create a mount point and mount the filesystem there
sudo mkdir -p /mnt/data
sudo mount /dev/sdb1 /mnt/data
# Confirm
mount | grep /mnt/data
df -h /mnt/data
# Unmount (the directory must not be in use)
sudo umount /mnt/data
# If umount complains "target is busy", find what's using it
sudo lsof +D /mnt/data
sudo fuser -vm /mnt/data
A manual mount does not survive a reboot — for that you need /etc/fstab.
Persistent mounts: /etc/fstab¶
/etc/fstab tells the system what to mount at boot. Use UUIDs for reliability.
Add a line to /etc/fstab:
# <device> <mountpoint> <type> <options> <dump> <fsck>
UUID=9f8e7d6c-1234-5678-9abc-def012345678 /mnt/data xfs defaults 0 0
# Validate the fstab and mount everything in it WITHOUT rebooting
sudo mount -a
# On systemd hosts, also refresh the mount units it generates
sudo systemctl daemon-reload
A broken fstab can block boot
A bad /etc/fstab entry can leave the system stuck at an emergency prompt on the next reboot. Always run sudo mount -a after editing — if it errors, fix it before you reboot. Adding the nofail option to non-critical mounts lets the system boot even if the device is missing.
Disk usage¶
# Free space per mounted filesystem (human-readable)
df -h
# Inode usage (a disk can be "full" of inodes while showing free space)
df -i
# Size of a directory (summarized, human-readable)
du -sh /var/log
# Biggest subdirectories, sorted
sudo du -h --max-depth=1 /var | sort -hr | head
Swap¶
Swap is disk space the kernel uses to offload memory under pressure. It can be a partition or a file.
Create a swap file (the easy, flexible method):
# Create a 2 GiB file (fallocate is fast; on XFS use dd if fallocate misbehaves)
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
# Format it as swap and enable it
sudo mkswap /swapfile
sudo swapon /swapfile
# Make it persistent in /etc/fstab
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
swappiness
Control how aggressively the kernel swaps with vm.swappiness (0–100, default ~60). Lower it for memory-heavy servers: sudo sysctl vm.swappiness=10, and persist it in /etc/sysctl.d/99-swappiness.conf.
LVM basics¶
LVM (Logical Volume Manager) adds a flexible layer over physical disks so you can resize, combine, and snapshot storage without repartitioning. The stack:
- PV (Physical Volume): a disk or partition handed to LVM.
- VG (Volume Group): a pool made of one or more PVs.
- LV (Logical Volume): a "virtual partition" carved from a VG — this is what you format and mount.
[ /dev/sdb1 ] [ /dev/sdc1 ] → PVs
\ /
[ vg_data ] → VG (pooled space)
/ | \
lv_web lv_db lv_logs → LVs (formatted & mounted)
Building an LVM stack¶
# 1. Initialize disks/partitions as physical volumes
sudo pvcreate /dev/sdb1 /dev/sdc1
sudo pvs # list PVs
# 2. Create a volume group from them
sudo vgcreate vg_data /dev/sdb1 /dev/sdc1
sudo vgs # list VGs
# 3. Create a 10 GiB logical volume
sudo lvcreate -L 10G -n lv_web vg_data
sudo lvs # list LVs
# 4. Format and mount it (path is /dev/<vg>/<lv>)
sudo mkfs.xfs /dev/vg_data/lv_web
sudo mkdir -p /srv/web
sudo mount /dev/vg_data/lv_web /srv/web
Add to /etc/fstab using the LV's UUID (sudo blkid /dev/vg_data/lv_web) for persistence.
Extending a logical volume (online)¶
This is LVM's killer feature — grow a volume that's running out of space, live.
# Add more physical capacity to the VG first if needed
sudo pvcreate /dev/sdd1
sudo vgextend vg_data /dev/sdd1
# Grow the LV by 5 GiB (or use -l +100%FREE to use all remaining space)
sudo lvextend -L +5G /dev/vg_data/lv_web
# Now grow the FILESYSTEM to fill the larger LV:
# XFS — must be MOUNTED, grows in place:
sudo xfs_growfs /srv/web
# ext4 — works mounted or unmounted:
sudo resize2fs /dev/vg_data/lv_web
Combine lvextend + resize in one step
sudo lvextend -r -L +5G /dev/vg_data/lv_web resizes the filesystem automatically (-r/--resizefs), picking xfs_growfs or resize2fs for you.
Grow vs shrink
Growing is safe and online. Shrinking an LV requires shrinking the filesystem first and is risky (XFS can't shrink at all). Back up before any shrink operation.
Verify your work¶
# Confirm the device, filesystem type, and UUID
lsblk -f /dev/sdb
sudo blkid /dev/sdb1
# Confirm it is mounted with the right size and space
df -h /mnt/data
# Confirm fstab is valid (no errors = good)
sudo mount -a && echo "fstab OK"
# Confirm LVM layout
sudo pvs && sudo vgs && sudo lvs
# Confirm swap is active
swapon --show
A correctly configured volume shows up in lsblk -f with the expected type/UUID, appears in df -h at its mount point, and survives mount -a without errors.
Summary¶
- Identify storage with
lsblk -f,fdisk -l, andblkid; UUIDs are the stable way to reference filesystems. - Partition with
fdisk(interactive) orparted(scriptable); prefer GPT over MBR for modern disks. - Create filesystems with
mkfs.xfs(RHEL default, grow-only) ormkfs.ext4(Debian default, can shrink). - Mount manually with
mount/umount; make it permanent in/etc/fstab(alwaysmount -ato test before rebooting). - Check space with
df -h/df -i/du -sh; add swap via a swapfile (fallocate→mkswap→swapon→ fstab). - LVM (PV → VG → LV) gives resizable storage:
pvcreate/vgcreate/lvcreate, thenlvextendplusxfs_growfs/resize2fsto grow online.