X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=mm%2Frmap.c;h=d8ce5ff6145492469a3b81640946fca58d7e8002;hb=7a2fe8c49f0f346601a18c69ba0f75227c0c5993;hp=f4b91d7aa5cfb4f3b7d79ef4258bb08985d92b04;hpb=a3351e525e4768c29aa5d22ef59b5b38e0361e53;p=linux-2.6 diff --git a/mm/rmap.c b/mm/rmap.c index f4b91d7aa5..d8ce5ff614 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -212,27 +212,36 @@ 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); #endif /*