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.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 08f6c1993832..3644ff918434 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -32,6 +32,7 @@
32#include <linux/userfaultfd_k.h> 32#include <linux/userfaultfd_k.h>
33#include <linux/page_idle.h> 33#include <linux/page_idle.h>
34#include <linux/shmem_fs.h> 34#include <linux/shmem_fs.h>
35#include <linux/oom.h>
35 36
36#include <asm/tlb.h> 37#include <asm/tlb.h>
37#include <asm/pgalloc.h> 38#include <asm/pgalloc.h>
@@ -550,6 +551,7 @@ static int __do_huge_pmd_anonymous_page(struct vm_fault *vmf, struct page *page,
550 struct mem_cgroup *memcg; 551 struct mem_cgroup *memcg;
551 pgtable_t pgtable; 552 pgtable_t pgtable;
552 unsigned long haddr = vmf->address & HPAGE_PMD_MASK; 553 unsigned long haddr = vmf->address & HPAGE_PMD_MASK;
554 int ret = 0;
553 555
554 VM_BUG_ON_PAGE(!PageCompound(page), page); 556 VM_BUG_ON_PAGE(!PageCompound(page), page);
555 557
@@ -561,9 +563,8 @@ static int __do_huge_pmd_anonymous_page(struct vm_fault *vmf, struct page *page,
561 563
562 pgtable = pte_alloc_one(vma->vm_mm, haddr); 564 pgtable = pte_alloc_one(vma->vm_mm, haddr);
563 if (unlikely(!pgtable)) { 565 if (unlikely(!pgtable)) {
564 mem_cgroup_cancel_charge(page, memcg, true); 566 ret = VM_FAULT_OOM;
565 put_page(page); 567 goto release;
566 return VM_FAULT_OOM;
567 } 568 }
568 569
569 clear_huge_page(page, haddr, HPAGE_PMD_NR); 570 clear_huge_page(page, haddr, HPAGE_PMD_NR);
@@ -576,13 +577,14 @@ static int __do_huge_pmd_anonymous_page(struct vm_fault *vmf, struct page *page,
576 577
577 vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd); 578 vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd);
578 if (unlikely(!pmd_none(*vmf->pmd))) { 579 if (unlikely(!pmd_none(*vmf->pmd))) {
579 spin_unlock(vmf->ptl); 580 goto unlock_release;
580 mem_cgroup_cancel_charge(page, memcg, true);
581 put_page(page);
582 pte_free(vma->vm_mm, pgtable);
583 } else { 581 } else {
584 pmd_t entry; 582 pmd_t entry;
585 583
584 ret = check_stable_address_space(vma->vm_mm);
585 if (ret)
586 goto unlock_release;
587
586 /* Deliver the page fault to userland */ 588 /* Deliver the page fault to userland */
587 if (userfaultfd_missing(vma)) { 589 if (userfaultfd_missing(vma)) {
588 int ret; 590 int ret;
@@ -610,6 +612,15 @@ static int __do_huge_pmd_anonymous_page(struct vm_fault *vmf, struct page *page,
610 } 612 }
611 613
612 return 0; 614 return 0;
615unlock_release:
616 spin_unlock(vmf->ptl);
617release:
618 if (pgtable)
619 pte_free(vma->vm_mm, pgtable);
620 mem_cgroup_cancel_charge(page, memcg, true);
621 put_page(page);
622 return ret;
623
613} 624}
614 625
615/* 626/*
@@ -688,7 +699,10 @@ int do_huge_pmd_anonymous_page(struct vm_fault *vmf)
688 ret = 0; 699 ret = 0;
689 set = false; 700 set = false;
690 if (pmd_none(*vmf->pmd)) { 701 if (pmd_none(*vmf->pmd)) {
691 if (userfaultfd_missing(vma)) { 702 ret = check_stable_address_space(vma->vm_mm);
703 if (ret) {
704 spin_unlock(vmf->ptl);
705 } else if (userfaultfd_missing(vma)) {
692 spin_unlock(vmf->ptl); 706 spin_unlock(vmf->ptl);
693 ret = handle_userfault(vmf, VM_UFFD_MISSING); 707 ret = handle_userfault(vmf, VM_UFFD_MISSING);
694 VM_BUG_ON(ret & VM_FAULT_FALLBACK); 708 VM_BUG_ON(ret & VM_FAULT_FALLBACK);