READAHEAD OVERVIEW(9)
π Readahead Overview π
okay so this is the Kernel API Manual page for Readahead, section 9, and bestie it is actually so good once you get the vibe. let's get into it π«Ά
Readahead is the whole "read it before they ask" situation β it reads content into the page cache before the application explicitly requests it. Iconic. But like, it's picky in a good way: readahead only ever attempts to read folios that are not yet in the page cache. If a folio is present but not up-to-date, readahead will not try to read it β in that case a simple ->read_folio will be requested instead. no gatecrashing β¨
πΈ When does it even trigger
Readahead gets triggered when an application read request (whether a system call or a page fault) finds that the requested folio is not in the page cache, or that it is in the page cache and has the readahead flag set. That flag means: this folio was read as part of a previous readahead request, and now that it has been accessed, it's time for the next readahead. literally a little "you're up" note π
π¦ The sync bit and the async bit
Every readahead request is partly synchronous read, and partly async readahead. This shows up in the struct file_ra_state, which contains:
->sizeβ the total number of pages->async_sizeβ the number of pages in the async section
The readahead flag gets set on the first folio in this async section to trigger a subsequent readahead. And once a series of sequential reads has been established, there should be no need for a synchronous component at all β every readahead request will be fully asynchronous. glow up β¨
π The three numbers
When either of the triggers causes a readahead, three numbers need to be determined:
- the start of the region to read
- the size of the region
- the size of the async tail
π Start of the region
Simply the first page address at or after the accessed address which is not currently populated in the page cache. Found with a simple search in the page cache. cute and efficient.
π Size of the async tail
Determined by subtracting the size that was explicitly requested from the determined request size β unless this would be less than zero, in which case zero is used.
β οΈ NOTE THIS CALCULATION IS WRONG WHEN THE START OF THE REGION IS NOT THE ACCESSED PAGE. ALSO THIS CALCULATION IS NOT USED CONSISTENTLY. fr fr, that's the manpage yelling, not me π
π Size of the region
Normally determined from the size of the previous readahead which loaded the preceding pages. This may be discovered from the struct file_ra_state for simple sequential reads, or from examining the state of the page cache when multiple sequential reads are interleaved.
Specifically: where the readahead was triggered by the readahead flag, the size of the previous readahead is assumed to be the number of pages from the triggering page to the start of the new readahead. In these cases, the size of the previous readahead is scaled, often doubled, for the new readahead β though see get_next_ra_size for the details.
π When we can't figure out the previous read
If the size of the previous read cannot be determined, the number of preceding pages in the page cache is used to estimate the size of a previous read. But plot twist: this estimate could easily be misled by random reads being coincidentally adjacent π« so it is ignored unless it is larger than the current request, and it is not scaled up, unless it is at the start of file.
In general, readahead is accelerated at the start of the file, since reads from there are often sequential. There are other minor adjustments to the readahead size in various special cases, and honestly those are best discovered by reading the code. iykyk π
The above calculation, based on the previous readahead size, determines the size of the readahead, to which any requested read size may be added.
β Talking to the filesystem
Readahead requests are sent to the filesystem using the ->readahead address space operation, for which mpage_readahead is a canonical implementation.
->readahead should normally initiate reads on all folios, but may fail to read any or all folios without causing an I/O error. The page cache reading code will issue a ->read_folio request for any folio which ->readahead did not read, and only an error from this will be final. so like, the fallback has your back π«Ά
->readahead will generally call readahead_folio repeatedly to get each folio from those prepared for readahead. It may fail to read a folio by:
- not calling
readahead_foliosufficiently many times, effectively ignoring some folios, as might be appropriate if the path to storage is congested - failing to actually submit a read request for a given folio, possibly due to insufficient resources, or
- getting an error during subsequent processing of a request
In the last two cases, the folio should be unlocked by the filesystem to indicate that the read attempt has failed. In the first case the folio will be unlocked by the VFS.
π Urgent folios vs. less urgent folios
Those folios not in the final async_size of the request should be considered to be important, and ->readahead should not fail them due to congestion or temporary resource unavailability β instead it should wait for necessary resources (e.g. memory or indexing information) to become available.
Folios in the final async_size may be considered less urgent, and failure to read them is more acceptable. In this case it is best to use filemap_remove_folio to remove the folios from the page cache, as is automatically done for folios that were not fetched with readahead_folio. This will allow a subsequent synchronous readahead request to try them again. If they are left in the page cache, then they will be read individually using ->read_folio β which may be less efficient. π
π SEE ALSO π
Kernel file ./mm/readahead.c read_pages(9), page_cache_ra_unbounded(9), readahead_expand(9)
k that's the whole thing bestie, go be iconic with it π
source dir ./mm Β· version date October 2026 Β· mwah π
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms