aboutsummaryrefslogtreecommitdiffstats
path: root/mm/rmap.c
diff options
context:
space:
mode:
authorAndrea Arcangeli <aarcange@redhat.com>2010-08-09 20:19:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-09 23:44:59 -0400
commit44ab57a06ded284db6ccdefc6b76eddb1c34d7ed (patch)
treee757c1af6be102b90d8a989d6fcfacad93ff6b69 /mm/rmap.c
parent21d0d443cdc1658a8c1484fdcece4803f0f96d0e (diff)
rmap: 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. Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Signed-off-by: Rik van Riel <riel@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/rmap.c')
-rw-r--r--mm/rmap.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/mm/rmap.c b/mm/rmap.c
index 2f855babfd06..4d152a6d3a89 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -811,6 +811,7 @@ static void __page_check_anon_rmap(struct page *page,
811 * are initially only visible via the pagetables, and the pte is locked 811 * are initially only visible via the pagetables, and the pte is locked
812 * over the call to page_add_new_anon_rmap. 812 * over the call to page_add_new_anon_rmap.
813 */ 813 */
814 BUG_ON(page_anon_vma(page)->root != vma->anon_vma->root);
814 BUG_ON(page->index != linear_page_index(vma, address)); 815 BUG_ON(page->index != linear_page_index(vma, address));
815#endif 816#endif
816} 817}
@@ -1408,6 +1409,7 @@ int try_to_munlock(struct page *page)
1408 */ 1409 */
1409void drop_anon_vma(struct anon_vma *anon_vma) 1410void drop_anon_vma(struct anon_vma *anon_vma)
1410{ 1411{
1412 BUG_ON(atomic_read(&anon_vma->external_refcount) <= 0);
1411 if (atomic_dec_and_lock(&anon_vma->external_refcount, &anon_vma->root->lock)) { 1413 if (atomic_dec_and_lock(&anon_vma->external_refcount, &anon_vma->root->lock)) {
1412 struct anon_vma *root = anon_vma->root; 1414 struct anon_vma *root = anon_vma->root;
1413 int empty = list_empty(&anon_vma->head); 1415 int empty = list_empty(&anon_vma->head);
@@ -1419,6 +1421,7 @@ void drop_anon_vma(struct anon_vma *anon_vma)
1419 * the refcount on the root and check if we need to free it. 1421 * the refcount on the root and check if we need to free it.
1420 */ 1422 */
1421 if (empty && anon_vma != root) { 1423 if (empty && anon_vma != root) {
1424 BUG_ON(atomic_read(&root->external_refcount) <= 0);
1422 last_root_user = atomic_dec_and_test(&root->external_refcount); 1425 last_root_user = atomic_dec_and_test(&root->external_refcount);
1423 root_empty = list_empty(&root->head); 1426 root_empty = list_empty(&root->head);
1424 } 1427 }