Skip to contentSkip to conversation

further anon_vma fixes & optimizations

PATCH In review Rik van Riel 3 participants 11 messages Jun 21, 2010 – Jun 23, 2010

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover further anon_vma fixes & optimizations

A collection of anon_vma fixes and optimizations from Andrea's transparent hugepage tree.

Signature · 7 lines
All rights reversed.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#1 lore raw

PATCH 1/6 mmap: remove unnecessary lock from __vma_link

From: Andrea Arcangeli <[email protected]>
Subject: remove unnecessary lock from __vma_link

There's no anon-vma related mangling happening inside __vma_link anymore so no need of anon_vma locking there.

---

mm/mmap.c +0 -2
@@ -469,12 +469,10 @@ static void vma_link(struct mm_struct *m
 		spin_lock(&mapping->i_mmap_lock);
 		vma->vm_truncate_count = mapping->truncate_count;
 	}
-	vma_lock_anon_vma(vma);
 
 	__vma_link(mm, vma, prev, rb_link, rb_parent);
 	__vma_link_file(vma);
 
-	vma_unlock_anon_vma(vma);
 	if (mapping)
 		spin_unlock(&mapping->i_mmap_lock);
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#2 lore raw

PATCH 2/6 rmap: always add new vmas at the end

In reply to Rik van Riel

From: Andrea Arcangeli <[email protected]>
Subject: always add new vmas at the end

Make sure to always add new VMAs at the end of the list. This is important so rmap_walk does not miss a VMA that was created during the rmap_walk.

The old code got this right most of the time due to luck, but was buggy when anon_vma_prepare reused a mergeable anon_vma.

---

mm/rmap.c +1 -1
@@ -149,7 +149,7 @@ int anon_vma_prepare(struct vm_area_stru
 			avc->anon_vma = anon_vma;
 			avc->vma = vma;
 			list_add(&avc->same_vma, &vma->anon_vma_chain);
-			list_add(&avc->same_anon_vma, &anon_vma->head);
+			list_add_tail(&avc->same_anon_vma, &anon_vma->head);
 			allocated = NULL;
 			avc = NULL;
 		}

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#3 lore raw

Re: [PATCH -mm 2/6] rmap: always add new vmas at the end

Quoted 18 lines · On Mon, 21 Jun 2010 16:33:49 -0400 Rik van Riel <[email protected]> wrote:

From: Andrea Arcangeli <[email protected]>
Subject: always add new vmas at the end

Make sure to always add new VMAs at the end of the list. This is important so rmap_walk does not miss a VMA that was created during the rmap_walk.

The old code got this right most of the time due to luck, but was buggy when anon_vma_prepare reused a mergeable anon_vma.

---

