Creating a Reverse Mapping

When a reverse mapping is created, it is necessary to distinguish between two alternatives — anonymous pages and pages with file-based mappings. This is understandable because the data structures used to manage both alternatives also differ.

The information below only covers working with page instances to be inserted into the reverse mapping scheme. Other parts of the kernel are responsible for adding the relevant vm_area_structs to the data structures discussed above (priority tree and anon list); for example, by invoking vma_prio_tree_insert that is used (directly or indirectly) at several places in the kernel.

Anonymous Pages

There are two ways of inserting an anonymous page into the reverse mapping data structures. page_ add_new_anon_rmap must be invoked for new anonymous pages. page_add_anon_rmap is the right option for pages that are already reference-counted. The only difference between these alternatives is that the former sets the mapping counter page->_mapcount to 0 (reminder: the initial value of _mapcount is 0 for newly initialized pages), and the latter increments the counter by 1. Both functions then merge into _page_set_anon_rmap.

mm/rmap.c void _page_set_anon_rmap(struct page *page, struct vm_area_struct *vma, unsigned long address)

struct anon_vma *anon_vma = vma->anon_vma;

anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON; page->mapping = (struct address_space *) anon_vma;

page->index = linear_page_index(vma, address);

The address of the anon_vma list head is stored in the mapping element of the page instance after PAGE_ mapping_anon has been added to the pointer. This enables the kernel to distinguish between anonymous pages and pages with a regular mapping by checking whether the least significant bit is 0 (if page_mapping_anon is not set) or 1 (if page_mapping_anon is set) as discussed above. Recall that this trick is valid because the lowest-order bit of a page pointer is guaranteed to be zero because of alignment requirements.

Pages with a File-Based Mapping

Work is even simpler for pages of this type, as the following code excerpt shows: mm/rmap.c void page_add_file_rmap(struct page *page) {

if (atomic_inc_and_test(&page->_mapcount))

_inc_zone_page_state(page, NR_FILE_MAPPED);

Basically, all that needs to be done is to increment the _mapcount variable atomically and update the per-zone statistics.

Was this article helpful?

+1 0

Post a comment