summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--mm/rmap.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/mm/rmap.c b/mm/rmap.c
index 6657000b18d4..ab16c96efdfb 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1054,8 +1054,14 @@ static void __page_set_anon_rmap(struct page *page,
 	if (!exclusive)
 		anon_vma = anon_vma->root;
 
+	/*
+	 * page_idle does a lockless/optimistic rmap scan on page->mapping.
+	 * Make sure the compiler doesn't split the stores of anon_vma and
+	 * the PAGE_MAPPING_ANON type identifier, otherwise the rmap code
+	 * could mistake the mapping for a struct address_space and crash.
+	 */
 	anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
-	page->mapping = (struct address_space *) anon_vma;
+	WRITE_ONCE(page->mapping, (struct address_space *) anon_vma);
 	page->index = linear_page_index(vma, address);
 }