diff options
author | Todd Poynor <toddpoynor@google.com> | 2013-03-13 17:35:08 -0700 |
---|---|---|
committer | Todd Poynor <toddpoynor@google.com> | 2013-03-13 17:35:08 -0700 |
commit | 1249d25539343d1a7fe361c8d40be7a5df5b0216 (patch) | |
tree | 770c9a33604bb00c62f44d780aefab27e4eb9379 /mm/memory.c | |
parent | 4aad13d07babf68c1d0d37ff1e5f797573c4fd2a (diff) | |
parent | 0b203ab4aacdb6e6dfb8c277aa290f0a02428e6f (diff) | |
download | kernel_samsung_tuna-1249d25539343d1a7fe361c8d40be7a5df5b0216.zip kernel_samsung_tuna-1249d25539343d1a7fe361c8d40be7a5df5b0216.tar.gz kernel_samsung_tuna-1249d25539343d1a7fe361c8d40be7a5df5b0216.tar.bz2 |
Merge branch 'android-3.0' into android-omap-3.0
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/mm/memory.c b/mm/memory.c index 7292acb..4da0f8a 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3470,6 +3470,7 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(is_vm_hugetlb_page(vma))) return hugetlb_fault(mm, vma, address, flags); +retry: pgd = pgd_offset(mm, address); pud = pud_alloc(mm, pgd, address); if (!pud) @@ -3483,13 +3484,24 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, pmd, flags); } else { pmd_t orig_pmd = *pmd; + int ret; + barrier(); if (pmd_trans_huge(orig_pmd)) { if (flags & FAULT_FLAG_WRITE && !pmd_write(orig_pmd) && - !pmd_trans_splitting(orig_pmd)) - return do_huge_pmd_wp_page(mm, vma, address, - pmd, orig_pmd); + !pmd_trans_splitting(orig_pmd)) { + ret = do_huge_pmd_wp_page(mm, vma, address, pmd, + orig_pmd); + /* + * If COW results in an oom, the huge pmd will + * have been split, so retry the fault on the + * pte for a smaller charge. + */ + if (unlikely(ret & VM_FAULT_OOM)) + goto retry; + return ret; + } return 0; } } |