diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2019-02-08 09:40:29 +0530 |
---|---|---|
committer | Viresh Kumar <viresh.kumar@linaro.org> | 2019-02-08 09:40:29 +0530 |
commit | af816ddfbdf049dfce251513af4b5dc903c9764c (patch) | |
tree | 15fe94fb3dbb0db54d203c2a1229a0b7a9c3a608 /mm/memory.c | |
parent | 446fae2bb5395f3028d8e3aae1508737e5a72ea1 (diff) | |
parent | dab535052f67db0ff48b1b23e714b58650d1a787 (diff) |
Merge branch 'cpufreq/qcom-hw' into cpufreq/arm/linux-next
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/mm/memory.c b/mm/memory.c index a52663c0612d..e11ca9dd823f 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2994,6 +2994,28 @@ static vm_fault_t __do_fault(struct vm_fault *vmf) struct vm_area_struct *vma = vmf->vma; vm_fault_t ret; + /* + * Preallocate pte before we take page_lock because this might lead to + * deadlocks for memcg reclaim which waits for pages under writeback: + * lock_page(A) + * SetPageWriteback(A) + * unlock_page(A) + * lock_page(B) + * lock_page(B) + * pte_alloc_pne + * shrink_page_list + * wait_on_page_writeback(A) + * SetPageWriteback(B) + * unlock_page(B) + * # flush A, B to clear the writeback + */ + if (pmd_none(*vmf->pmd) && !vmf->prealloc_pte) { + vmf->prealloc_pte = pte_alloc_one(vmf->vma->vm_mm); + if (!vmf->prealloc_pte) + return VM_FAULT_OOM; + smp_wmb(); /* See comment in __pte_alloc() */ + } + ret = vma->vm_ops->fault(vmf); if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY | VM_FAULT_DONE_COW))) @@ -4077,8 +4099,8 @@ static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address, goto out; if (range) { - range->start = address & PAGE_MASK; - range->end = range->start + PAGE_SIZE; + mmu_notifier_range_init(range, mm, address & PAGE_MASK, + (address & PAGE_MASK) + PAGE_SIZE); mmu_notifier_invalidate_range_start(range); } ptep = pte_offset_map_lock(mm, pmd, address, ptlp); |