Index: linux-2.6/include/linux/rmap.h =================================================================== --- linux-2.6.orig/include/linux/rmap.h 2006-11-30 15:28:50.000000000 -0800 +++ linux-2.6/include/linux/rmap.h 2006-11-30 15:29:26.000000000 -0800 @@ -26,6 +26,7 @@ struct anon_vma { spinlock_t lock; /* Serialize access to vma list */ struct list_head head; /* List of private "related" vmas */ + int migration_count; /* # processes migrating pages */ }; #ifdef CONFIG_MMU Index: linux-2.6/mm/migrate.c =================================================================== --- linux-2.6.orig/mm/migrate.c 2006-11-30 15:29:30.000000000 -0800 +++ linux-2.6/mm/migrate.c 2006-11-30 15:37:49.000000000 -0800 @@ -229,11 +229,15 @@ */ anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON); spin_lock(&anon_vma->lock); + anon_vma->migration_count--; list_for_each_entry(vma, &anon_vma->head, anon_vma_node) remove_migration_pte(vma, old, new); + empty = list_empty(&anon_vma->head); spin_unlock(&anon_vma->lock); + if (empty) + anon_vma_free(anon_vma); } /* Index: linux-2.6/mm/rmap.c =================================================================== --- linux-2.6.orig/mm/rmap.c 2006-11-30 15:30:43.000000000 -0800 +++ linux-2.6/mm/rmap.c 2006-11-30 15:33:20.000000000 -0800 @@ -151,7 +151,7 @@ list_del(&vma->anon_vma_node); /* We must garbage collect the anon_vma if it's empty */ - empty = list_empty(&anon_vma->head); + empty = list_empty(&anon_vma->head) && !anon_vma->migration_count; spin_unlock(&anon_vma->lock); if (empty) @@ -787,6 +787,9 @@ if (!anon_vma) return ret; + if (migration) + anon_vma->migration_count++; + list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { ret = try_to_unmap_one(page, vma, migration); if (ret == SWAP_FAIL || !page_mapped(page))