Chapter 06 · Storage Layout & Disk Management
Chapter Overview
Linux’s distinctive storage layout often leaves newcomers scratching their heads. This chapter starts with the on‑disk layout used by Linux, introduces the Filesystem Hierarchy Standard (FHS), explains the kernel’s udev device‑naming rules, and walks through how block devices actually work.
To make the role of a filesystem concrete, we compare the commonly used Ext3, Ext4, and XFS filesystems, then practice the day‑to‑day administration tasks you’ll use most: partitioning, formatting, and mounting disks and partitions. By the end, you’ll be comfortable working with filesystems in real environments.
After you’ve got the fundamentals down, we’ll set up a swap area, configure quota to control disk consumption, and learn to create symbolic (soft) and hard links with ln
. The goal is a deep, practical understanding of storage and filesystems on Linux (and how that compares to Windows).
6.1 Everything Starts at “/”
On Linux, everything is a file: directories, character devices, sockets, disks, CD‑ROMs, and printers are all represented as files. If everything is a file, how do we find the one we want?
In Windows, you first choose a drive letter (partition), then the folders within it, and finally the file. Linux has no C:
/D:
/E:
letters. Every path begins at the root directory /
, and files are organized beneath it in an inverted‑tree structure defined by the Filesystem Hierarchy Standard (FHS).
Linux is case‑sensitive. root
, rOOt
, Root
, and rooT
are all different. Filenames cannot include a forward slash (/
). The overall storage layout is shown in Figure 6‑1.
Figure 6‑1 Storage layout on Linux
The FHS distills decades of experience from users and developers. It’s a set of conventions about where things should live (and where you should look to find them). It’s not a police officer—people can and do ignore it—but learning it will save you time. Table 6‑1 lists common top‑level directories and what they’re for.
Table 6‑1 Common directories and what they contain
Directory | What belongs here |
---|---|
/boot | Bootloader files such as the kernel and boot menu |
/dev | Device files representing hardware |
/etc | System and service configuration |
/root | The superuser’s home directory |
/home | Home directories for regular users |
/bin | Core user commands (available even in single‑user mode) |
/sbin | Administrative commands for the superuser |
/lib | Shared libraries used by /bin and /sbin |
/media | Mount points for removable devices |
/opt | Third‑party application packages |
/srv | Service data for network services |
/tmp | Temporary files (writable by everyone) |
/proc | Virtual filesystem exposing process and kernel information |
/usr/local | Locally installed software |
/usr/sbin | Non‑core admin commands |
/usr/share | Architecture‑independent shared data such as docs and help files |
/var | Variable data such as logs and spools |
/lost+found | Recovered fragments after filesystem repairs |
Two path styles matter:
- Absolute path: starts at
/
and is valid from anywhere. - Relative path: interpreted relative to your current working directory—short to type, but not universal.
If the distinction isn’t crystal clear yet, don’t worry. Practice in the coming pages will make it second nature. For now, keep the FHS roles in mind; they’ll pay off soon.
6.2 How Physical Devices Are Named
If everything is a file, hardware must have filenames too. The kernel’s device manager, udev, creates and maintains device files and names them so you can guess a device’s type and partitioning from its name. udev runs as a daemon and listens to kernel events to manage the entries under /dev
. Table 6‑2 shows common device types and their canonical names.
Table 6‑2 Common devices and their names
Device | Name pattern |
---|---|
IDE disks | /dev/hd[a-d] |
NVMe devices | /dev/nvme[0-n] |
SCSI/SATA/USB | /dev/sd[a-z] |
Virtio disks | /dev/vd[a-z] |
Floppy | /dev/fd[0-1] |
Parallel printer | /dev/lp[0-15] |
Optical drive | /dev/cdrom |
Mouse | /dev/mouse |
Tape | /dev/st0 or /dev/ht0 |
IDE is rare today, so most disks appear as /dev/sd*
. A single host can have many disks, so the kernel uses a
–z
to label up to 26 devices of a given class (starting at a
). Partition numbering follows these rules:
Primary and extended partitions are numbered 1–4.
Logical partitions start at 5.
Two common misconceptions are worth correcting:
-
“
/dev/sda
is the device in the first motherboard slot.”
Not necessarily. Thea
in/dev/sda
reflects detection order, not the physical slot. In practice these often correlate, which fuels the myth, but they’re not the same. For example, an iSCSI disk might show up as/dev/sdb
even if the second physical slot is empty—because the kernel’s scan order put it there. -
“Partition numbers imply how many partitions exist.”
They don’t.sda3
means “partition number 3 onsda
,” not “the third partition created.” Numbers can be assigned non‑sequentially by the admin.
Let’s decode /dev/sda5
(Figure 6‑2):
Figure 6‑2 Decoding a device filename
- Entries under
/dev
denote hardware. sd
denotes a SCSI/SATA/USB storage device.a
is the first detected device of that class.5
indicates a logical partition.
NVMe is increasingly common in servers. It fully exploits SSD performance and outpaces SATA/SCSI. NVMe device names differ from SATA/SCSI; Figure 6‑3 illustrates the mapping.
Figure 6‑3 NVMe naming versus SATA/SCSI
A quick primer on partitioning: Disks are composed of sectors (traditionally 512 bytes). The first sector is special; it contains the Master Boot Record (MBR) and the partition table. In the classic MBR layout, the boot code uses 446 bytes, the partition table 64 bytes, and the signature 2 bytes. Each partition table entry consumes 16 bytes, so at most four entries fit—hence the limit of four primary partitions. Figure 6‑4 shows the first sector layout.
Figure 6‑4 Contents of the first sector
But four partitions are rarely enough. The solution is the extended partition: one of the four table entries points to additional partition records elsewhere on disk. The extended partition is just a pointer, not a place to store data. You then create multiple logical partitions inside it. Figure 6‑5 shows a typical plan.
Tips:
The extended partition forms a one‑way linked list of records. Because it’s a container, not a data area, you store data in the logical partitions it links to—not in the extended partition itself.
Figure 6‑5 Planning out primary, extended, and logical partitions
What does /dev/hdc8
mean? It’s the third IDE disk’s logical partition number 8 (IDE is mostly historical now).
You’ll also see devices like /dev/vda
and /dev/vdb
on RHCE exams or cloud VMs. Those are Virtio devices—the paravirtualized disks used by hypervisors such as KVM or Xen.
6.3 Filesystems and Your Data
Try writing a few lines on a blank sheet of A4 paper held sideways. Your lines soon drift up or down. Now switch to lined paper—everything becomes neat and easy to read. The lesson: without structure, content drifts. On storage, that structure is provided by a filesystem. It decides how to lay out and organize data, tracks metadata, and makes space use efficient.
Linux supports dozens of filesystems. The most common are:
Ext2 — The first commercial‑grade Linux filesystem (1993), modeled on classic UNIX designs. It lacks journaling, so crashes make recovery difficult and risky. Avoid it unless you truly need it (e.g., on small SD cards or certain USB sticks).
Ext3 — Adds a journal: before writing data, it records the intent. After a crash, the system replays the journal to bring the filesystem back to a consistent state. On very large volumes, recovery can still take a long time, and, as with any journaling FS, there’s no absolute guarantee of zero data loss.
Ext4 — An improved Ext3 and the default on RHEL 6. It supports volumes up to 1 EB (1,073,741,824 GB) and vast directory counts. Extent‑based allocation boosts throughput by allocating blocks in contiguous chunks. Many mainstream servers still default to Ext4.
XFS — A high‑performance journaled filesystem and the default on RHEL 7 and later. It recovers quickly after crashes and its journal overhead is low. XFS supports volumes up to 18 EB, effectively eliminating size limits for most real‑world needs.
A note on performance: RHEL 10 adopts XFS as its primary filesystem. While the official line touts big gains, real‑world read performance depends on many variables (file sizes and counts, CPU and memory pressure, controller/SSD models, etc.). In testing, XFS beats Ext4 in several cases but not overwhelmingly. XFS’s most impressive headline feature is its 18‑EB maximum size.
To visualize 18 EB: that’s 18,874,368 TB. With 100‑TB drives you’d need roughly 190,000 of them. At this scale, the limit is usually your budget, not the technology. A classic joke in the field: “If you must move 18 EB of data from Shanghai to Beijing as fast as possible, what’s the best transport?” Answer: the high‑speed rail—put the disks on a train.
When you unbox a new disk, the workflow is:
- Partition it (optional in some cases),
- Format the partition(s) with a filesystem, then
- Mount the filesystem at a directory.
Tips:
It’s like working with a large sheet of paper: first cut it into sizes you want (partition), then draw lines so writing stays neat (format), then start writing (mount).
What happens during formatting? Linux maintains a “map” called the superblock, which tracks filesystem‑wide information. File metadata (permissions, owner, size, timestamps, etc.) lives in fixed‑size records called inodes (128 bytes by default in classic Ext filesystems). The data itself lives in blocks (typically 1 KB, 2 KB, or 4 KB). An inode stores pointers to data blocks. If one inode’s pointers aren’t enough, the filesystem allocates extra blocks just to hold more pointers, chaining everything together so the kernel can read the entire file.
Two common space‑usage scenarios (assuming 4‑KB blocks):
- A 1‑KB file still consumes one full 4‑KB block → ~3 KB wasted (internal fragmentation).
- A 5‑KB file uses two blocks (one full 4‑KB block + one additional block for the remaining 1 KB).
This “last block can’t be fully filled” reality exists on every filesystem. Check any file’s size on disk vs. logical size and you’ll see they differ (Figure 6‑6).
Figure 6‑6 Logical size vs. space on disk
Inodes + blocks enable read/write operations but feel abstract. Figure 6‑7 makes their relationship concrete.
Figure 6‑7 How inodes reference blocks
To insulate user‑space tools from the quirks of each filesystem, the kernel provides VFS (Virtual File System). VFS is a translation layer that exposes a uniform API. Your tools interact with VFS (Figure 6‑8), and VFS translates those calls to the specific filesystem implementation below.
Figure 6‑8 The VFS architecture
Tips:
VFS is so reliable and transparent that many admins use it for years without realizing it’s there.
6.4 Mounting Storage
If you’re used to Windows, you probably plug in a USB drive and start using it without thinking about the steps involved. On Linux we’ll make the process explicit: mounting and unmounting devices so you understand how the OS wires a device into the directory tree.
Mounting associates a device (or partition) with an existing directory—called a mount point. After mounting, the device’s contents become visible inside that directory.
The mount
command’s basic form is:
mount [filesystem] [mountpoint]
Modern Linux usually auto‑detects the filesystem type, so -t
is rarely needed. The -a
option tells mount
to attempt mounting everything declared in /etc/fstab
.
Table 6‑3 Common mount
options
Option | Meaning |
---|---|
-a | Mount everything defined in /etc/fstab |
-t | Specify filesystem type explicitly |
Example: mount /dev/sdb2
on /backup
:
root@linuxprobe:~# mount /dev/sdb2 /backup
For network storage, device names can change. Use UUIDs (Universally Unique IDentifiers), which are stable and unique per filesystem. Find them with blkid
:
root@linuxprobe:~# blkid
/dev/sdb1: UUID="1ff63c74-090c-4fa9-a3fb-cfb029572819" TYPE="xfs"
/dev/sdb2: UUID="53f01fa2-2a23-4979-8add-8fe0df5b8947" TYPE="ext4"
… [output truncated] …
Mount by UUID:
root@linuxprobe:~# mount UUID=53f01fa2-2a23-4979-8add-8fe0df5b8947 /backup
Ad‑hoc mounts disappear on reboot. To make a mount persist across boots, add an entry to /etc/fstab
using this six‑field format: device mountpoint fstype options dump fsck. Table 6‑4 explains the fields.
Table 6‑4 Fields in /etc/fstab
Field | Meaning |
---|---|
Device | Device path (e.g., /dev/sdb2 ) or UUID=… |
Mountpoint | Directory to attach to (create it first) |
Fstype | Filesystem type (e.g., Ext3, Ext4, XFS, SWAP, iso9660 for CD/DVD) |
Options | defaults expands to rw,suid,dev,exec,auto,nouser,async |
Dump | 1 to enable dump backups at boot, else 0 |
Fsck | 1 to enable filesystem checks at boot, else 0 |
Example: auto‑mount an Ext4 filesystem at /backup
with defaults and no fsck:
root@linuxprobe:~# vim /etc/fstab
#
# /etc/fstab
# Created by anaconda on Wed Mar 12 19:35:26 2025
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=408f4a3d-a4d3-4a44-bb23-6988cdbd10bf / xfs defaults 0 0
UUID=4cf8ecae-bcb6-4b1e-8001-968b33643a8a /boot xfs defaults 0 0
UUID=1FB8-9199 /boot/efi vfat umask=0077,shortname=winnt 0 2
UUID=d936c726-45a7-4ca2-8932-c54f84a3d787 none swap defaults 0 0
/dev/sdb2 /backup ext4 defaults 0 0
Optical media use the iso9660
filesystem. To pre‑declare a CD/DVD mount at /media/cdrom
:
root@linuxprobe:~# vim /etc/fstab
#
# /etc/fstab
# Created by anaconda on Wed Mar 12 19:35:26 2025
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=408f4a3d-a4d3-4a44-bb23-6988cdbd10bf / xfs defaults 0 0
UUID=4cf8ecae-bcb6-4b1e-8001-968b33643a8a /boot xfs defaults 0 0
UUID=1FB8-9199 /boot/efi vfat umask=0077,shortname=winnt 0 2
UUID=d936c726-45a7-4ca2-8932-c54f84a3d787 none swap defaults 0 0
/dev/sdb2 /backup ext4 defaults 0 0
/dev/cdrom /media/cdrom iso9660 defaults 0 0
After editing /etc/fstab
, activate pending mounts with:
root@linuxprobe:~# mount -a
Use df -h
to see mounted filesystems and their space usage (“disk free”). The -h
option renders sizes in human‑friendly units (KB/MB/GB), so 10240K
prints as 10M
:
root@linuxprobe:~# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 17G 3.7G 13G 23% /
devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs 1.9G 84K 1.9G 1% /dev/shm
efivarfs 256K 56K 196K 23% /sys/firmware/efi/efivars
tmpfs 776M 9.7M 767M 2% /run
tmpfs 1.0M 0 1.0M 0% /run/credentials/systemd-journald.service
/dev/sr0 6.5G 6.5G 0 100% /media/cdrom
/dev/sda2 960M 272M 689M 29% /boot
/dev/sda1 599M 8.3M 591M 2% /boot/efi
/dev/sdb2 480M 20M 460M 4% /backup
For network filesystems declared in fstab
, add the _netdev
option so the system waits for networking to come up before attempting the mount (handy with iSCSI in Chapter 17):
root@linuxprobe:~# vim /etc/fstab
#
# /etc/fstab
# Created by anaconda on Wed Mar 12 19:35:26 2025
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=408f4a3d-a4d3-4a44-bb23-6988cdbd10bf / xfs defaults 0 0
UUID=4cf8ecae-bcb6-4b1e-8001-968b33643a8a /boot xfs defaults 0 0
UUID=1FB8-9199 /boot/efi vfat umask=0077,shortname=winnt 0 2
UUID=d936c726-45a7-4ca2-8932-c54f84a3d787 none swap defaults 0 0
/dev/sdb2 /backup ext4 defaults,_netdev 0 0
/dev/cdrom /media/cdrom iso9660 defaults 0 0
To unmount, specify either the device or the mount point:
root@linuxprobe:~# umount /dev/sdb2
If the target is busy (e.g., your shell is cd
’d into the mount point), leave that directory and try again:
root@linuxprobe:~# cd /media/cdrom
root@linuxprobe:/media/cdrom# umount /dev/cdrom
umount: /media/cdrom: target is busy.
root@linuxprobe:/media/cdrom# cd ~
root@linuxprobe:~# umount /dev/cdrom
root@linuxprobe:~#
Tips:
Mounting is like registering a marriage—both parties (device and directory) must be present. Once recorded, you can’t “remarry” the same device to another directory without first unmounting it.
When there are lots of disks and partitions, it’s easy to forget what’s where. Use lsblk
to see a tree of block devices, partitions, and LVM volumes:
root@linuxprobe:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 20G 0 disk
├─sda1 8:1 0 600M 0 part /boot/efi
├─sda2 8:2 0 1G 0 part /boot
└─sda3 8:3 0 18.4G 0 part
├─rhel-root 253:0 0 16.4G 0 lvm /
└─rhel-swap 253:1 0 2G 0 lvm [SWAP]
sdb 8:16 0 20G 0 disk
├─sdb1 8:17 0 1G 0 part
└─sdb2 8:18 0 500M 0 part
sr0 11:0 1 6.5G 0 rom
6.5 Adding a New Disk
Here’s the workflow we’ll practice:
- add a new virtual disk,
- partition it,
- make a filesystem and mount it, and
- verify mounts and actually use the space.
Using a VM saves buying real hardware and is ideal for learning. Steps:
- Shut down the VM and return to the hypervisor’s main window. Click Edit virtual machine settings, then Add to add hardware (Figure 6‑9).
Figure 6‑9 Add hardware in your VM
- Choose Hard Disk, click Next (Figure 6‑10).
Figure 6‑10 Choose the device type
- Select SATA as the virtual disk type (Figure 6‑11). The device will appear as
/dev/sdb
in Linux.
Figure 6‑11 Choose SATA for the new disk
- Pick Create a new virtual disk (Figure 6‑12).
Figure 6‑12 Create a brand‑new virtual disk
- Set Maximum disk size to 20 GB. This caps usage; it doesn’t pre‑allocate the space (Figure 6‑13).
Figure 6‑13 Cap the virtual disk at 20 GB
- Accept the default filename and location, click Finish (Figure 6‑14).
Figure 6‑14 Disk file name and location
- Review the new device in the VM’s hardware list and boot the VM (Figure 6‑15).
Figure 6‑15 Review hardware, then boot
Back in Linux, the new disk should appear as /dev/sdb
. Let’s carve out a 2‑GB partition.
fdisk
manages MBR‑style partition tables: create, delete, change type, list, and write. It’s interactive; type a letter at the prompt to invoke a function (Table 6‑5).
Table 6‑5 fdisk
commands
Key | Action |
---|---|
m | List all available commands |
n | Add a new partition |
d | Delete a partition |
l | List known partition types |
t | Change a partition’s type |
p | Print the partition table |
w | Write changes and exit |
q | Quit without saving |
Start fdisk
and print the empty table:
root@linuxprobe:~# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.40.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table.
Created a new DOS (MBR) disklabel with disk identifier 0x186f3f5e.
Command (m for help): p
Disk /dev/sdb: 20 GiB, 21474836480 bytes, 41943040 sectors
Disk model: VMware Virtual S
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x186f3f5e
Create a primary partition (n
→ p
) of 2 GB. Accept the default first sector and specify +2G
for the last sector:
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-41943039, default 2048): [press Enter]
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-41943039, default 41943039): +2G
Created a new partition 1 of type 'Linux' and of size 2 GiB.
Print the table and write it with w
:
Command (m for help): p
Disk /dev/sdb: 20 GiB, 21474836480 bytes, 41943040 sectors
Disk model: VMware Virtual S
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x186f3f5e
Device Boot Start End Sectors Size Id Type
/dev/sdb1 2048 4196351 4194304 2G 83 Linux
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
Partition type IDs are short codes describing a partition’s intended use. List them with l
. We’ll change one later to 82
(Linux swap) in Section 6.6:
Command (m for help): l
[output abbreviated]
Aliases:
linux - 83
swap - 82
extended - 05
uefi - EF
raid - FD
lvm - 8E
linuxex - 85
After partitioning, the kernel should expose /dev/sdb1
. If it doesn’t appear immediately, use partprobe
to nudge the kernel (run it twice if needed). As a last resort, reboot.
root@linuxprobe:~# file /dev/sdb1
/dev/sdb1: cannot open `/dev/sdb1' (No such file or directory)
root@linuxprobe:~# partprobe
root@linuxprobe:~# partprobe
root@linuxprobe:~# file /dev/sdb1
/dev/sdb1: block special (8/17)
Format the partition. Typing mkfs
and pressing Tab twice shows formatters for various filesystems:
root@linuxprobe:~# mkfs
mkfs mkfs.exfat mkfs.ext3 mkfs.fat mkfs.msdos mkfs.xfs
mkfs.cramfs mkfs.ext2 mkfs.ext4 mkfs.minix mkfs.vfat
Use the appropriate tool, e.g., mkfs.xfs /dev/sdb1
:
root@linuxprobe:~# mkfs.xfs /dev/sdb1
meta-data=/dev/sdb1 isize=512 agcount=4, agsize=131072 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=1
= reflink=1 bigtime=1 inobtcount=1 nrext64=1
data = bsize=4096 blocks=524288, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=16384, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
Mount and confirm:
root@linuxprobe:~# mkdir /newFS
root@linuxprobe:~# mount /dev/sdb1 /newFS
root@linuxprobe:~# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/rhel-root 17G 3.7G 13G 23% /
devtmpfs 4.0M 0 4.0M 0% /dev
tmpfs 1.9G 84K 1.9G 1% /dev/shm
efivarfs 256K 56K 196K 23% /sys/firmware/efi/efivars
tmpfs 776M 9.7M 767M 2% /run
tmpfs 1.0M 0 1.0M 0% /run/credentials/systemd-journald.service
/dev/sda2 960M 272M 689M 29% /boot
/dev/sr0 6.5G 6.5G 0 100% /media/cdrom
/dev/sda1 599M 8.3M 591M 2% /boot/efi
tmpfs 388M 120K 388M 1% /run/user/0
/dev/sdb1 2.0G 71M 1.9G 4% /newFS
du
(disk usage) reports space consumed by directories or files. To find which top‑level directory is hogging space:
root@linuxprobe:~# du -sh /*
0 /afs
0 /bin
229M /boot
84K /dev
29M /etc
12K /home
0 /lib
0 /lib64
6.5G /media
0 /mnt
0 /newFS
0 /opt
0 /proc
4.2M /root
9.8M /run
0 /sbin
0 /srv
0 /sys
20K /tmp
3.2G /usr
69M /var
Copy some files over and check consumption:
root@linuxprobe:~# cp -rf /etc/* /newFS
root@linuxprobe:~# ls /newFS
adjtime gshadow profile
aliases gshadow- profile.d
alsa gss protocols
alternatives host.conf pulse
anacrontab hostname qemu-ga
asound.conf hosts ras
… [output truncated] …
root@linuxprobe:~# du -sh /newFS
29M /newFS/
To make the new mount persistent, add it to fstab
:
root@linuxprobe:~# vim /etc/fstab
#
# /etc/fstab
# Created by anaconda on Wed Mar 12 19:35:26 2025
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=408f4a3d-a4d3-4a44-bb23-6988cdbd10bf / xfs defaults 0 0
UUID=4cf8ecae-bcb6-4b1e-8001-968b33643a8a /boot xfs defaults 0 0
UUID=1FB8-9199 /boot/efi vfat umask=0077,shortname=winnt 0 2
UUID=d936c726-45a7-4ca2-8932-c54f84a3d787 none swap defaults 0 0
/dev/cdrom /media/cdrom iso9660 defaults 0 0
/dev/sdb1 /newFS xfs defaults 0 0
6.6 Adding Swap

Swap is disk space used as an overflow for RAM: when physical memory is tight, the kernel pushes less‑active pages to disk to free RAM for active tasks. Because disks are far slower than RAM, swap is used only when necessary.
The workflow mirrors adding a filesystem. Before we begin on /dev/sdb
, a sizing guideline: in production, swap is often 1.5–2× RAM. To make the effect obvious, we’ll carve out a 5‑GB swap partition.
Create the partition with fdisk
and then change its type ID to 82 (Linux swap):
root@linuxprobe:~# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.40.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): n
Partition type
p primary (1 primary, 0 extended, 3 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): [press Enter]
First sector (4196352-41943039, default 4196352): [press Enter]
Last sector, +/-sectors or +/-size{K,M,G,T,P} (4196352-41943039, default 41943039): +5G
Created a new partition 2 of type 'Linux' and of size 5 GiB.
Command (m for help): t
Partition number (1,2, default 2): 2
Hex code or alias (type L to list all): 82
Changed type of partition 'Linux' to 'Linux swap / Solaris'.
Command (m for help): p
Disk /dev/sdb: 20 GiB, 21474836480 bytes, 41943040 sectors
Disk model: VMware Virtual S
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x186f3f5e
Device Boot Start End Sectors Size Id Type
/dev/sdb1 2048 4196351 4194304 2G 83 Linux
/dev/sdb2 4196352 14682111 10485760 5G 82 Linux swap / Solaris
Command (m for help): w
The partition table has been altered.
Syncing disks.
Format the swap area and enable it:
root@linuxprobe:~# mkswap /dev/sdb2
Setting up swapspace version 1, size = 5 GiB (5368705024 bytes)
no label, UUID=cd6c8f9d-0af2-4020-96bc-02509c118b5c
root@linuxprobe:~# free -m
total used free shared buff/cache available
Mem: 3879 1535 1563 14 1125 2344
Swap: 2047 0 2047
root@linuxprobe:~# swapon /dev/sdb2
root@linuxprobe:~# free -m
total used free shared buff/cache available
Mem: 3879 1540 1558 14 1126 2339
Swap: 7167 0 7167
To persist swap across reboots, add it to fstab
:
root@linuxprobe:~# vim /etc/fstab
#
# /etc/fstab
# Created by anaconda on Wed Mar 12 19:35:26 2025
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=408f4a3d-a4d3-4a44-bb23-6988cdbd10bf / xfs defaults 0 0
UUID=4cf8ecae-bcb6-4b1e-8001-968b33643a8a /boot xfs defaults 0 0
UUID=1FB8-9199 /boot/efi vfat umask=0077,shortname=winnt 0 2
UUID=d936c726-45a7-4ca2-8932-c54f84a3d787 none swap defaults 0 0
/dev/cdrom /media/cdrom iso9660 defaults 0 0
/dev/sdb1 /newFS xfs defaults 0 0
/dev/sdb2 swap swap defaults 0 0
6.7 Disk Quotas
Linux was designed as a multi‑user, multi‑tasking OS, and disk space is finite. To prevent a single user from filling a filesystem with giant videos or a blizzard of tiny files, the superuser can impose quotas—limits on the total space or total file count a user (or group) may consume on a given mount point. Quotas have two thresholds:
Soft limit — crossing it triggers warnings but still allows operation for a grace period.
Hard limit — cannot be exceeded; operations are immediately denied.
RHEL 10 ships with the quota tools installed, but filesystems don’t enable quota by default. Edit /etc/fstab
and enable user quotas on /boot
, then reboot so XFS initializes quota accounting:
root@linuxprobe:~# vim /etc/fstab
#
# /etc/fstab
# Created by anaconda on Wed Mar 12 19:35:26 2025
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=408f4a3d-a4d3-4a44-bb23-6988cdbd10bf / xfs defaults 0 0
UUID=4cf8ecae-bcb6-4b1e-8001-968b33643a8a /boot xfs defaults,uquota 0 0
UUID=1FB8-9199 /boot/efi vfat umask=0077,shortname=winnt 0 2
UUID=d936c726-45a7-4ca2-8932-c54f84a3d787 none swap defaults 0 0
/dev/cdrom /media/cdrom iso9660 defaults 0 0
/dev/sdb1 /newFS xfs defaults 0 0
/dev/sdb2 swap swap defaults 0 0
root@linuxprobe:~# reboot
Tips:
In some versions of VMware Workstation, the guest can confuse devices on reboot and fail to boot. If that happens, remove the/dev/sdb2
entry fromfstab
(or switch to UUID‑based entries) and reboot again.
If you used very old distributions (RHEL 5/6 era), note the option name change: older systems used usrquota
; modern XFS uses uquota
for user quotas.
After reboot, confirm quotas are active:
root@linuxprobe:~# mount | grep boot
/dev/sda2 on /boot type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,usrquota)
Create a test user and grant write access to /boot
so the user can exercise the quota:
root@linuxprobe:~# useradd tom
root@linuxprobe:~# chmod -R o+w /boot
Use xfs_quota
to manage quotas on XFS. The -c
flag passes subcommands; -x
enables expert mode for advanced operations.
Set user tom to have bsoft=3m and bhard=6m (block‑based soft/hard limits) and isoft=3 and ihard=6 (inode‑based soft/hard limits). Then report the quota:
root@linuxprobe:~# xfs_quota -x -c 'limit bsoft=3m bhard=6m isoft=3 ihard=6 tom' /boot
root@linuxprobe:~# xfs_quota -x -c report /boot
User quota on /boot (/dev/sda2)
Blocks
User ID Used Soft Hard Warn/Grace
---------- --------------------------------------------------
root 225552 0 0 00 [--------]
tom 0 3072 6144 00 [--------]
There are two groups of limits: i‑soft/i‑hard and b‑soft/b‑hard. As discussed in Section 6.3, each file consumes one inode to store its metadata, so i‑limits cap file counts. b‑limits cap total space consumed, measured in blocks.
“Soft” means the system only logs that the limit was crossed; “hard” means the operation is blocked immediately.
Switch to the test user and try creating a 5‑MB file, then an 8‑MB file. The second attempt should be denied by the quota:
root@linuxprobe:~# su - tom
tom@linuxprobe:~$ cd /boot
tom@linuxprobe:/boot$ dd if=/dev/zero of=/boot/tom bs=5M count=1
1+0 records in
1+0 records out
5242880 bytes (5.2 MB, 5.0 MiB) copied, 0.00163334 s, 3.2 GB/s
tom@linuxprobe:/boot$ dd if=/dev/zero of=/boot/tom bs=8M count=1
dd: error writing '/boot/tom': Disk quota exceeded
1+0 records in
0+0 records out
4194304 bytes (4.2 MB, 4.0 MiB) copied, 0.00370067 s, 1.1 GB/s
To adjust limits later, use edquota
. It edits quota settings in your default editor. -u
targets a user; -g
targets a group; other flags copy policies or edit grace periods.
Table 6‑6 edquota
options
Option | Meaning |
---|---|
-u | Edit a user’s limits |
-g | Edit a group’s limits |
-p | Copy one user’s/ group’s limits |
-t | Edit grace periods |
Example: raise tom’s hard block limit to 8 MB and verify:
tom@linuxprobe:/boot$ exit
root@linuxprobe:~# edquota -u tom
Disk quotas for user tom (uid 1001):
Filesystem blocks soft hard inodes soft hard
/dev/sda2 4096 3072 8192 1 3 6
root@linuxprobe:~# su - tom
tom@linuxprobe:~$ cd /boot
tom@linuxprobe:/boot$ dd if=/dev/zero of=/boot/tom bs=8M count=1
1+0 records in
1+0 records out
8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.00644861 s, 1.3 GB/s
tom@linuxprobe:~$ exit
6.8 Soft and Hard Links
With disk management under your belt, let’s introduce Linux’s equivalent of a “shortcut.” Windows shortcuts are small files that point to another file; if you move or delete the original, the shortcut breaks. Linux offers two flavors of links, and the details matter.
- Symbolic (soft) link — a reference that stores the target’s pathname. If the target is moved or deleted, the symlink breaks. Symlinks can point to files or directories and can cross filesystem boundaries. This is the closest match to Windows shortcuts. See Figure 6‑16.
Figure 6‑16 How a symbolic link points to its target
- Hard link — an additional directory entry that points to the same inode as the original file. Hard links are valid only within the same filesystem and cannot target directories. Because multiple names point at the same inode, the link continues to work even if one name is removed.
Create a test file and a symbolic link to it:
root@linuxprobe:~# echo "Welcome to linuxprobe.com" > old.txt
root@linuxprobe:~# ln -s old.txt new.txt
root@linuxprobe:~# ls -l
total 8
-rw-r--r--. 1 root root 26 Mar 16 23:18 old.txt
lrwxrwxrwx. 1 root root 7 Mar 16 23:18 new.txt -> old.txt
root@linuxprobe:~# cat new.txt
Welcome to linuxprobe.com
Rename the original file. The symlink breaks because it only stores the old path name:
root@linuxprobe:~# mv old.txt newold.txt
root@linuxprobe:~# ls -l
total 8
lrwxrwxrwx. 1 root root 7 Mar 16 23:18 new.txt -> old.txt
-rw-r--r--. 1 root root 26 Mar 16 23:18 newold.txt
root@linuxprobe:~# cat new.txt
cat: new.txt: No such file or directory
Create a hard link instead:
root@linuxprobe:~# echo "Welcome to linuxprobe.com" > old.txt
root@linuxprobe:~# ln old.txt new.txt
root@linuxprobe:~# ls -l
total 12
-rw-r--r--. 2 root root 26 Mar 16 23:18 new.txt
-rw-r--r--. 2 root root 26 Mar 16 23:18 old.txt
root@linuxprobe:~# cat new.txt
Welcome to linuxprobe.com
root@linuxprobe:~# ls -l old.txt
-rw-r--r--. 2 root root 26 Mar 16 23:18 old.txt
Notice the second column now shows 2
(the link count)—the number of directory entries pointing at the same inode. Delete one name and the other still works because the inode (and data) remain until the link count reaches zero:
root@linuxprobe:~# rm -f old.txt
root@linuxprobe:~# cat new.txt
Welcome to linuxprobe.com
You cannot create hard links to directories, and hard links cannot cross filesystem boundaries. Their effect is illustrated below.
Figure 6‑17 How a hard link points to the same inode
Tips:
Think of the table of contents in a book: each entry is a label that leads you to the real page. A link is the same idea — a name that resolves to the actual data.
Table 6‑7 ln options and what they do
Option | Meaning |
---|---|
-s | Create a symbolic link (without -s, ln creates a hard link) |
-f | Force creation (overwrite existing destination) |
-i | Prompt before overwriting |
-v | Verbose: print actions taken |
That wraps up the fundamentals. For production environments you’ll also want RAID (combine multiple disks into arrays) and LVM (resize logical volumes on the fly). On to Chapter 7!
Review Questions
-
What’s similar and different between files under
/home
and/root
? -
How does Linux determine names like
/dev/sda1
and/dev/sdb2
? -
What are primary, extended, and logical partitions? Why is there a limit of four primary partitions?
-
In the MBR’s first sector, what’s stored where?
-
Which commands format filesystems and which mount them?
-
How can you view mounted filesystems and space usage?
-
You try to unmount a filesystem and get “device is busy.” What does that usually mean, and how do you proceed?
Answer: Your current directory (or another process) is using the mount point. Change to another directory (e.g.,cd ~
) or stop the process, then try again. -
In quota configuration, must the soft limit be lower than the hard limit?
Answer: Not necessarily; soft can be ≤ hard. -
If the original file is renamed, will a symbolic link still reach it?
Answer: No. -
If the original file is deleted, will a hard link still reach it?
Answer: Yes—until the link count drops to zero.