Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 16: Page and Buffer Cache


if (!error) {
page_cache_get(page);
SetPageLocked(page);
page->mapping = mapping;
page->index = offset;
mapping->nrpages++;
}
...
return error;
}

The index in the page cache and the pointer to the address space of the page are held in the correspond-
ing elements ofstruct page(mappingandindex). Finally, the address space page count (nrpages)is
incremented by 1 because there is now one more page in the cache.

An alternative function namedadd_to_page_cache_lruwith identical prototype is also available. This
first invokesadd_to_page_cacheto add a page to the address space-specific page cache before also
adding the page to the system’s LRU cache using thelru_cache_addfunction.

16.4.2 Finding Pages


Keeping all cached pages in a radix tree data structure is especially beneficial when the kernel needs to
decide if a given page is cached or not.find_get_pageis provided for this purpose:

mm/filemap.c
struct page * find_get_page(struct address_space *mapping, pgoff_t offset)
{
struct page *page;

page = radix_tree_lookup(&mapping->page_tree, offset);
if (page)
page_cache_get(page);
return page;
}

Life is easy for the page cache because all the hard work is done by the radix tree implementation:
radix_tree_lookupfinds the desired page at a givenoffset,andpage_cache_getincrements the page’s
reference count if one was found.

However, pages will very often belong to a file. Unfortunately, positions in a file are specified as byte
offsets, not as offsets within the page cache. How can a file offset be converted into a page cache offset?

Currently, the granularity of the page cache is a single page; that is, the leaf elements of the page cache
radix tree are single pages. Future kernels might, however, increase the granularity, so assuming a page
size granularity is not valid. Instead, the macroPAGE_CACHE_SHIFTis provided. The object size for a page
cache element can be computed by 2PAGE_CACHE_SHIFT.

Converting between byte offsets in a file and page cache offsets is then a simple matter of dividing the
index byPAGE_CACHE_SHIFT:

index = ppos >> PAGE_CACHE_SHIFT;
Free download pdf