mm/rmap.c int anon_vma_prepare(struct vm_area_stru · line 155

Quoted 8 lines
mm/rmap.c +1 -1
@@ -149,7 +149,7 @@ int anon_vma_prepare(struct vm_area_stru
 			avc->anon_vma = anon_vma;
 			avc->vma = vma;
 			list_add(&avc->same_vma, &vma->anon_vma_chain);
-			list_add(&avc->same_anon_vma, &anon_vma->head);
+			list_add_tail(&avc->same_anon_vma, &anon_vma->head);
 			allocated = NULL;
 			avc = NULL;
 		}

Should this go into 2.6.35?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#4 lore raw

Re: [PATCH -mm 2/6] rmap: always add new vmas at the end

Quoted 17 lines · Andrew Morton
Quoted 14 lines · On Mon, 21 Jun 2010 16:33:49 -0400 Rik van Riel <[email protected]> wrote:

From: Andrea Arcangeli <[email protected]>
Subject: always add new vmas at the end

Make sure to always add new VMAs at the end of the list. This is important so rmap_walk does not miss a VMA that was created during the rmap_walk.

The old code got this right most of the time due to luck, but was buggy when anon_vma_prepare reused a mergeable anon_vma.

---

Quoted 14 lines

mm/rmap.c int anon_vma_prepare(struct vm_area_stru · line 155

Quoted 12 lines
mm/rmap.c +1 -1
@@ -149,7 +149,7 @@ int anon_vma_prepare(struct vm_area_stru
 			avc->anon_vma = anon_vma;
 			avc->vma = vma;
 			list_add(&avc->same_vma, &vma->anon_vma_chain);
-			list_add(&avc->same_anon_vma, &anon_vma->head);
+			list_add_tail(&avc->same_anon_vma, &anon_vma->head);
 			allocated = NULL;
 			avc = NULL;
 		}

Should this go into 2.6.35?

Well migrate got broken anyway in 2.6.34, so until the whole root-anon-vma patchqueue is merged, it's not going to provide a safe migrate anyway and it can as well wait with the rest.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#5 lore raw

PATCH 3/6 ksm: fix ksm swapin time optimization

In reply to Rik van Riel

From: Andrea Arcangeli <[email protected]>
Subject: fix ksm swapin time optimization

The new anon-vma code, was suboptimal and it lead to erratic invocation of ksm_does_need_to_copy. That leads to host hangs or guest vnc lockup, or weird behavior. It's unclear why ksm_does_need_to_copy is unstable but the point is that when KSM is not in use, ksm_does_need_to_copy must never run or we bounce pages for no good reason. I suspect the same hangs will happen with KVM swaps. But this at least fixes the regression in the new-anon-vma code and it only let KSM bugs triggers when KSM is in use.

The code in do_swap_page likely doesn't cope well with a not-swapcache, especially the memcg code.

---

include/linux/ksm.h +1 -1
@@ -78,7 +78,7 @@ static inline struct page *ksm_might_nee
 	struct anon_vma *anon_vma = page_anon_vma(page);
 
 	if (!anon_vma ||
-	    (anon_vma == vma->anon_vma &&
+	    (anon_vma->root == vma->anon_vma->root &&
 	     page->index == linear_page_index(vma, address)))
 		return page;
 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#6 lore raw

Re: [PATCH -mm 3/6] ksm: fix ksm swapin time optimization

Quoted 7 lines · Rik van Riel

From: Andrea Arcangeli <[email protected]>
Subject: fix ksm swapin time optimization

The new anon-vma code, was suboptimal and it lead to erratic invocation of ksm_does_need_to_copy. That leads to host hangs or guest vnc lockup, or weird behavior. It's unclear why ksm_does_need_to_copy is unstable but the point is that when KSM is not in use, ksm_does_need_to_copy must never run or we bounce

BTW, I'm debugging why ksm_does_need_to_copy breaks things... probably I found something already, maybe not. I'll let you know as soon as I have a fix. In the meantime the one above is a fix needed to avoid calling ksm_does_need_to_copy erratically even when KSM is off (which also avoids the bug to trigger).

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw

PATCH 4/6 always use anon_vma root pointer

In reply to Rik van Riel

From: Andrea Arcangeli <[email protected]>
Subject: always use anon_vma root pointer

Always use anon_vma->root pointer instead of anon_vma_chain.prev.

Also optimize the map-paths, if a mapping is already established no need to overwrite it with root anon-vma list, we can keep the more finegrined anon-vma and skip the overwrite: see the PageAnon check in !exclusive case. This is also the optimization that hidden the ksm bug as this tends to make ksm_might_need_to_copy skip the copy, but only the proper fix to ksm_might_need_to_copy guarantees not triggering the ksm bug unless ksm is in use. this is an optimization only...

mm/rmap.c +5 -7
index 006f223..2d9504d 100644
@@ -776,15 +776,13 @@ static void __page_set_anon_rmap(struct page *page,
 	 * If the page isn't exclusively mapped into this vma,
 	 * we must use the _oldest_ possible anon_vma for the
 	 * page mapping!
-	 *
-	 * So take the last AVC chain entry in the vma, which is
-	 * the deepest ancestor, and use the anon_vma from that.
 	 */
 	if (!exclusive) {
-		struct anon_vma_chain *avc;
-		avc = list_entry(vma->anon_vma_chain.prev, struct anon_vma_chain, same_vma);
-		anon_vma = avc->anon_vma;
-	}
+		if (PageAnon(page))
+			return;
+		anon_vma = anon_vma->root;
+	} else
+		BUG_ON(PageAnon(page));
 
 	anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
 	page->mapping = (struct address_space *) anon_vma;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#8 lore raw

PATCH 5/6 resurrect page_address_in_vma anon_vma check

In reply to Rik van Riel

From: Andrea Arcangeli <[email protected]>
Subject: resurrect page_address_in_vma anon_vma check

With root anon-vma it's trivial to keep doing the usual check as in old-anon-vma code.

---

mm/rmap.c +4 -3
@@ -362,9 +362,10 @@ vma_address(struct page *page, struct vm
  */
 unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
 {
-	if (PageAnon(page))
-		;
-	else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
+	if (PageAnon(page)) {
+		if (vma->anon_vma->root != page_anon_vma(page)->root)
+			return -EFAULT;
+	} else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) {
 		if (!vma->vm_file ||
 		    vma->vm_file->f_mapping != page->mapping)
 			return -EFAULT;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#9 lore raw

PATCH 6/6 add anon_vma bug checks

In reply to Rik van Riel

From: Andrea Arcangeli <[email protected]>
Subject: add anon_vma bug checks

Verify the refcounting doesn't go wrong, and resurrect the check in __page_check_anon_rmap as in old anon-vma code.

---

mm/rmap.c +3 -0
@@ -815,6 +815,7 @@ static void __page_check_anon_rmap(struc
 	 * are initially only visible via the pagetables, and the pte is locked
 	 * over the call to page_add_new_anon_rmap.
 	 */
+	BUG_ON(page_anon_vma(page)->root != vma->anon_vma->root);
 	BUG_ON(page->index != linear_page_index(vma, address));
 #endif
 }
@@ -1405,6 +1406,7 @@ int try_to_munlock(struct page *page)
  */
 void drop_anon_vma(struct anon_vma *anon_vma)
 {
+	BUG_ON(atomic_read(&anon_vma->external_refcount) <= 0);
 	if (atomic_dec_and_lock(&anon_vma->external_refcount, &anon_vma->root->lock)) {
 		struct anon_vma *root = anon_vma->root;
 		int empty = list_empty(&anon_vma->head);
@@ -1416,6 +1418,7 @@ void drop_anon_vma(struct anon_vma *anon
 		 * the refcount on the root and check if we need to free it.
 		 */
 		if (empty && anon_vma != root) {
+			BUG_ON(atomic_read(&root->external_refcount) <= 0);
 			last_root_user = atomic_dec_and_test(&root->external_refcount);
 			root_empty = list_empty(&root->head);
 		}

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>