Fundamentals 30 min read

Why Understanding Linux Memory Caches Is Essential for Mastering File Access

The article explains how Linux uses page cache, inode cache, and dentry cache to accelerate file operations, detailing their structures, lookup mechanisms, LRU eviction, and real‑world performance impact, and shows step‑by‑step path resolution with code examples.

Deepin Linux
Deepin Linux
Deepin Linux
Why Understanding Linux Memory Caches Is Essential for Mastering File Access

1. Review of Page Cache

Page cache is the kernel area that stores file data in memory, bridging the huge speed gap between RAM (nanoseconds) and disk (milliseconds). It accelerates reads of hot files, merges small writes into larger ones, and enables zero‑copy operations such as sendfile(), dramatically reducing disk I/O.

2. Inode Cache Analysis

2.1 What Is the Inode Cache?

The inode cache (icache) holds file metadata—permissions, size, timestamps, owner, and block pointers—so the kernel can fetch this information from memory instead of disk.

2.2 How the Inode Cache Works

Each file has a unique inode that acts like a record card. When a file is accessed, the kernel first locates its inode number, then uses the inode’s block pointers to read the file’s data blocks. If the inode is already cached, the lookup is instantaneous; otherwise the kernel reads it from disk and stores it in the cache.

2.3 Storage of Inodes

Inodes are stored on disk in an inode table, but frequently used ones are copied into memory. The in‑memory representation may include reference counts and dirty flags to manage updates and eviction.

3. Dentry Cache Analysis

3.1 What Is the Dentry Cache?

The dentry cache (dcache) stores the results of pathname resolution. Each dentry contains the filename, a pointer to its inode, a pointer to its parent dentry, and a list of child dentries, forming a tree that mirrors the directory hierarchy.

3.2 How the Dentry Cache Works

When resolving a path such as /usr/local/bin/python, the kernel walks the dentry tree from the root, looking up each component in a hash table. A cache hit returns the associated inode immediately; a miss triggers a disk read to create a new dentry.

3.3 Dentry Structure and Organization

Dentries are linked via d_parent and child lists, and are organized in a hash table for O(1) lookup. An LRU list tracks usage; least‑recently used dentries are evicted when memory is scarce.

4. Linux Path‑Resolution Process

4.1 Starting from the Root Directory

The kernel begins at the root inode, reads the root directory block, and finds the first component (e.g., "home") using lookup_one_len:

// From root dentry, look up first level directory "home"
struct dentry *root_dentry = dget_current_root();
struct dentry *home_dentry = lookup_one_len("home", root_dentry, 4);

4.2 Step‑by‑Step Path Parsing

For each subsequent component, the kernel repeats the hash‑table lookup, obtains the inode, and proceeds until the final file is reached.

// Resolve "home" → "user" → "file.txt"
struct dentry *user_dentry = lookup_one_len("user", home_dentry, 4);
struct dentry *file_dentry = lookup_one_len("file.txt", user_dentry, 8);

4.3 Obtaining the Target Inode

Once the final dentry is found, the inode is accessed directly:

struct inode *file_inode = file_dentry->d_inode;

5. Benefits of Inode + Dentry Caching

5.1 Cache Creation

On the first access, the kernel creates dentry objects for each path component and loads the corresponding inodes, inserting them into their respective caches.

5.2 Lookup and Hit

Subsequent accesses find the required dentries and inodes in memory, avoiding any disk I/O.

5.3 Cache Update and Eviction

Metadata changes (e.g., chmod) update the inode and its linked dentry. When memory is tight, an LRU algorithm evicts entries with zero reference counts, freeing space while keeping hot entries.

5.4 Performance Impact

Reduces disk I/O by 70‑90% in heavy‑load servers.

Accelerates file open/read by several‑fold to tens of‑fold.

Improves overall system responsiveness, especially for web servers serving static assets.

A real‑world case showed average file open time dropping from 3‑5 seconds to 0.5‑1 second after enabling these caches.

6. Case Study: Inode + Dentry Cache in Action

6.1 First Access – Cache Miss and Creation

The kernel starts at /, finds no relevant dentry, and performs disk I/O.

It reads the root block, locates etc, reads its inode.

Creates dentry objects for / and etc and inserts them into the cache.

Continues similarly for config and service.conf, finally loading the file’s inode into the inode cache.

// Kernel path lookup: create dentries and cache them
struct dentry *root = dget_current_root();
struct dentry *etc = lookup_one_len("etc", root, 3);
struct dentry *config = lookup_one_len("config", etc, 6);
struct dentry *file = lookup_one_len("service.conf", config, 12);
struct inode *inode = iget_locked(sb, ino);

6.2 Subsequent Access – Full Cache Hit

Root dentry is found in memory.

Hash‑table lookups quickly locate etc, config, and service.conf dentries.

No disk I/O occurs; the inode is obtained directly from the cached dentry.

// Directly fetch from cache
struct dentry *cached = d_lookup(parent_dentry, &name);
struct inode *cached_inode = cached->d_inode;

6.3 File Modification – Automatic Cache Update

When chmod or a write changes the file, the kernel updates the inode fields and marks the inode dirty; the linked dentry remains valid.

inode->i_mode = new_mode;
inode->i_size = new_size;
inode->i_ctime = current_time(inode);
mark_inode_dirty(inode);

6.4 Memory Pressure – LRU Eviction

The kernel records last‑access timestamps and reference counts for each dentry and inode.

Unused entries become candidates for eviction.

When memory is low, entries with zero references are freed.

// Evict cold dentry and inode
if (dentry->d_count == 0 && !dentry->d_connected)
    dentry_free(dentry);
iput(inode);

These mechanisms ensure that the most frequently accessed metadata stays in memory, providing fast path resolution while automatically reclaiming space for less used entries.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

LinuxLRUfile systempage cacheMemory CachePath ResolutionDentry CacheInode Cache
Deepin Linux
Written by

Deepin Linux

Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.