Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e8788c0c authored by Christoph Lameter's avatar Christoph Lameter Committed by Linus Torvalds
Browse files

[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: default avatarChristoph Lameter <clameter@sgi.com>
Acked-by: default avatarHugh Dickins <hugh@veritas.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 6af6aab3
Loading
Loading
Loading
Loading
+13 −5
Original line number Diff line number Diff line
@@ -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);