diff options
author | Pekka Enberg <penberg@kernel.org> | 2011-03-11 11:10:45 -0500 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2011-03-11 11:10:45 -0500 |
commit | c9149556756d56c68451a4a8735c37e7062fd3d7 (patch) | |
tree | a2dae56b22adaa9a23c8f92f30c3b3ad3b610850 /mm/huge_memory.c | |
parent | d71f606f687ef9d0cdddfd3619ca7cb9a0b3fb63 (diff) | |
parent | 5bfe53a77e8a3ffce4a10003c75f464a138e272d (diff) |
Merge branch 'slab/rcu' into slab/next
Conflicts:
mm/slub.c
Diffstat (limited to 'mm/huge_memory.c')
-rw-r--r-- | mm/huge_memory.c | 72 |
1 files changed, 42 insertions, 30 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index e187454d82f6..dbe99a5f2073 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -650,10 +650,10 @@ static inline gfp_t alloc_hugepage_gfpmask(int defrag) | |||
650 | 650 | ||
651 | static inline struct page *alloc_hugepage_vma(int defrag, | 651 | static inline struct page *alloc_hugepage_vma(int defrag, |
652 | struct vm_area_struct *vma, | 652 | struct vm_area_struct *vma, |
653 | unsigned long haddr) | 653 | unsigned long haddr, int nd) |
654 | { | 654 | { |
655 | return alloc_pages_vma(alloc_hugepage_gfpmask(defrag), | 655 | return alloc_pages_vma(alloc_hugepage_gfpmask(defrag), |
656 | HPAGE_PMD_ORDER, vma, haddr); | 656 | HPAGE_PMD_ORDER, vma, haddr, nd); |
657 | } | 657 | } |
658 | 658 | ||
659 | #ifndef CONFIG_NUMA | 659 | #ifndef CONFIG_NUMA |
@@ -678,7 +678,7 @@ int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
678 | if (unlikely(khugepaged_enter(vma))) | 678 | if (unlikely(khugepaged_enter(vma))) |
679 | return VM_FAULT_OOM; | 679 | return VM_FAULT_OOM; |
680 | page = alloc_hugepage_vma(transparent_hugepage_defrag(vma), | 680 | page = alloc_hugepage_vma(transparent_hugepage_defrag(vma), |
681 | vma, haddr); | 681 | vma, haddr, numa_node_id()); |
682 | if (unlikely(!page)) | 682 | if (unlikely(!page)) |
683 | goto out; | 683 | goto out; |
684 | if (unlikely(mem_cgroup_newpage_charge(page, mm, GFP_KERNEL))) { | 684 | if (unlikely(mem_cgroup_newpage_charge(page, mm, GFP_KERNEL))) { |
@@ -799,8 +799,8 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm, | |||
799 | } | 799 | } |
800 | 800 | ||
801 | for (i = 0; i < HPAGE_PMD_NR; i++) { | 801 | for (i = 0; i < HPAGE_PMD_NR; i++) { |
802 | pages[i] = alloc_page_vma(GFP_HIGHUSER_MOVABLE, | 802 | pages[i] = alloc_page_vma_node(GFP_HIGHUSER_MOVABLE, |
803 | vma, address); | 803 | vma, address, page_to_nid(page)); |
804 | if (unlikely(!pages[i] || | 804 | if (unlikely(!pages[i] || |
805 | mem_cgroup_newpage_charge(pages[i], mm, | 805 | mem_cgroup_newpage_charge(pages[i], mm, |
806 | GFP_KERNEL))) { | 806 | GFP_KERNEL))) { |
@@ -902,7 +902,7 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
902 | if (transparent_hugepage_enabled(vma) && | 902 | if (transparent_hugepage_enabled(vma) && |
903 | !transparent_hugepage_debug_cow()) | 903 | !transparent_hugepage_debug_cow()) |
904 | new_page = alloc_hugepage_vma(transparent_hugepage_defrag(vma), | 904 | new_page = alloc_hugepage_vma(transparent_hugepage_defrag(vma), |
905 | vma, haddr); | 905 | vma, haddr, numa_node_id()); |
906 | else | 906 | else |
907 | new_page = NULL; | 907 | new_page = NULL; |
908 | 908 | ||
@@ -1162,7 +1162,12 @@ static void __split_huge_page_refcount(struct page *page) | |||
1162 | /* after clearing PageTail the gup refcount can be released */ | 1162 | /* after clearing PageTail the gup refcount can be released */ |
1163 | smp_mb(); | 1163 | smp_mb(); |
1164 | 1164 | ||
1165 | page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP; | 1165 | /* |
1166 | * retain hwpoison flag of the poisoned tail page: | ||
1167 | * fix for the unsuitable process killed on Guest Machine(KVM) | ||
1168 | * by the memory-failure. | ||
1169 | */ | ||
1170 | page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP | __PG_HWPOISON; | ||
1166 | page_tail->flags |= (page->flags & | 1171 | page_tail->flags |= (page->flags & |
1167 | ((1L << PG_referenced) | | 1172 | ((1L << PG_referenced) | |
1168 | (1L << PG_swapbacked) | | 1173 | (1L << PG_swapbacked) | |
@@ -1740,7 +1745,8 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page, | |||
1740 | static void collapse_huge_page(struct mm_struct *mm, | 1745 | static void collapse_huge_page(struct mm_struct *mm, |
1741 | unsigned long address, | 1746 | unsigned long address, |
1742 | struct page **hpage, | 1747 | struct page **hpage, |
1743 | struct vm_area_struct *vma) | 1748 | struct vm_area_struct *vma, |
1749 | int node) | ||
1744 | { | 1750 | { |
1745 | pgd_t *pgd; | 1751 | pgd_t *pgd; |
1746 | pud_t *pud; | 1752 | pud_t *pud; |
@@ -1768,7 +1774,8 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
1768 | * mmap_sem in read mode is good idea also to allow greater | 1774 | * mmap_sem in read mode is good idea also to allow greater |
1769 | * scalability. | 1775 | * scalability. |
1770 | */ | 1776 | */ |
1771 | new_page = alloc_hugepage_vma(khugepaged_defrag(), vma, address); | 1777 | new_page = alloc_hugepage_vma(khugepaged_defrag(), vma, address, |
1778 | node); | ||
1772 | if (unlikely(!new_page)) { | 1779 | if (unlikely(!new_page)) { |
1773 | up_read(&mm->mmap_sem); | 1780 | up_read(&mm->mmap_sem); |
1774 | *hpage = ERR_PTR(-ENOMEM); | 1781 | *hpage = ERR_PTR(-ENOMEM); |
@@ -1806,6 +1813,8 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
1806 | /* VM_PFNMAP vmas may have vm_ops null but vm_file set */ | 1813 | /* VM_PFNMAP vmas may have vm_ops null but vm_file set */ |
1807 | if (!vma->anon_vma || vma->vm_ops || vma->vm_file) | 1814 | if (!vma->anon_vma || vma->vm_ops || vma->vm_file) |
1808 | goto out; | 1815 | goto out; |
1816 | if (is_vma_temporary_stack(vma)) | ||
1817 | goto out; | ||
1809 | VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma)); | 1818 | VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma)); |
1810 | 1819 | ||
1811 | pgd = pgd_offset(mm, address); | 1820 | pgd = pgd_offset(mm, address); |
@@ -1847,7 +1856,6 @@ static void collapse_huge_page(struct mm_struct *mm, | |||
1847 | set_pmd_at(mm, address, pmd, _pmd); | 1856 | set_pmd_at(mm, address, pmd, _pmd); |
1848 | spin_unlock(&mm->page_table_lock); | 1857 | spin_unlock(&mm->page_table_lock); |
1849 | anon_vma_unlock(vma->anon_vma); | 1858 | anon_vma_unlock(vma->anon_vma); |
1850 | mem_cgroup_uncharge_page(new_page); | ||
1851 | goto out; | 1859 | goto out; |
1852 | } | 1860 | } |
1853 | 1861 | ||
@@ -1893,6 +1901,7 @@ out_up_write: | |||
1893 | return; | 1901 | return; |
1894 | 1902 | ||
1895 | out: | 1903 | out: |
1904 | mem_cgroup_uncharge_page(new_page); | ||
1896 | #ifdef CONFIG_NUMA | 1905 | #ifdef CONFIG_NUMA |
1897 | put_page(new_page); | 1906 | put_page(new_page); |
1898 | #endif | 1907 | #endif |
@@ -1912,6 +1921,7 @@ static int khugepaged_scan_pmd(struct mm_struct *mm, | |||
1912 | struct page *page; | 1921 | struct page *page; |
1913 | unsigned long _address; | 1922 | unsigned long _address; |
1914 | spinlock_t *ptl; | 1923 | spinlock_t *ptl; |
1924 | int node = -1; | ||
1915 | 1925 | ||
1916 | VM_BUG_ON(address & ~HPAGE_PMD_MASK); | 1926 | VM_BUG_ON(address & ~HPAGE_PMD_MASK); |
1917 | 1927 | ||
@@ -1942,6 +1952,13 @@ static int khugepaged_scan_pmd(struct mm_struct *mm, | |||
1942 | page = vm_normal_page(vma, _address, pteval); | 1952 | page = vm_normal_page(vma, _address, pteval); |
1943 | if (unlikely(!page)) | 1953 | if (unlikely(!page)) |
1944 | goto out_unmap; | 1954 | goto out_unmap; |
1955 | /* | ||
1956 | * Chose the node of the first page. This could | ||
1957 | * be more sophisticated and look at more pages, | ||
1958 | * but isn't for now. | ||
1959 | */ | ||
1960 | if (node == -1) | ||
1961 | node = page_to_nid(page); | ||
1945 | VM_BUG_ON(PageCompound(page)); | 1962 | VM_BUG_ON(PageCompound(page)); |
1946 | if (!PageLRU(page) || PageLocked(page) || !PageAnon(page)) | 1963 | if (!PageLRU(page) || PageLocked(page) || !PageAnon(page)) |
1947 | goto out_unmap; | 1964 | goto out_unmap; |
@@ -1958,7 +1975,7 @@ out_unmap: | |||
1958 | pte_unmap_unlock(pte, ptl); | 1975 | pte_unmap_unlock(pte, ptl); |
1959 | if (ret) | 1976 | if (ret) |
1960 | /* collapse_huge_page will return with the mmap_sem released */ | 1977 | /* collapse_huge_page will return with the mmap_sem released */ |
1961 | collapse_huge_page(mm, address, hpage, vma); | 1978 | collapse_huge_page(mm, address, hpage, vma, node); |
1962 | out: | 1979 | out: |
1963 | return ret; | 1980 | return ret; |
1964 | } | 1981 | } |
@@ -2027,32 +2044,27 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, | |||
2027 | if ((!(vma->vm_flags & VM_HUGEPAGE) && | 2044 | if ((!(vma->vm_flags & VM_HUGEPAGE) && |
2028 | !khugepaged_always()) || | 2045 | !khugepaged_always()) || |
2029 | (vma->vm_flags & VM_NOHUGEPAGE)) { | 2046 | (vma->vm_flags & VM_NOHUGEPAGE)) { |
2047 | skip: | ||
2030 | progress++; | 2048 | progress++; |
2031 | continue; | 2049 | continue; |
2032 | } | 2050 | } |
2033 | |||
2034 | /* VM_PFNMAP vmas may have vm_ops null but vm_file set */ | 2051 | /* VM_PFNMAP vmas may have vm_ops null but vm_file set */ |
2035 | if (!vma->anon_vma || vma->vm_ops || vma->vm_file) { | 2052 | if (!vma->anon_vma || vma->vm_ops || vma->vm_file) |
2036 | khugepaged_scan.address = vma->vm_end; | 2053 | goto skip; |
2037 | progress++; | 2054 | if (is_vma_temporary_stack(vma)) |
2038 | continue; | 2055 | goto skip; |
2039 | } | 2056 | |
2040 | VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma)); | 2057 | VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma)); |
2041 | 2058 | ||
2042 | hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK; | 2059 | hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK; |
2043 | hend = vma->vm_end & HPAGE_PMD_MASK; | 2060 | hend = vma->vm_end & HPAGE_PMD_MASK; |
2044 | if (hstart >= hend) { | 2061 | if (hstart >= hend) |
2045 | progress++; | 2062 | goto skip; |
2046 | continue; | 2063 | if (khugepaged_scan.address > hend) |
2047 | } | 2064 | goto skip; |
2048 | if (khugepaged_scan.address < hstart) | 2065 | if (khugepaged_scan.address < hstart) |
2049 | khugepaged_scan.address = hstart; | 2066 | khugepaged_scan.address = hstart; |
2050 | if (khugepaged_scan.address > hend) { | 2067 | VM_BUG_ON(khugepaged_scan.address & ~HPAGE_PMD_MASK); |
2051 | khugepaged_scan.address = hend + HPAGE_PMD_SIZE; | ||
2052 | progress++; | ||
2053 | continue; | ||
2054 | } | ||
2055 | BUG_ON(khugepaged_scan.address & ~HPAGE_PMD_MASK); | ||
2056 | 2068 | ||
2057 | while (khugepaged_scan.address < hend) { | 2069 | while (khugepaged_scan.address < hend) { |
2058 | int ret; | 2070 | int ret; |
@@ -2081,7 +2093,7 @@ breakouterloop: | |||
2081 | breakouterloop_mmap_sem: | 2093 | breakouterloop_mmap_sem: |
2082 | 2094 | ||
2083 | spin_lock(&khugepaged_mm_lock); | 2095 | spin_lock(&khugepaged_mm_lock); |
2084 | BUG_ON(khugepaged_scan.mm_slot != mm_slot); | 2096 | VM_BUG_ON(khugepaged_scan.mm_slot != mm_slot); |
2085 | /* | 2097 | /* |
2086 | * Release the current mm_slot if this mm is about to die, or | 2098 | * Release the current mm_slot if this mm is about to die, or |
2087 | * if we scanned all vmas of this mm. | 2099 | * if we scanned all vmas of this mm. |
@@ -2236,9 +2248,9 @@ static int khugepaged(void *none) | |||
2236 | 2248 | ||
2237 | for (;;) { | 2249 | for (;;) { |
2238 | mutex_unlock(&khugepaged_mutex); | 2250 | mutex_unlock(&khugepaged_mutex); |
2239 | BUG_ON(khugepaged_thread != current); | 2251 | VM_BUG_ON(khugepaged_thread != current); |
2240 | khugepaged_loop(); | 2252 | khugepaged_loop(); |
2241 | BUG_ON(khugepaged_thread != current); | 2253 | VM_BUG_ON(khugepaged_thread != current); |
2242 | 2254 | ||
2243 | mutex_lock(&khugepaged_mutex); | 2255 | mutex_lock(&khugepaged_mutex); |
2244 | if (!khugepaged_enabled()) | 2256 | if (!khugepaged_enabled()) |