Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 16: Page and Buffer Cache


.sync_page = block_sync_page,
.write_begin = blkdev_write_begin,
.write_end = blkdev_write_end,
.writepages = generic_writepages,
.direct_IO = blkdev_direct_IO,
};

Again, it is clear that a large number of special functions are used to implement the requirements, but
they quickly lead to the kernel’s standard functions:

Block layer Standard function
blkdev_readpage block_read_full_page
blkdev_writepage block_write_full_page
blkdev_write_begin block_write_begin
blkdev_write_end block_write_end
blkdev_direct_IO __blockdev_direct_IO

The implementation of the address space operations for filesystems and raw access to block devices have
much in common in the kernel since both share the same helper functions.

16.4 Implementation of the Page Cache


The page cache is implemented on top of radix trees. Although the cache belongs to the most
performance-critical parts of the kernel and is widely used across all subsystems, the implementation is
astonishingly simple. Well-designed data structures are an essential ingredient for this.

16.4.1 Allocating Pages


page_cache_allocis used to reserve the data structure of a new page to be added to the page cache. The
variant postfixed by_coldworks identically, but tries to obtain a cache cold page:

<pagemap.h>
struct page *page_cache_alloc(struct address_space *x)
struct page *page_cache_alloc_cold(struct address_space *x)

Initially, the radix tree is left untouched because work is delegated toalloc_pages, which takes a page
frame from the buddy system (described in Chapter 3). However, the address space argument is required
to infer from which memory region that page must come.

Adding the new page to the page cache is a little more complicated and falls under the responsibility of
add_to_page_cache. Here,radix_tree_insertinserts thepageinstance associated with the page into
the radix tree of the address space involved:

mm/filemap.c
int add_to_page_cache(struct page *page, struct address_space *mapping,
pgoff_t offset, gfp_t gfp_mask)
{
...
error = radix_tree_insert(&mapping->page_tree, offset, page);
Free download pdf