diff options
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r-- | mm/hugetlb.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index ac5f044bf514..ea0826ff2663 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -277,12 +277,15 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, | |||
277 | unsigned long addr; | 277 | unsigned long addr; |
278 | 278 | ||
279 | for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) { | 279 | for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) { |
280 | src_pte = huge_pte_offset(src, addr); | ||
281 | if (!src_pte) | ||
282 | continue; | ||
280 | dst_pte = huge_pte_alloc(dst, addr); | 283 | dst_pte = huge_pte_alloc(dst, addr); |
281 | if (!dst_pte) | 284 | if (!dst_pte) |
282 | goto nomem; | 285 | goto nomem; |
286 | spin_lock(&dst->page_table_lock); | ||
283 | spin_lock(&src->page_table_lock); | 287 | spin_lock(&src->page_table_lock); |
284 | src_pte = huge_pte_offset(src, addr); | 288 | if (!pte_none(*src_pte)) { |
285 | if (src_pte && !pte_none(*src_pte)) { | ||
286 | entry = *src_pte; | 289 | entry = *src_pte; |
287 | ptepage = pte_page(entry); | 290 | ptepage = pte_page(entry); |
288 | get_page(ptepage); | 291 | get_page(ptepage); |
@@ -290,6 +293,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, | |||
290 | set_huge_pte_at(dst, addr, dst_pte, entry); | 293 | set_huge_pte_at(dst, addr, dst_pte, entry); |
291 | } | 294 | } |
292 | spin_unlock(&src->page_table_lock); | 295 | spin_unlock(&src->page_table_lock); |
296 | spin_unlock(&dst->page_table_lock); | ||
293 | } | 297 | } |
294 | return 0; | 298 | return 0; |
295 | 299 | ||
@@ -354,7 +358,6 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) | |||
354 | 358 | ||
355 | hugetlb_prefault_arch_hook(mm); | 359 | hugetlb_prefault_arch_hook(mm); |
356 | 360 | ||
357 | spin_lock(&mm->page_table_lock); | ||
358 | for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) { | 361 | for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) { |
359 | unsigned long idx; | 362 | unsigned long idx; |
360 | pte_t *pte = huge_pte_alloc(mm, addr); | 363 | pte_t *pte = huge_pte_alloc(mm, addr); |
@@ -389,11 +392,12 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) | |||
389 | goto out; | 392 | goto out; |
390 | } | 393 | } |
391 | } | 394 | } |
395 | spin_lock(&mm->page_table_lock); | ||
392 | add_mm_counter(mm, file_rss, HPAGE_SIZE / PAGE_SIZE); | 396 | add_mm_counter(mm, file_rss, HPAGE_SIZE / PAGE_SIZE); |
393 | set_huge_pte_at(mm, addr, pte, make_huge_pte(vma, page)); | 397 | set_huge_pte_at(mm, addr, pte, make_huge_pte(vma, page)); |
398 | spin_unlock(&mm->page_table_lock); | ||
394 | } | 399 | } |
395 | out: | 400 | out: |
396 | spin_unlock(&mm->page_table_lock); | ||
397 | return ret; | 401 | return ret; |
398 | } | 402 | } |
399 | 403 | ||