Lots of deletions: the next patch will put in the new anon rmap,I expect it to look clearer if first we remove all of the oldpte-pointer-based anon rmap in this patch - which thereforeleaves anonymous rmap totally disabled, anon pages locked inmemory until the process frees them.

A few additions: the previous patch brought ClearPageAnon intormap.c instead of leaving it to final page free; but I thinkthere'd be a race with swapin or swapoff doing SetPageAnon:now SetPageAnon under lock within page_add_rmap. That locknow being called rmap_lock instead of pte_chain_lock.

Removed nr_reverse_maps, ReverseMaps: easily reverted if thatposes a vmstat or meminfo compatibility problem, or someone isstill interested in that number; but objrmap wasn't maintainingit, and if they don't occupy space, is it worth showing?Besides, look at page_dup_rmap for copy_page_range: I don'twant to clutter that with inc_page_state(nr_reverse_maps).

/* * Locking:- * - the page->pte.chain is protected by the PG_chainlock bit,- * which nests within the zone->lru_lock, then the- * mm->page_table_lock, and then the page lock.+ * - the page->rmap field is protected by the PG_rmaplock bit,+ * which nests within the mm->page_table_lock,+ * which nests within the page lock. * - because swapout locking is opposite to the locking order * in the page fault path, the swapout path uses trylocks * on the mm->page_table_lock */+ #include <linux/mm.h> #include <linux/pagemap.h> #include <linux/swapops.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/rmap.h>-#include <linux/cache.h> #include <linux/percpu.h>--#include <asm/pgalloc.h>-#include <asm/rmap.h>-#include <asm/tlb.h> #include <asm/tlbflush.h>

/* * Something oopsable to put for now in the page->mapping@@ -50,61 +43,13 @@ ClearPageAnon(page); }

-/*- * Shared pages have a chain of pte_chain structures, used to locate- * all the mappings to this page. We only need a pointer to the pte- * here, the page struct for the page table page contains the process- * it belongs to and the offset within that process.- *- * We use an array of pte pointers in this structure to minimise cache misses- * while traversing reverse maps.- */-#define NRPTE ((L1_CACHE_BYTES - sizeof(void *))/sizeof(pte_addr_t))--struct pte_chain {- struct pte_chain *next;- pte_addr_t ptes[NRPTE];-} ____cacheline_aligned;--kmem_cache_t *pte_chain_cache;--/*- * pte_chain list management policy:- *- * - If a page has a pte_chain list then it is shared by at least two processes,- * because a single sharing uses PageDirect. (Well, this isn't true yet,- * coz this code doesn't collapse singletons back to PageDirect on the remove- * path).- * - A pte_chain list has free space only in the head member - all succeeding- * members are 100% full.- * - If the head element has free space, it occurs in its leading slots.- * - All free space in the pte_chain is at the start of the head member.- * - Insertion into the pte_chain puts a pte pointer in the last free slot of- * the head member.- * - Removal from a pte chain moves the head pte of the head member onto the- * victim pte and frees the head member if it became empty.- */- /**- ** VM stuff below this comment+ ** Subfunctions of page_referenced: page_referenced_one called+ ** repeatedly from page_referenced_obj. **/

-/**- * find_pte - Find a pte pointer given a vma and a struct page.- * @vma: the vma to search- * @page: the page to find- *- * Determine if this page is mapped in this vma. If it is, map and rethrn- * the pte pointer associated with it. Return null if the page is not- * mapped in this vma for any reason.- *- * This is strictly an internal helper function for the object-based rmap- * functions.- * - * It is the caller's responsibility to unmap the pte if it is returned.- */-static inline pte_t *-find_pte(struct vm_area_struct *vma, struct page *page, unsigned long *addr)+static int+page_referenced_one(struct page *page, struct vm_area_struct *vma) { struct mm_struct *mm = vma->vm_mm; pgd_t *pgd;@@ -112,6 +57,7 @@ pte_t *pte; unsigned long loffset; unsigned long address;+ int referenced = 0;

- /*- * If this is an object-based page, just count it. We can- * find the mappings by walking the object vma chain for that object.- */- if (!PageAnon(page)) {- if (PageSwapCache(page))- BUG();- if (!page->pte.mapcount)- inc_page_state(nr_mapped);- page->pte.mapcount++;- pte_chain_unlock(page);- return pte_chain;- }+ if (!page_mapped(page))+ inc_page_state(nr_mapped);+ page_mapcount(page)++;