aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/ksm.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/mm/ksm.c b/mm/ksm.c
index b99e828172f6..4786b4150f62 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -783,6 +783,7 @@ static int unmerge_and_remove_all_rmap_items(void)
783 } 783 }
784 784
785 remove_trailing_rmap_items(mm_slot, &mm_slot->rmap_list); 785 remove_trailing_rmap_items(mm_slot, &mm_slot->rmap_list);
786 up_read(&mm->mmap_sem);
786 787
787 spin_lock(&ksm_mmlist_lock); 788 spin_lock(&ksm_mmlist_lock);
788 ksm_scan.mm_slot = list_entry(mm_slot->mm_list.next, 789 ksm_scan.mm_slot = list_entry(mm_slot->mm_list.next,
@@ -794,12 +795,9 @@ static int unmerge_and_remove_all_rmap_items(void)
794 795
795 free_mm_slot(mm_slot); 796 free_mm_slot(mm_slot);
796 clear_bit(MMF_VM_MERGEABLE, &mm->flags); 797 clear_bit(MMF_VM_MERGEABLE, &mm->flags);
797 up_read(&mm->mmap_sem);
798 mmdrop(mm); 798 mmdrop(mm);
799 } else { 799 } else
800 spin_unlock(&ksm_mmlist_lock); 800 spin_unlock(&ksm_mmlist_lock);
801 up_read(&mm->mmap_sem);
802 }
803 } 801 }
804 802
805 /* Clean up stable nodes, but don't worry if some are still busy */ 803 /* Clean up stable nodes, but don't worry if some are still busy */
@@ -1663,8 +1661,15 @@ next_mm:
1663 up_read(&mm->mmap_sem); 1661 up_read(&mm->mmap_sem);
1664 mmdrop(mm); 1662 mmdrop(mm);
1665 } else { 1663 } else {
1666 spin_unlock(&ksm_mmlist_lock);
1667 up_read(&mm->mmap_sem); 1664 up_read(&mm->mmap_sem);
1665 /*
1666 * up_read(&mm->mmap_sem) first because after
1667 * spin_unlock(&ksm_mmlist_lock) run, the "mm" may
1668 * already have been freed under us by __ksm_exit()
1669 * because the "mm_slot" is still hashed and
1670 * ksm_scan.mm_slot doesn't point to it anymore.
1671 */
1672 spin_unlock(&ksm_mmlist_lock);
1668 } 1673 }
1669 1674
1670 /* Repeat until we've completed scanning the whole list */ 1675 /* Repeat until we've completed scanning the whole list */