An inode (index node) is the data structure a Linux filesystem uses to describe a single file system object: a regular file, directory, symbolic link, device node, socket or named pipe. It stores the object’s metadata and the location of its data blocks, and it is identified by an inode number that is unique within its filesystem. Notably, an inode does not contain the file name.
Names live in directories, which are lists of entries mapping each name to an inode number. This separation between name and identity is a fundamental filesystem concept inherited from early Unix. It explains hard links, why renaming a large file is instantaneous, why disk space can remain in use after a file is deleted and why a filesystem can run out of inodes while it still has free space.
What an inode stores
The exact layout depends on the filesystem, but the information an inode holds follows the POSIX file model. The stat command displays most of it, and ls -i prints inode numbers.
| Field | Meaning | Visible with |
|---|---|---|
| File type and mode | Type plus permission bits such as 0644 | ls -l, stat |
| Owner and group | Numeric UID and GID | ls -n, stat |
| Size | Length of the data in bytes | ls -l, stat |
| Link count | Number of directory entries pointing to the inode | ls -l, second column |
| Timestamps | atime, mtime, ctime and, on many filesystems, creation time | stat |
| Data location | Block pointers or extents describing where data is stored | debugfs, filefrag |
| Extended attributes | ACLs, security labels and other key-value data | getfattr, getfacl |
Two timestamps are frequently confused. mtime changes when the file content changes, whereas ctime is the inode change time, updated whenever metadata such as permissions, owner or link count changes. ctime is not a creation time; newer filesystems record creation separately as birth time.
How names, directories and inodes connect
Opening /home/anna/report.txt is a chain of lookups. The kernel starts at the root directory’s inode, reads its entries to find home and its inode number, repeats the process for anna and finally finds the directory entry for report.txt, which yields the file’s inode. The Linux dentry cache keeps recently resolved names in memory, so this lookup is usually fast.
Because a name is only a pointer, several names can refer to the same inode. Each such name is a hard link, and the inode’s link count records how many exist. The data is freed only when the link count reaches zero and no process still has the file open. A symbolic link works differently: it is a separate inode whose content is a path.
| Operation | Effect on the inode | Practical consequence |
|---|---|---|
| Rename within a filesystem | Inode unchanged, only directory entries change | Instant, even for huge files |
| Move to another filesystem | New inode created, data copied | Slow, needs space on the target |
| Create a hard link | Link count increases | Both names are fully equal |
| Create a symbolic link | New inode storing a path | Breaks if the target is removed |
| Delete a name | Link count decreases | Space freed only at zero links and no open handles |
inode handling in ext4, XFS and Btrfs
Filesystems differ mainly in when inodes are allocated and how data locations are recorded. The difference matters most for workloads with millions of small files.
| Filesystem | inode allocation | Default inode size | Data mapping |
|---|---|---|---|
| ext4 | Fixed number set when the filesystem is created | 256 bytes | Extents, with small data optionally inline |
| XFS | Dynamic, up to a configurable share of space | 512 bytes | Extents in B+ trees |
| Btrfs | Dynamic, stored as items in B-trees | Not a fixed on-disk slot | Extents with copy-on-write |
On ext4, the number of inodes is derived from the bytes-per-inode ratio, typically one inode per 16 KiB of capacity on general-purpose filesystems. It can be set with the -i or -N options of mkfs.ext4 but cannot be increased later without recreating the filesystem. XFS and Btrfs avoid that limit by allocating inodes as needed.
Monitoring and planning inode capacity
A filesystem can refuse to create files with the error No space left on device while df -h still shows free gigabytes. The cause is inode exhaustion, visible with df -i, which reports used and free inodes. It typically appears on mail spools, caches, build directories and session stores holding millions of tiny files.
- Monitor inode usage alongside disk usage and alert at around 80 percent.
- Find directories with many entries using
du --inodesor a count of files per directory. - For many small files on ext4, create the filesystem with a lower bytes-per-inode ratio.
- Consider XFS or Btrfs when the number of files is hard to predict.
Common misconceptions and pitfalls
A common surprise is space not released after deletion. When a large log file is deleted while a process still writes to it, the name disappears but the inode and its blocks stay allocated until the process closes the file. lsof +L1 lists such open but unlinked files; restarting or signaling the process releases the space.
Another misconception is that inode numbers identify files globally. They are unique only within one filesystem, so tools that detect identical files compare both the device ID and the inode number. Inode numbers can also be reused after deletion, which matters for backup and synchronization tools that track files by number.
Understanding it simply
Think of a library. The catalog card for a book records its author, size, location on the shelf and who may borrow it. The title signs on the shelves only point to that card.
An inode is the catalog card of a file. The file name is just a label pointing to it. That is why one file can have several names, and why renaming a file does not move any of its data.
Applied in practice
An e-commerce site stores image thumbnails on a 200 GB ext4 volume. One morning, uploads fail with No space left on device, although df -h shows 70 GB free. The administrator runs df -i and sees that all 13 million inodes are used, because a cache directory holds millions of files of a few kilobytes each.
As an immediate fix, the team deletes cache entries older than 30 days, which frees several million inodes. For the long term, it moves the cache to a new XFS volume with dynamic inode allocation and adds an alert when inode usage exceeds 80 percent. The incident does not recur.