Linux df Command Deep Dive: From Disk Space Monitoring to inode Exhaustion Troubleshooting
Linux df Command Deep Dive: From Disk Space Monitoring to inode Exhaustion Troubleshooting#
Server disk full, SSH login fails with No space left on device. First reaction: df -h. But sometimes there’s still space showing, yet errors persist—that’s inode exhaustion. After diving deep into the df command, I found this seemingly simple tool hides quite a few intricacies.
df’s Underlying Implementation: statvfs System Call#
The core data of df comes from the statvfs() system call, which returns filesystem statistics:
#include <sys/statvfs.h>
int statvfs(const char *path, struct statvfs *buf);
struct statvfs {
unsigned long f_bsize; // Filesystem block size
fsblkcnt_t f_blocks; // Total blocks
fsblkcnt_t f_bfree; // Free blocks
fsblkcnt_t f_bavail; // Available blocks for unprivileged users
fsfilcnt_t f_files; // Total inodes
fsfilcnt_t f_ffree; // Free inodes
// ...
};
The key distinction is between f_bfree and f_bavail:
- f_bfree: Actual free blocks in the filesystem
- f_bavail: Blocks available to ordinary users (5% reserved for root)
This is why df -h can show Use% exceeding 100%—root can still write using that reserved 5%.
Common Parameters Explained#
-h: Human-Readable Format#
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 100G 85G 10G 90% /
tmpfs 7.8G 0 7.8G 0% /dev/shm
-h automatically selects appropriate units (K/M/G/T), much more readable than the default 1K blocks.
-i: inode Usage#
$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 655360 655350 10 100% /
This is the classic sign of inode exhaustion: Use% is only 90%, but IUse% is 100%. Too many small files (like log rotations, cache files) consume inodes even when disk space is still available.
-T: Display Filesystem Type#
$ df -T
Filesystem Type 1K-blocks Used Available Use% Mounted on
/dev/sda1 ext4 104755200 85000000 10000000 90% /
/dev/sdb1 xfs 209715200 50000000 159715200 20% /data
Different filesystem characteristics:
| Filesystem | Max File Size | Max Volume Size | Features |
|---|---|---|---|
| ext4 | 16TB | 1EB | Mature, stable, Linux default |
| xfs | 8EB | 8EB | High concurrency, large files |
| btrfs | 16EB | 16EB | Snapshots, compression, checksums |
| tmpfs | Memory limit | Memory limit | RAM filesystem, fast |
–total: Summary Statistics#
$ df -h --total
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 100G 85G 10G 90% /
/dev/sdb1 200G 50G 150G 20% /data
total 300G 135G 160G 45% -
Useful for quick total capacity assessment.
Practical Scenarios#
1. Disk Space Alert Script#
#!/bin/bash
# Monitor disk usage, send email alert when threshold exceeded
THRESHOLD=80
df -H | grep -vE '^Filesystem|tmpfs|cdrom' | while read line; do
usage=$(echo "$line" | awk '{print $5}' | sed 's/%//')
mount=$(echo "$line" | awk '{print $NF}')
if [ "$usage" -gt "$THRESHOLD" ]; then
echo "Warning: $mount usage at ${usage}%" | mail -s "Disk Space Alert" admin@example.com
fi
done
2. inode Exhaustion Investigation#
# Find which directory has the most inodes
for dir in /*; do
if [ -d "$dir" ]; then
count=$(find "$dir" -xdev | wc -l)
echo "$count $dir"
fi
done | sort -rn | head -10
Usually /var/spool/postfix/maildrop or /tmp accumulates many small files.
3. Combine with du to Locate Large Directories#
# First check which partition is full with df
df -h
# Then locate large directories with du
du -h --max-depth=1 / | sort -hr | head -10
4. View Real Mount Point Usage#
# -x exclude specific filesystem types
df -h -x tmpfs -x devtmpfs
# -t show only specified types
df -h -t ext4 -t xfs
Performance Considerations#
The df command itself is rarely a performance concern, but special scenarios require attention:
NFS Mount Timeout#
# When NFS server is down, df will hang
# Solution: use timeout or background execution
timeout 5 df -h /mnt/nfs
Large Number of Mount Points#
# View all mount points (including docker, snap, etc.)
$ df -h | wc -l
127
Long-running systems accumulate many mount points, and df queries each one sequentially.
Common Pitfalls#
1. Space Not Released After File Deletion#
$ df -h /data
/dev/sdb1 200G 180G 20G 90% /data
$ rm -f /data/large_file
$ df -h /data
/dev/sdb1 200G 180G 20G 90% /data # Space unchanged!
Reason: File is held by a process; deletion only marks it as pending removal.
# Find processes holding deleted files
$ lsof +L1
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 1234 www-data 3w REG 8,17 50G 123 /data/large_file (deleted)
# Restart nginx to release space
$ systemctl reload nginx
2. Reserved Space Misunderstanding#
$ df -h /
/dev/sda1 100G 95G 0G 95% /
# Regular user write fails
$ touch /test
touch: cannot touch '/test': No space left on device
# Root user can still write
# sudo touch /test # Success
ext4 reserves 5% by default for root. For large disks (like 10TB), you can reduce it:
# Reduce to 1%
tune2fs -m 1 /dev/sda1
3. tmpfs Memory Consumption#
$ df -h /dev/shm
tmpfs 7.8G 0 7.8G 0% /dev/shm
tmpfs uses RAM; writing large files can exhaust memory. Production environments should limit size:
mount -o remount,size=2G /dev/shm
Web Implementation: Browser-Based Disk Monitoring#
While browsers can’t directly access local disks, we can implement a “virtual disk” concept using Web APIs:
// Use Storage API to monitor localStorage quota
async function checkStorageQuota() {
const estimate = await navigator.storage.estimate()
const usedMB = (estimate.usage || 0) / 1024 / 1024
const quotaMB = (estimate.quota || 0) / 1024 / 1024
const percent = ((estimate.usage || 0) / (estimate.quota || 1)) * 100
return {
used: usedMB.toFixed(2) + ' MB',
quota: quotaMB.toFixed(2) + ' MB',
percent: percent.toFixed(1) + '%',
warning: percent > 80
}
}
// Simulate df -h output
function formatDiskInfo(info: DiskInfo): string {
const pad = (str: string, len: number) => str.padEnd(len)
return [
pad('Filesystem', 20),
pad('Size', 10),
pad('Used', 10),
pad('Avail', 10),
pad('Use%', 6),
'Mounted on'
].join(' ') + '\n' +
[
pad(info.fs, 20),
pad(info.total, 10),
pad(info.used, 10),
pad(info.avail, 10),
pad(info.percent, 6),
info.mount
].join(' ')
}
After diving deep into the df command, I found it’s more than just a simple disk viewer. From inode exhaustion to reserved space, from NFS timeouts to file handles, each scenario has its troubleshooting approach. Next time you encounter disk issues, don’t just check Use%—remember to check -i too.
Online disk space calculator: Disk Space Monitor
Related tools: Memory Unit Converter | Port Checker