Why Inode Exhaustion Happens
On a busy server you’ll often see df still showing plenty of space, but df -i screaming 100 % inode usage on a mount like /usr. The kernel will happily refuse to create any more files, even though there’s room on disk. The culprit is usually a deluge of tiny files—think logs, temp data, or a mis‑configured service that never cleans up.
Spotting the Problem Quickly
# Space vs. inodes
df -h /usr
df -i /usr
If the first command reports 20 GB free but the second is 100 % used, you’ve hit an inode shortage. Now find the directory that’s eating them.
# Count files per directory
sudo find /usr -xdev -type f -printf '%h\n' | \
awk -F/ '{print $NF}' | sort | uniq -c | sort -nr | head
The list will point you to the worst offenders—usually something like /usr/lib/tmp or /usr/share/doc where a build system or package manager churns out many small objects.
Common Sources of Tiny Files
| Source | Typical Path | Why it explodes |
|---|---|---|
| Package builds | /usr/lib/build |
make generates thousands of object files |
| Package managers | /var/cache/apt/archives |
Unpacked packages leave a lot of small files |
| Log rotation mis‑config | /var/log |
Old logs never get pruned |
| Temp directories | /tmp, /var/tmp |
Services that forget to clean up |
Cleaning Up
-
Remove old logs
sudo journalctl --vacuum-size=200M sudo find /var/log -type f -mtime +30 -delete -
Clear package cache
sudo apt-get clean # Debian/Ubuntu sudo dnf clean all # RHEL/CentOS -
Delete build artefacts
sudo find /usr/lib/build -type f -delete -
Use
tmpfsfor short‑lived datasudo mount -t tmpfs -o size=512M tmpfs /usr/lib/tmpPersist the mount in
/etc/fstabso it comes back after reboot. -
Automate cleanup with
systemd-tmpfiles
Create/etc/tmpfiles.d/usr-lib.conf:d /usr/lib/tmp 0755 root root 10dThis will delete files older than 10 days automatically. See
systemd-tmpfiles(5)on systemd.io.
Preventing Future Exhaustion
-
Adjust inode density when you format a new filesystem. Ext4 defaults to one inode per 16 kB of data. If you’re going to store lots of tiny files, bump the density:
mkfs.ext4 -i 4096 /dev/sdx1You’ll waste a bit of space on large files, but you’ll gain the ability to hold more small ones.
-
Set inode quotas on critical mounts. Add
quotato/etc/fstaband runedquota -u <user>. Quotas keep a single user or service from swallowing all the inodes. -
Rotate and purge logs with
logrotate. The default Debian config keeps a limited number of rotated logs. Edit/etc/logrotate.d/*to match your retention policy. More detail is on debian.org. -
Use
tmpfsfor/tmpand/var/tmpon systems that churn a lot of temporary files. That way the inode pressure stays in RAM.
Security Implications
Inode exhaustion is a classic denial‑of‑service vector. An attacker who can flood a filesystem with small files can lock out legitimate users. Mitigations:
- Limit write access to
/tmpand similar dirs withchmod 1777andtmpfsmounts. - Apply quotas to stop a single process from draining all inodes.
- Keep log rotation tight; unpurged logs not only waste space but can leak sensitive data.
Quick Checklist
-
df -ishows 100 % on/usr? - Identify heavy directories with
find | awk. - Clean logs, caches, build artefacts.
- Use
tmpfsfor transient data. - Adjust inode density if many small files are expected.
- Enable quotas on critical mounts.
- Verify
logrotateandsystemd-tmpfilesare configured.
By checking inode usage regularly and applying these practices, you keep /usr (and any other mount) healthy and avoid silent denial‑of‑service conditions.
See also
- When /tmp fills a 1‑GB VPS in 15 minutes – how a simple tmpfs mount stops crashes
- When systemd‑resolved ignores /etc/hosts: a quick fix for local hostname resolution
- How to use journalctl to pinpoint why a scheduled rsync job stalls during authentication
- Fixing GNOME’s broken audio output after an ALSA upgrade
- When systemd‑resolved ignores /etc/hosts entries for local subdomains