Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 4: Virtual Process Memory


} shared;

/*
* A file’s MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
* list, after a COW of one of the file pages. A MAP_SHARED vma
* can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
* or brk vma (with NULL file) can only be in an anon_vma list.
*/
struct list_head anon_vma_node; /* Serialized by anon_vma->lock */
struct anon_vma *anon_vma; /* Serialized by page_table_lock */
...
}

The trick employed by the kernel when implementing reverse mapping is not to store a direct link
between a page and the associated users but only the association between a page and theregionin which
the page is located. All other regions in which the page is included (and therefore all users) can be found
by means of the data structures just mentioned. This method is also known asobject-based reverse mapping
because no direct link between page and user is stored; instead, a further object (the regions in which the
page is located) is interposed between the two.

4.8.2 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 withpageinstances to be inserted into
the reverse mapping scheme. Other parts ofthe kernel are responsible for adding
the relevantvm_area_structs to the data structures discussed above (priority tree
and anon list); for example, by invokingvma_prio_tree_insertthat is used
(directly or indirectly) at several places in the kernel.

AnonymousPages


There are two ways of inserting an anonymous page into the reverse mapping data structures.page_
add_new_anon_rmapmust be invoked for new anonymous pages.page_add_anon_rmapis the right option
for pages that are already reference-counted. The only difference between these alternatives is that the
former sets the mapping counterpage->_mapcountto 0 (reminder: the initial value of_mapcountis 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);
}
Free download pdf