mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 06:34:12 +08:00
[PATCH] remove_from_swap: fix locking
remove_from_swap() currently attempts to use page_lock_anon_vma to obtain an anon_vma lock. That is not working since the page may have been remapped via swap ptes in order to move the page. However, do_migrate_pages() obtain the mmap_sem lock and therefore there is a guarantee that the anonymous vma will not vanish from under us. There is therefore no need to use page_lock_anon_vma. Signed-off-by: Christoph Lameter <clameter@sgi.com> Acked-by: Hugh Dickins <hugh@veritas.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
6af6aab34a
commit
e8788c0cce
18
mm/rmap.c
18
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);
|
||||
|
Loading…
Reference in New Issue
Block a user