Chapter 4: Virtual Process Memory
if (!page_mapped(page))
goto out;
anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON);
return anon_vma;
}
Oncethecodehasensuredthatthepage->mappingpointer actually points to ananon_vmainstance using
the by-now-familiar trick (the least significant bit of the pointer must be set),page_mappedchecks whether
the page has been mapped at all (page->_mapcountmust then be greater than or equal to 0). If so, the
function returns a pointer to theanon_vmainstance associated with the page.
page_referenced_anonmakes use of this knowledge as follows:
mm/rmap.c
static int page_referenced_anon(struct page *page)
{
unsigned int mapcount;
struct anon_vma *anon_vma;
struct vm_area_struct *vma;
int referenced = 0;
anon_vma = page_lock_anon_vma(page);
if (!anon_vma)
return referenced;
mapcount = page_mapcount(page);
list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
referenced += page_referenced_one(page, vma, &mapcount);
if (!mapcount)
break;
}
return referenced;
}
Once the matchinganon_vmainstance has been found, the kernel iterates over all regions in the list
and invokespage_referenced_onefor each one to return the number of places at which the page is
used (some corrections are required when the system is swapping pages in and out, but these are not of
interest here and are discussed in Section 18.7). The results are added together for all pages before the
total is returned.^14
page_referenced_oneperforms its task in two steps:
- It finds the page table entry that points to the page. This is possible because not only the
pageinstance but also the associatedvm_area_structis passed topage_referenced_one.
The position in virtual address space at which the page is mapped can be determined from
the latter variable.
(^14) The kernel terminates its work when the number of references reaches the number of mappings held inmapcountas it makes no
sense to continue searching.page_referenced_oneautomatically decrements themapcountcounter passed for each referenced
page.