diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-20 12:47:40 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2006-03-20 12:47:40 -0500 |
commit | 9a21247181d93fdf99255911845ecdb041d21583 (patch) | |
tree | 6d69be36f8a2bd8c76bf02ead2f0121a511c0a92 /mm/rmap.c | |
parent | c752666c17f870fa8ae9f16804dd457e9e6daaec (diff) | |
parent | 7705a8792b0fc82fd7d4dd923724606bbfd9fb20 (diff) | |
download | blackbird-op-linux-9a21247181d93fdf99255911845ecdb041d21583.tar.gz blackbird-op-linux-9a21247181d93fdf99255911845ecdb041d21583.zip |
Merge branch 'master'
Diffstat (limited to 'mm/rmap.c')
-rw-r--r-- | mm/rmap.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/mm/rmap.c b/mm/rmap.c index df2c41c2a9a2..67f0e20b101f 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -212,25 +212,33 @@ out: * through real pte's pointing to valid pages and then releasing * the page from the swap cache. * - * Must hold page lock on page. + * Must hold page lock on page and mmap_sem of one vma that contains + * the page. */ void remove_from_swap(struct page *page) { struct anon_vma *anon_vma; struct vm_area_struct *vma; + unsigned long mapping; - if (!PageAnon(page) || !PageSwapCache(page)) + if (!PageSwapCache(page)) return; - anon_vma = page_lock_anon_vma(page); - if (!anon_vma) + mapping = (unsigned long)page->mapping; + + if (!mapping || (mapping & PAGE_MAPPING_ANON) == 0) return; + /* + * We hold the mmap_sem lock. So no need to call page_lock_anon_vma. + */ + anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON); + spin_lock(&anon_vma->lock); + list_for_each_entry(vma, &anon_vma->head, anon_vma_node) remove_vma_swap(vma, page); spin_unlock(&anon_vma->lock); - delete_from_swap_cache(page); } EXPORT_SYMBOL(remove_from_swap); @@ -529,9 +537,6 @@ void page_add_new_anon_rmap(struct page *page, */ void page_add_file_rmap(struct page *page) { - BUG_ON(PageAnon(page)); - BUG_ON(!pfn_valid(page_to_pfn(page))); - if (atomic_inc_and_test(&page->_mapcount)) __inc_page_state(nr_mapped); } |