Skip to main content

Inode

An inode is a data structure in a Linux filesystem that stores metadata about a file — its permissions, owner, size, and data block locations — but not its filename. The filename lives in a directory entry that points to the inode number.

What Is an Inode in Simple Terms

Think of a library again. The inode is the library card — it contains all the information about a book (author, size, location on shelves, who can borrow it) but not the title. The title is written on a separate index card (the directory entry) that says "the book called X is at library card number 12345."

This separation is what makes hard links possible: two different titles (filenames) can point to the same library card (inode) — the same actual file content.

How It Works

Every file and directory has exactly one inode. Every inode has a unique number within its filesystem. Directory entries map filenames to inode numbers.

◈ DIAGRAM
Directory /etc/
+-------------------------+
| hostname -> inode 1234 |
| hosts -> inode 1235 |
| passwd -> inode 1236 |
| shadow -> inode 1237 |
+-------------------------+
Inode 1235 (hosts file)
+-----------------------------+
| Permissions: 644 |
| Owner UID: 0 (root) |
| Group GID: 0 (root) |
| Size: 221 bytes |
| Last modified: Jan 15 09:00 |
| Links: 1 (number of names) |
| Data blocks: [block 48291] |
+-----------------------------+

What an inode stores:

TEXT
Permissions (the 10-character rwxr-xr-x string)
Owner (UID number)
Group (GID number)
File size in bytes
Timestamps: access (atime), modify (mtime), change (ctime)
Link count (how many directory entries point to this inode)
Pointers to data blocks on disk
What it does NOT store:
- The filename (that is in the directory entry)
- The file content (that is in data blocks)

Hard links — two names, one inode:

Bash
## Create a hard link
ln /etc/hosts /tmp/hosts-hardlink
## Both names point to the same inode
ls -lai /etc/hosts /tmp/hosts-hardlink
## 1235 -rw-r--r-- 2 root root 221 Jan 15 /etc/hosts
## 1235 -rw-r--r-- 2 root root 221 Jan 15 /tmp/hosts-hardlink
## Note: same inode number (1235), link count is 2
## Modifying one modifies both (same file)
echo "127.0.0.2 test" >> /tmp/hosts-hardlink
cat /etc/hosts ## shows the change
## Deleting one does not delete the data
rm /tmp/hosts-hardlink ## link count drops to 1
cat /etc/hosts ## still works

Symbolic links — a file that points to a name:

Bash
## Create a symbolic link
ln -s /etc/hosts /tmp/hosts-symlink
## The symlink has its own inode
ls -lai /etc/hosts /tmp/hosts-symlink
## 1235 -rw-r--r-- 1 root root 221 Jan 15 /etc/hosts
## 9876 lrwxrwxrwx 1 root root 10 Jan 15 /tmp/hosts-symlink -> /etc/hosts
## Different inode numbers
## Symlink stores the target path, not the content
readlink /tmp/hosts-symlink
## /etc/hosts
## If target is deleted, symlink breaks
rm /etc/hosts
cat /tmp/hosts-symlink ## Error: No such file or directory

Practical Commands

Bash
## Show inode number with ls
ls -lai /etc/hosts
## First column is inode number
## Show inode info with stat
stat /etc/hosts
## File: /etc/hosts
## Size: 221 Blocks: 8 IO Block: 4096 regular file
## Device: 202ah/522d Inode: 1235 Links: 1
## Access: (0644/-rw-r--r--) Uid: (0/root) Gid: (0/root)
## Check inode usage across filesystem
df -i
## Shows IUsed and IFree per filesystem
## Find files by inode number (useful for finding hard links)
find / -inum 1235 2>/dev/null
## Find files with multiple hard links (inode link count > 1)
find /etc -links +1 -type f

Troubleshooting

Symptom Command What to Look For
Cannot create files, disk not full df -i IUse% at 100% — inode exhaustion
Two files always identical ls -lai both-files Same inode number = hard links
File deleted but disk space not freed `lsof grep deleted`
Symlink not working readlink -f symlinkname Target path does not exist
Tip

Inode exhaustion is more common than you might expect on servers running many small files — email servers, log servers, build systems. A mailbox directory with 2 million tiny email files can exhaust inodes even when gigabytes of disk space remain. Monitor df -i alongside df -h.

Remember

When a process deletes a file, it decrements the inode link count. The disk space is only freed when the link count reaches zero AND no process has the file open. That is why lsof | grep deleted finds files that are deleted but still consuming disk space.

Security

Hard links cannot cross filesystem boundaries. A hard link to /etc/shadow from /tmp is impossible if they are on different filesystems. This is an intentional security constraint — it prevents users from creating hard links to files they do not own.

Frequently Asked Questions

Why can a Linux filesystem run out of space for new files even when df shows free disk space?

Each filesystem allocates a fixed number of inodes at creation time, separate from data block capacity. If a workload creates millions of tiny files (a common pattern with certain caching layers or session-storage setups), you can exhaust the inode table while gigabytes of raw disk space remain free — `df -i` shows inode usage separately from `df`'s block usage, and 100% inode usage blocks all new file creation regardless of free space.

Why does a hard link not create a new inode, but a symbolic link does?

A hard link is just another directory entry pointing to the same inode number, so both names share identical permissions, ownership, and data — deleting one leaves the other intact until the inode's link count hits zero. A symlink is a separate small file with its own inode that stores a path string pointing to another file, which is why symlinks can cross filesystems and point to nonexistent targets (dangling links) in a way hard links cannot.