When a radix tree iteration drops the tree lock, another thread might
swoop in and free the node holding the current slot. The iteration
needs to do another tree lookup from the current index to continue.

[kirill.shute...@linux.intel.com: re-lookup for replacement]
Fixes: f3f0e1d2150b ("khugepaged: add support of collapse for tmpfs/shmem 
pages")
Signed-off-by: Johannes Weiner <han...@cmpxchg.org>
---
 mm/khugepaged.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 728d7790dc2d..bdfdab40a813 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -1401,6 +1401,9 @@ static void collapse_shmem(struct mm_struct *mm,
 
                spin_lock_irq(&mapping->tree_lock);
 
+               slot = radix_tree_lookup_slot(&mapping->page_tree, index);
+               VM_BUG_ON_PAGE(page != radix_tree_deref_slot_protected(slot,
+                                       &mapping->tree_lock), page);
                VM_BUG_ON_PAGE(page_mapped(page), page);
 
                /*
@@ -1424,6 +1427,7 @@ static void collapse_shmem(struct mm_struct *mm,
                radix_tree_replace_slot(slot,
                                new_page + (index % HPAGE_PMD_NR));
 
+               slot = radix_tree_iter_next(&iter);
                index++;
                continue;
 out_lru:
@@ -1535,6 +1539,7 @@ static void collapse_shmem(struct mm_struct *mm,
                        putback_lru_page(page);
                        unlock_page(page);
                        spin_lock_irq(&mapping->tree_lock);
+                       slot = radix_tree_iter_next(&iter);
                }
                VM_BUG_ON(nr_none);
                spin_unlock_irq(&mapping->tree_lock);
-- 
2.10.2

Reply via email to