aboutsummaryrefslogtreecommitdiffstats
path: root/mm/huge_memory.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/huge_memory.c')
-rw-r--r--mm/huge_memory.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 9e894edc7811..6001ee6347a9 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1819,9 +1819,19 @@ int split_huge_page(struct page *page)
1819 1819
1820 BUG_ON(is_huge_zero_pfn(page_to_pfn(page))); 1820 BUG_ON(is_huge_zero_pfn(page_to_pfn(page)));
1821 BUG_ON(!PageAnon(page)); 1821 BUG_ON(!PageAnon(page));
1822 anon_vma = page_lock_anon_vma_read(page); 1822
1823 /*
1824 * The caller does not necessarily hold an mmap_sem that would prevent
1825 * the anon_vma disappearing so we first we take a reference to it
1826 * and then lock the anon_vma for write. This is similar to
1827 * page_lock_anon_vma_read except the write lock is taken to serialise
1828 * against parallel split or collapse operations.
1829 */
1830 anon_vma = page_get_anon_vma(page);
1823 if (!anon_vma) 1831 if (!anon_vma)
1824 goto out; 1832 goto out;
1833 anon_vma_lock_write(anon_vma);
1834
1825 ret = 0; 1835 ret = 0;
1826 if (!PageCompound(page)) 1836 if (!PageCompound(page))
1827 goto out_unlock; 1837 goto out_unlock;
@@ -1832,7 +1842,8 @@ int split_huge_page(struct page *page)
1832 1842
1833 BUG_ON(PageCompound(page)); 1843 BUG_ON(PageCompound(page));
1834out_unlock: 1844out_unlock:
1835 page_unlock_anon_vma_read(anon_vma); 1845 anon_vma_unlock(anon_vma);
1846 put_anon_vma(anon_vma);
1836out: 1847out:
1837 return ret; 1848 return ret;
1838} 1849}