logo

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:

  1. Kernel looks at the inode for / (the root inode is usually #2).
  2. It reads the data blocks of inode #2 to find the directory table for /.
  3. In that table, it finds the entry for home and gets its inode number.
  4. It repeats this for user, then test.txt.
  5. 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
  • 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):

  1. The kernel creates a new entry in the target directory table with the old inode number.
  2. The kernel removes the entry from the old directory table.
  3. 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:

  1. i_op (Inode Operations): These are functions that act on the file as an object in the filesystem.
    • Examples: create(), lookup(), link(), mkdir(), rename().
  2. i_fop (File Operations): These are functions that act on the data inside the file.
    • Examples: read(), write(), mmap(), open().

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:

  1. Locates the struct inode for that file.
  2. Copies the relevant data (size, owner, inode number) into a user-space structure called struct stat.
  3. 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 dentry has a pointer to an inode.
  • There's no pointer from struct inode to struct 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:

  1. A dentry for home (pointing to the home inode).
  2. A dentry for user (pointing to the user inode).
  3. A dentry for file.txt (pointing to the file.txt inode).

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":

  1. Start at Root: The kernel knows the root directory (/) is always at a fixed Inode (usually #2).
  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.
  3. Lookup log: The kernel reads Inode #500's data blocks. It finds the string "log" and sees it maps to Inode #800.
  4. Lookup syslog: The kernel reads Inode #800's data blocks. It finds the string "syslog" and sees it maps to Inode #9999.
  5. 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 because file2.txt still points to it.
  • The data is only deleted when the link count reaches 0.