Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 8: The Virtual Filesystem


Independent of the expected read pattern, thefind_get_pagefunction checks whether the page is
already in the page cache. Afterward, the kernel handles a sequential read hint that could be associ-
ated with the VM area to which the page belongs.^28 The generic readahead logic that is used in this case
consists of the following code sequence:


mm/filemap.c
if (VM_SequentialReadHint(vma)) {
if (!page) {
page_cache_sync_readahead(mapping, ra, file,
vmf->pgoff, 1);
page = find_lock_page(mapping, vmf->pgoff);
if (!page)
goto no_cached_page;
}
if (PageReadahead(page)) {
page_cache_async_readahead(mapping, ra, file, page,
vmf->pgoff, 1);
}
}

The mechanism is identical with the mechanism used indo_generic_mapping_read. When the page can-
not be found with synchronous readahead, the jump tono_cached_pageemployspage_cache_readto
allocate a new page in the page cache and issue a read request. Afterward, the code retries the operation
from the first call tofind_lock_pageonward. Obviously, this requires using C’sgotofeature.


Let’s go back to the code snippet shown above. If the page was present in the system, it has origi-
nated from a previous readahead operation. As discussed in Chapter 16.4.5., the readahead mecha-
nism marks a page near the end of a readahead window, that is, a range of files that is read in before
a process actually requests them. Once this page is reached, then asynchronous readahead should
be started to read in pages speculatively. The required mark is thePG_readaheadbit (which can be
checked withPageReadahead), and the function responsible to perform asynchronous readahead is
page_cache_async_readahead. Again, notice that more details about this mechanism are discussed in
Chapter 16.4.5.


If no sequential readahead hint was given and the page could not be found in the page cache, the generic
readahead mechanism needs to be invoked. Slightly simplified, it is implemented as follows:


mm/filemap.c
if (!page) {
unsigned long ra_pages;
...
ra_pages = max_sane_readahead(file->f_ra.ra_pages);
if (ra_pages) {
pgoff_t start = 0;

if (vmf->pgoff > ra_pages / 2)
start = vmf->pgoff - ra_pages / 2;
do_page_cache_readahead(mapping, file, start, ra_pages);
}

(^28) It sounds odd that the kernel checks for a sequential read hint even if a random read hint was found only a couple of steps before,
and the check could in this case be, in fact, avoided. However, the structure offilemap_fault, which contains a quite liberal use
ofgoto, can lead to this situation.

Free download pdf