From c3e96bd42d7654888311b077578f0ad7ec147692 Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Mon, 9 Aug 2010 17:19:48 -0700 Subject: [PATCH] --- yaml --- r: 207266 b: refs/heads/master c: ad8c2ee801ad7a52d919b478d9b2c7b39a72d295 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/linux/rmap.h | 2 ++ trunk/mm/memory.c | 4 +++- trunk/mm/rmap.c | 13 ++++++++++++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index e4e726965e8a..5ed372ad63df 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 51b1bd2ace1595b72956224deda349efa880b693 +refs/heads/master: ad8c2ee801ad7a52d919b478d9b2c7b39a72d295 diff --git a/trunk/include/linux/rmap.h b/trunk/include/linux/rmap.h index dc9b3c0bf5d4..d6661de56f30 100644 --- a/trunk/include/linux/rmap.h +++ b/trunk/include/linux/rmap.h @@ -162,6 +162,8 @@ static inline void anon_vma_merge(struct vm_area_struct *vma, */ void page_move_anon_rmap(struct page *, struct vm_area_struct *, unsigned long); void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long); +void do_page_add_anon_rmap(struct page *, struct vm_area_struct *, + unsigned long, int); void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned long); void page_add_file_rmap(struct page *); void page_remove_rmap(struct page *); diff --git a/trunk/mm/memory.c b/trunk/mm/memory.c index 6b0c37dcfd16..6bc039486e9f 100644 --- a/trunk/mm/memory.c +++ b/trunk/mm/memory.c @@ -2628,6 +2628,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, swp_entry_t entry; pte_t pte; struct mem_cgroup *ptr = NULL; + int exclusive = 0; int ret = 0; if (!pte_unmap_same(mm, pmd, page_table, orig_pte)) @@ -2722,10 +2723,11 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, if ((flags & FAULT_FLAG_WRITE) && reuse_swap_page(page)) { pte = maybe_mkwrite(pte_mkdirty(pte), vma); flags &= ~FAULT_FLAG_WRITE; + exclusive = 1; } flush_icache_page(vma, page); set_pte_at(mm, address, page_table, pte); - page_add_anon_rmap(page, vma, address); + do_page_add_anon_rmap(page, vma, address, exclusive); /* It's better to call commit-charge after rmap is established */ mem_cgroup_commit_charge_swapin(page, ptr); diff --git a/trunk/mm/rmap.c b/trunk/mm/rmap.c index 4d152a6d3a89..a7d0f5482634 100644 --- a/trunk/mm/rmap.c +++ b/trunk/mm/rmap.c @@ -829,6 +829,17 @@ static void __page_check_anon_rmap(struct page *page, */ void page_add_anon_rmap(struct page *page, struct vm_area_struct *vma, unsigned long address) +{ + do_page_add_anon_rmap(page, vma, address, 0); +} + +/* + * Special version of the above for do_swap_page, which often runs + * into pages that are exclusively owned by the current process. + * Everybody else should continue to use page_add_anon_rmap above. + */ +void do_page_add_anon_rmap(struct page *page, + struct vm_area_struct *vma, unsigned long address, int exclusive) { int first = atomic_inc_and_test(&page->_mapcount); if (first) @@ -839,7 +850,7 @@ void page_add_anon_rmap(struct page *page, VM_BUG_ON(!PageLocked(page)); VM_BUG_ON(address < vma->vm_start || address >= vma->vm_end); if (first) - __page_set_anon_rmap(page, vma, address, 0); + __page_set_anon_rmap(page, vma, address, exclusive); else __page_check_anon_rmap(page, vma, address); }