Linux - Inode
An Inode (Index Node) is the most fundamental data structure in a Linux filesystem. If you understand inodes, you understand how Linux actually "sees" files.
What is an Inode?
An inode is a data structure that describes a filesystem object (a file, a directory, a symbolic link, etc.).
Crucially: The inode contains all the metadata about a file EXCEPT its name.
What is inside an Inode?
An inode is a struct inode. It is defined in the header file include/linux/fs.h.
- File Type: (Regular file, directory, block device, etc.)
- Permissions: (Read, Write, Execute for Owner/Group/Others)
- Owner Info: (UID and GID)
- File Size: (In bytes)
- Timestamps: (mtime: modification, atime: access, ctime: change)
- Link Count: How many hard links point to this inode.
- Data Block Pointers: A list of "addresses" on the physical disk where the actual content of the file is stored.
The Inode Number
Every inode has a unique ID number within its specific filesystem.
- To the Linux kernel, the "name" of a file is irrelevant. It identifies the file by its Inode Number.
- You can see the inode number of a file using
ls -i:$ ls -i myfile.txt 1234567 myfile.txt
Relationship: Path vs. Filename vs. Inode
This is the part that surprises many: A "Directory" is just a special file that contains a simple lookup table.
The table in a directory looks like this:
| Filename | Inode Number |
|---|---|
notes.txt |
5501 |
photo.jpg |
8829 |
scripts |
1002 |
How the kernel opens /home/user/test.txt:
- Kernel looks at the inode for
/(the root inode is usually #2). - It reads the data blocks of inode #2 to find the directory table for
/. - In that table, it finds the entry for
homeand gets its inode number. - It repeats this for
user, thentest.txt. - Finally, it has the inode number for
test.txt, which tells it which disk blocks to read to get your data.
How are Inodes stored?
Inodes are stored in an Inode Table on the physical disk.
- Fixed Allocation (e.g., ext4): When you format a partition, the filesystem sets aside a specific amount of space for the Inode Table. This means there is a finite number of inodes. Even if you have 100GB of free disk space, if you run out of inodes (by creating millions of tiny empty files), you cannot create new files.
- Check your inode usage with:
df -i
- Check your inode usage with:
- Dynamic Allocation (e.g., XFS, Btrfs): These filesystems create inodes on the fly as needed, so you rarely "run out" of them.
Practical Implications of the Inode Design
Hard Links
A hard link is simply two filenames pointing to the same inode number.
- Since they point to the same inode, they share the same permissions, owner, and data.
- If you edit one, the other changes (because the data blocks are the same).
- If you delete one filename, the inode (and data) stays alive until the "Link Count" reaches zero.
Renaming/Moving Files
When you move a file within the same filesystem (mv file1 file2):
- The kernel creates a new entry in the target directory table with the old inode number.
- The kernel removes the entry from the old directory table.
- The inode itself and the data blocks are never touched. This is why moving a 10GB file within the same partition is instantaneous.
Deleting a "Busy" File
Have you ever deleted a giant log file, but df shows that the disk space is still full?
- This happens because a process (like a web server) still has that file open.
- An inode is only truly deleted when its Link Count is 0 AND its Open Reference Count is 0.
- The filename is gone, but the inode and data blocks remain on disk until the process closes the file or exits.
The Two "Lives" of an Inode
It is important to distinguish between the inode on the disk and the inode in memory.
The On-Disk Inode
Every filesystem (ext4, XFS, etc.) has its own physical inode structure defined in its own code. For example, ext4 uses struct ext4_inode. This is a compact, binary structure optimized for storage on the hard drive.
The In-Memory Inode (struct inode)
When you try to access a file, the kernel reads the on-disk inode and "translates" (inflates) it into the generic struct inode. This object stays in the kernel's memory in a special area called the Inode Cache (icache) so that the next time you access the file, the kernel doesn't have to read the disk again.
Inode Operations vs. File Operations
Inside struct inode, you'll notice two different sets of function pointers:
i_op(Inode Operations): These are functions that act on the file as an object in the filesystem.- Examples:
create(),lookup(),link(),mkdir(),rename().
- Examples:
i_fop(File Operations): These are functions that act on the data inside the file.- Examples:
read(),write(),mmap(),open().
- Examples:
User-space View: struct stat
If you are writing a C program in user-space (not a kernel module), you cannot access struct inode directly because it is in kernel memory. Instead, you use the stat() system call.
When you call stat("myfile.txt", &buffer), the kernel:
- Locates the
struct inodefor that file. - Copies the relevant data (size, owner, inode number) into a user-space structure called
struct stat. - Sends it back to your program.
How to find the filename from the inode?
TL;DR: the mapping is only from dentry to inode.
- The filename lives in the
struct dentry(Directory Entry). struct dentryhas a pointer to an inode.- There's no pointer from
struct inodetostruct dentry.
From a pure kernel-programming perspective, if you only have a struct inode *, finding "the" filename is difficult, slow, and sometimes impossible.
On-Disk: The Directory Table
When you create a file named photo.jpg and the filesystem assigns it Inode #12345, the filesystem goes to the data blocks of the parent directory and writes a new entry.
A simplified version of that table looks like this:
| Inode Number | Name Length | File Type | Filename |
|---|---|---|---|
| 1002 | 4 | Directory | . (current) |
| 880 | 5 | Directory | .. (parent) |
| 12345 | 9 | Regular | photo.jpg |
| 12346 | 8 | Regular | note.txt |
Key takeaway: The filename photo.jpg is stored only in this directory table. It is not stored in the inode itself. This is why a single inode can have multiple names (Hard Links).
In-Memory: struct dentry
Reading the disk table every time you want to access a file would be incredibly slow. To solve this, the Linux Kernel uses a specific data structure in memory called a Dentry (Directory Entry).
While the Inode represents the metadata of the file, the Dentry represents the hierarchy (the path).
struct inode: Represents the object (The "What").struct dentry: Represents the link between a name and an inode (The "Where").
When you access /home/user/file.txt, the kernel creates (and caches) three dentry objects:
- A dentry for
home(pointing to thehomeinode). - A dentry for
user(pointing to theuserinode). - A dentry for
file.txt(pointing to thefile.txtinode).
The Dentry Cache (dcache) keeps these in RAM so that the next time you access the file, the kernel doesn't have to parse the directory table on the disk.
How the mapping is resolved (Step-by-Step)
When you run cat /var/log/syslog, the kernel performs "Path Resolution":
- Start at Root: The kernel knows the root directory (
/) is always at a fixed Inode (usually #2). - Lookup
var: The kernel reads Inode #2's data blocks (the directory table for/). it finds the string"var"and sees it maps to Inode #500. - Lookup
log: The kernel reads Inode #500's data blocks. It finds the string"log"and sees it maps to Inode #800. - Lookup
syslog: The kernel reads Inode #800's data blocks. It finds the string"syslog"and sees it maps to Inode #9999. - Access Data: Now the kernel has Inode #9999. It looks at the metadata (permissions) and then uses the "Data Block Pointers" inside that inode to start reading the actual text of your logs.
Why this mapping matters (Hard Links)
Because the "name → inode" mapping is just an entry in a table, you can have two different names point to the same inode number.
# Create a file
echo "hello" > file1.txt # Assigned Inode 555
# Create a hard link
ln file1.txt file2.txt # Directory table now has two entries for Inode 555
Result:
- Inode #555 now has an internal
i_nlink(link count) of 2. - If you delete
file1.txt, you are just removing that specific mapping from the directory table. The inode and the data survive becausefile2.txtstill points to it. - The data is only deleted when the link count reaches 0.