[Devel] [PATCH rh7 4/4] mm: page_idle: look up page anon_vma carefully when checking references

Vladimir Davydov vdavydov at virtuozzo.com
Tue Dec 8 05:03:48 PST 2015


Since we don't hold mmap_sem when checking references, we can't just
read anon_vma from page->mapping and call down_read on its rwsem,
becuase the page can be unmapped in the meantime and the anon_vma can be
freed so that we will end up messing with already freed and perhaps
reallocated anon_vma. This can result in memory corruptions and dead
locks.

To fix this issue, this patch makes use of the rmap_walk infrastructure
pulled by previous patches, which allows to use page_lock_anon_vma_read
for locking page anon_vma. This function handles the race described
above carefully, so make page_idle_clear_pte_refs use it, as it is done
upstream.

https://jira.sw.ru/browse/PSBM-42015

Fixes: 577afeb24634 ("ms/mm: introduce idle page tracking")
Signed-off-by: Vladimir Davydov <vdavydov at virtuozzo.com>
---
 mm/page_idle.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/mm/page_idle.c b/mm/page_idle.c
index c09a5a28264f..6470ba0e56ee 100644
--- a/mm/page_idle.c
+++ b/mm/page_idle.c
@@ -88,15 +88,28 @@ static int page_idle_clear_pte_refs_one(struct page *page,
 
 static void page_idle_clear_pte_refs(struct page *page)
 {
+	/*
+	 * Since rwc.arg is unused, rwc is effectively immutable, so we
+	 * can make it static const to save some cycles and stack.
+	 */
+	static const struct rmap_walk_control rwc = {
+		.rmap_one = page_idle_clear_pte_refs_one,
+		.anon_lock = page_lock_anon_vma_read,
+	};
+	bool need_lock;
+
 	if (!page_mapped(page) ||
 	    !page_rmapping(page))
 		return;
 
-	if (!trylock_page(page))
+	need_lock = !PageAnon(page) || PageKsm(page);
+	if (need_lock && !trylock_page(page))
 		return;
 
-	rmap_walk(page, page_idle_clear_pte_refs_one, NULL);
-	unlock_page(page);
+	rmap_walk(page, (struct rmap_walk_control *)&rwc);
+
+	if (need_lock)
+		unlock_page(page);
 }
 
 static ssize_t page_idle_bitmap_read(struct file *file, struct kobject *kobj,
-- 
2.1.4



More information about the Devel mailing list