<!--date=20250209 -->


<h1>File Systems and Disk Management</h1>
<p>File systems are something most people take for granted until a disk fills up or something won't unmount. This covers the practical side — creating and mounting file systems, checking what's using your space, and keeping things healthy. The commands here are the ones that come up in real situations, not a comprehensive survey of every filesystem type.</p>

<h2>Checking Disk Space</h2>

<table>
  <thead><tr><th>Command</th><th>What it does</th></tr></thead>
  <tbody>
    <tr><td><code>df -h</code></td><td>Disk usage by mounted filesystem, human-readable sizes</td></tr>
    <tr><td><code>df -h /home</code></td><td>Usage of a specific mount point</td></tr>
    <tr><td><code>du -sh /var/log</code></td><td>How much space a directory tree uses</td></tr>
    <tr><td><code>du -sh /var/log/*</code></td><td>Break it down by subdirectory</td></tr>
    <tr><td><code>du -sh * | sort -rh | head -20</code></td><td>Find the biggest things in the current directory</td></tr>
    <tr><td><code>lsof | grep deleted</code></td><td>Find deleted files still held open (still taking space)</td></tr>
  </tbody>
</table>

<pre>
When `df` shows 100% but you can't find the files consuming space:
  $ lsof | grep deleted

A deleted file still held open by a process still occupies disk space.
Restarting (or sending SIGHUP to) the process that has the file open frees it.
This is a common cause of "disk full but can't find anything" on busy log servers.
</pre>

<h2>Listing Block Devices</h2>
<pre>
$ lsblk              # tree view of all block devices
$ lsblk -f           # include filesystem type and UUID
$ blkid /dev/sdb1    # filesystem UUID for a specific device
$ fdisk -l /dev/sdb  # partition table details
</pre>
<p>Always run <code>lsblk</code> before touching a disk to confirm what you're looking at. Device names like <code>sdb</code> vs <code>sdc</code> can flip between boots if you're adding/removing drives.</p>

<h2>Creating File Systems</h2>

<table>
  <thead><tr><th>Command</th><th>Filesystem</th><th>Notes</th></tr></thead>
  <tbody>
    <tr><td><code>mkfs.ext4 /dev/sdb1</code></td><td>ext4</td><td>Most common Linux filesystem; mature, reliable</td></tr>
    <tr><td><code>mkfs.xfs /dev/sdb1</code></td><td>XFS</td><td>Better for large files; default on RHEL/Rocky</td></tr>
    <tr><td><code>mkfs.btrfs /dev/sdb1</code></td><td>Btrfs</td><td>Snapshots, checksums, copy-on-write</td></tr>
    <tr><td><code>mkfs.vfat -F 32 /dev/sdc1</code></td><td>FAT32</td><td>USB drives, cross-platform compatibility</td></tr>
  </tbody>
</table>

<p>There is no undo for <code>mkfs</code>. Double-check the device name with <code>lsblk</code> before running it.</p>

<h2>Mounting</h2>
<pre>
$ mount /dev/sdb1 /mnt              # basic mount (auto-detects type)
$ mount -t ext4 /dev/sdb1 /mnt      # explicit filesystem type
$ mount -o ro /dev/sdb1 /mnt        # read-only
$ mount -o remount,rw /mnt          # remount existing mount as read-write
$ umount /mnt                        # unmount
$ umount -l /mnt                     # lazy unmount — waits until device is idle
</pre>

<h3>Persistent Mounts via /etc/fstab</h3>
<p>Entries in <code>/etc/fstab</code> mount automatically at boot. Use UUIDs rather than device names — device names can change, UUIDs don't:</p>
<pre>
# Get the UUID
$ blkid /dev/sdb1
/dev/sdb1: UUID="a1b2c3d4-..." TYPE="ext4"

# /etc/fstab entry
UUID=a1b2c3d4-...  /mnt/data  ext4  defaults,noatime  0  2

Columns: device | mountpoint | type | options | dump | fsck-order
  dump: almost always 0
  fsck-order: 1 for root, 2 for others, 0 to skip

After editing fstab: test with `mount -a` before rebooting.
A bad fstab entry can prevent the system from booting.
</pre>

<h2>Common Mount Options</h2>

<table>
  <thead><tr><th>Option</th><th>Effect</th><th>Use case</th></tr></thead>
  <tbody>
    <tr><td><code>noatime</code></td><td>Don't update access time on reads</td><td>Better performance; SSDs especially benefit</td></tr>
    <tr><td><code>nodiratime</code></td><td>Same, for directories only</td><td>Complement to noatime</td></tr>
    <tr><td><code>noexec</code></td><td>Don't allow executing binaries</td><td>Data partitions, extra security for /tmp</td></tr>
    <tr><td><code>nosuid</code></td><td>Ignore setuid/setgid bits</td><td>Good for /tmp and shared data directories</td></tr>
    <tr><td><code>ro</code></td><td>Read-only</td><td>Backups, forensics, protecting source media</td></tr>
  </tbody>
</table>

<h2>Checking and Repairing File Systems</h2>
<p>Run <code>fsck</code> only on unmounted filesystems. Running it on a live mounted filesystem will cause damage:</p>
<pre>
$ umount /dev/sdb1
$ fsck /dev/sdb1             # check (auto-detects type)
$ fsck -y /dev/sdb1          # check and auto-fix without interactive prompts
$ fsck.ext4 -f /dev/sdb1     # force check even if filesystem appears clean

For the root filesystem (can't unmount while running):
$ tune2fs -C 1 /dev/sda1     # force fsck on next boot (ext filesystems)
</pre>

<h2>LVM — Logical Volume Management</h2>
<p>LVM separates physical disks from logical volumes, allowing you to resize and move storage without partitioning constraints. Many Linux installations use it by default.</p>

<table>
  <thead><tr><th>Command</th><th>Purpose</th></tr></thead>
  <tbody>
    <tr><td><code>pvdisplay</code></td><td>Show physical volumes</td></tr>
    <tr><td><code>vgdisplay</code></td><td>Show volume groups</td></tr>
    <tr><td><code>lvdisplay</code></td><td>Show logical volumes</td></tr>
    <tr><td><code>lvextend -L +10G /dev/vg0/data</code></td><td>Extend a logical volume by 10GB</td></tr>
    <tr><td><code>resize2fs /dev/vg0/data</code></td><td>Grow ext4 to use the new space</td></tr>
    <tr><td><code>xfs_growfs /mnt/data</code></td><td>Grow XFS to use the new space (can do live)</td></tr>
  </tbody>
</table>

<pre>
Growing vs. shrinking:
  XFS: can grow while mounted; shrinking is not supported at all
  ext4: can grow online; shrinking requires unmounting and a specific approach
  Btrfs: can grow and shrink while mounted (with `btrfs filesystem resize`)
</pre>

<h2>ZFS</h2>
<p>ZFS combines filesystem and volume management in one tool — checksums, snapshots, copy-on-write, and pool-based storage. Native to FreeBSD; available on Linux as OpenZFS.</p>
<pre>
$ zpool status              # pool health and device status
$ zpool list                # pool sizes and usage
$ zfs list                  # datasets (filesystems/volumes within pools)
$ zpool scrub mypool        # verify all data against checksums — run monthly
$ zfs snapshot mypool/data@$(date +%Y%m%d)  # point-in-time snapshot
$ zfs list -t snapshot      # list all snapshots
$ zfs rollback mypool/data@20250209          # revert to a snapshot
$ zfs clone mypool/data@snap mypool/test     # writable clone from a snapshot
</pre>
<p>ZFS scrub finds and corrects silent data corruption — bit rot that other filesystems would never notice. On a pool with redundancy (RAIDZ, mirror), it can fix errors. Without redundancy, it at least tells you the data is bad before you find out the hard way.</p>

<h2>References</h2>
<ul>
  <li><a href="https://man.openbsd.org/mount.8" target="_blank" rel="noopener">OpenBSD mount(8) man page ↗</a></li>
  <li><a href="https://openzfs.github.io/openzfs-docs/" target="_blank" rel="noopener">OpenZFS Documentation ↗</a></li>
  <li><a href="https://tldp.org/LDP/sag/html/filesystems.html" target="_blank" rel="noopener">Linux Filesystem Concepts — TLDP ↗</a></li>
</ul>
