Inodes & Links

Inode structure, stat output, hard links vs symlinks, inode exhaustion diagnosis, and df -i.

Overview

Every file and directory in a Linux filesystem is represented by an inode — a data structure stored in the filesystem's inode table. Understanding inodes is critical for diagnosing a range of subtle production issues, from "disk full" errors when the disk has free space, to files that persist on disk after deletion.

What an Inode Contains

An inode stores all file metadata except the filename:

  • File type — regular file, directory, symlink, device, socket, FIFO
  • Permissions — owner, group, and other read/write/execute bits
  • Owner UID and GID
  • File size in bytes
  • Three timestamps: atime (last access), mtime (last data modification), ctime (last inode/metadata change)
  • Link count — number of directory entries pointing to this inode
  • Block pointers — direct, indirect, double-indirect pointers to data blocks

Filenames Live in Directories

The filename itself is stored in the directory entry, which maps a name string to an inode number. This design enables hard links — multiple filenames pointing to the same inode.

Hard Links vs Symbolic Links

Hard link (ln source hardlink): creates a new directory entry pointing to the same inode. The inode's link count increments. The file data is only freed when link count reaches zero and no process holds the file open. Hard links cannot cross filesystem boundaries and cannot link to directories.

Symbolic link (ln -s target symlink): a special file whose data is the target path string. The symlink has its own inode. Can cross filesystem boundaries, can point to directories. Breaks if the target is moved or deleted (dangling symlink).

Inode Exhaustion

Filesystems have a fixed number of inodes allocated at creation time (ext4) or dynamic allocation (XFS). When inodes are exhausted, new files cannot be created even if gigabytes of block space remain. The symptom is No space left on device from df -h showing free space — check df -i instead.

Key concepts

Inode
Metadata structure for every file: type, permissions, owner, size, timestamps, block pointers. Does not contain the filename. View with stat filename or ls -i for inode number.
Hard link
Additional directory entry pointing to the same inode. Link count in inode increments. Data freed only when count reaches 0 and no open fds. Cannot cross filesystem boundaries.
Symbolic link
A file whose content is the target path. Has its own inode. Can cross filesystems and point to directories. Becomes a dangling symlink if target is moved or deleted.
Inode exhaustion
When all inodes are allocated, new files cannot be created even with free blocks. Check with df -i. Common cause: millions of tiny files in mail queues, session stores, or small log files.
Link count
Field in the inode tracking how many directory entries point to it. A new directory has link count 2 (the entry in parent + the . entry inside itself). Each subdirectory adds 1 via its .. entry.
ctime vs mtime
mtime — last data modification. ctime — last inode change (permissions, ownership, link count). ctime cannot be set manually — it updates whenever the inode changes.

When to use it

  • "No space left on device" but df -h shows free space — immediately check df -i for inode exhaustion
  • Debugging why deleting files does not free disk space — process holds open file descriptor
  • Explaining why you cannot hard link across filesystems or to directories
  • Finding which directory has millions of tiny files consuming all inodes
  • Understanding how log rotation works — hard link counts ensure the old log stays accessible while the new one is created

Interview questions

  • Your server reports "No space left on device" but df -h shows 40% free. What do you do?
  • What is the difference between a hard link and a symbolic link? Give practical examples.

Sign up free to read the full topic

More Linux topics

Start free on Cariara · Coding problems · System design studio