aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/hugetlb.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ab79cd4dd23c..ce8cbb29860b 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2071,6 +2071,14 @@ follow_huge_pud(struct mm_struct *mm, unsigned long address,
2071 return NULL; 2071 return NULL;
2072} 2072}
2073 2073
2074static int huge_zeropage_ok(pte_t *ptep, int write, int shared)
2075{
2076 if (!ptep || write || shared)
2077 return 0;
2078 else
2079 return huge_pte_none(huge_ptep_get(ptep));
2080}
2081
2074int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, 2082int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
2075 struct page **pages, struct vm_area_struct **vmas, 2083 struct page **pages, struct vm_area_struct **vmas,
2076 unsigned long *position, int *length, int i, 2084 unsigned long *position, int *length, int i,
@@ -2080,6 +2088,8 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
2080 unsigned long vaddr = *position; 2088 unsigned long vaddr = *position;
2081 int remainder = *length; 2089 int remainder = *length;
2082 struct hstate *h = hstate_vma(vma); 2090 struct hstate *h = hstate_vma(vma);
2091 int zeropage_ok = 0;
2092 int shared = vma->vm_flags & VM_SHARED;
2083 2093
2084 spin_lock(&mm->page_table_lock); 2094 spin_lock(&mm->page_table_lock);
2085 while (vaddr < vma->vm_end && remainder) { 2095 while (vaddr < vma->vm_end && remainder) {
@@ -2092,8 +2102,11 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
2092 * first, for the page indexing below to work. 2102 * first, for the page indexing below to work.
2093 */ 2103 */
2094 pte = huge_pte_offset(mm, vaddr & huge_page_mask(h)); 2104 pte = huge_pte_offset(mm, vaddr & huge_page_mask(h));
2105 if (huge_zeropage_ok(pte, write, shared))
2106 zeropage_ok = 1;
2095 2107
2096 if (!pte || huge_pte_none(huge_ptep_get(pte)) || 2108 if (!pte ||
2109 (huge_pte_none(huge_ptep_get(pte)) && !zeropage_ok) ||
2097 (write && !pte_write(huge_ptep_get(pte)))) { 2110 (write && !pte_write(huge_ptep_get(pte)))) {
2098 int ret; 2111 int ret;
2099 2112
@@ -2113,8 +2126,11 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
2113 page = pte_page(huge_ptep_get(pte)); 2126 page = pte_page(huge_ptep_get(pte));
2114same_page: 2127same_page:
2115 if (pages) { 2128 if (pages) {
2116 get_page(page); 2129 if (zeropage_ok)
2117 pages[i] = page + pfn_offset; 2130 pages[i] = ZERO_PAGE(0);
2131 else
2132 pages[i] = page + pfn_offset;
2133 get_page(pages[i]);
2118 } 2134 }
2119 2135
2120 if (vmas) 2136 if (vmas)