diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-26 12:19:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-26 12:19:36 -0700 |
commit | 7c902e273019ce60c1cb4d195e3cfd803969fd04 (patch) | |
tree | 72689ca58adee5750e7856f2e807d6b1a0c63c70 /mm/memory.c | |
parent | 4a21185cda0fbb860580eeeb4f1a70a9cda332a4 (diff) | |
parent | 19ef1f9dfeffe2bfbeaf624277a179b1c0eef201 (diff) | |
download | linux-7c902e273019ce60c1cb4d195e3cfd803969fd04.tar.bz2 |
Merge branch 'akpm' (patches from Andrew)
Merge misx fixes from Andrew Morton:
"31 patches.
Subsystems affected by this patch series: hotfixes, mm/pagealloc,
kexec, ocfs2, lib, mm/slab, mm/slab, mm/slub, mm/swap, mm/pagemap,
mm/vmalloc, mm/memcg, mm/gup, mm/thp, mm/vmscan, x86,
mm/memory-hotplug, MAINTAINERS"
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (31 commits)
MAINTAINERS: update info for sparse
mm/memory_hotplug.c: fix false softlockup during pfn range removal
mm: remove vmalloc_exec
arm64: use PAGE_KERNEL_ROX directly in alloc_insn_page
x86/hyperv: allocate the hypercall page with only read and execute bits
mm/memory: fix IO cost for anonymous page
mm/swap: fix for "mm: workingset: age nonresident information alongside anonymous pages"
mm: workingset: age nonresident information alongside anonymous pages
doc: THP CoW fault no longer allocate THP
docs: mm/gup: minor documentation update
mm/memcontrol.c: prevent missed memory.low load tears
mm/memcontrol.c: add missed css_put()
mm: memcontrol: handle div0 crash race condition in memory.low
mm/vmalloc.c: fix a warning while make xmldocs
media: omap3isp: remove cacheflush.h
make asm-generic/cacheflush.h more standalone
mm/debug_vm_pgtable: fix build failure with powerpc 8xx
mm/memory.c: properly pte_offset_map_lock/unlock in vm_insert_pages()
mm: fix swap cache node allocation mask
slub: cure list_slab_objects() from double fix
...
Diffstat (limited to 'mm/memory.c')
-rw-r--r-- | mm/memory.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/mm/memory.c b/mm/memory.c index dc7f3543b1fd..87ec87cdc1ff 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1498,7 +1498,7 @@ out: } #ifdef pte_index -static int insert_page_in_batch_locked(struct mm_struct *mm, pmd_t *pmd, +static int insert_page_in_batch_locked(struct mm_struct *mm, pte_t *pte, unsigned long addr, struct page *page, pgprot_t prot) { int err; @@ -1506,8 +1506,9 @@ static int insert_page_in_batch_locked(struct mm_struct *mm, pmd_t *pmd, if (!page_count(page)) return -EINVAL; err = validate_page_before_insert(page); - return err ? err : insert_page_into_pte_locked( - mm, pte_offset_map(pmd, addr), addr, page, prot); + if (err) + return err; + return insert_page_into_pte_locked(mm, pte, addr, page, prot); } /* insert_pages() amortizes the cost of spinlock operations @@ -1517,7 +1518,8 @@ static int insert_pages(struct vm_area_struct *vma, unsigned long addr, struct page **pages, unsigned long *num, pgprot_t prot) { pmd_t *pmd = NULL; - spinlock_t *pte_lock = NULL; + pte_t *start_pte, *pte; + spinlock_t *pte_lock; struct mm_struct *const mm = vma->vm_mm; unsigned long curr_page_idx = 0; unsigned long remaining_pages_total = *num; @@ -1536,18 +1538,17 @@ more: ret = -ENOMEM; if (pte_alloc(mm, pmd)) goto out; - pte_lock = pte_lockptr(mm, pmd); while (pages_to_write_in_pmd) { int pte_idx = 0; const int batch_size = min_t(int, pages_to_write_in_pmd, 8); - spin_lock(pte_lock); - for (; pte_idx < batch_size; ++pte_idx) { - int err = insert_page_in_batch_locked(mm, pmd, + start_pte = pte_offset_map_lock(mm, pmd, addr, &pte_lock); + for (pte = start_pte; pte_idx < batch_size; ++pte, ++pte_idx) { + int err = insert_page_in_batch_locked(mm, pte, addr, pages[curr_page_idx], prot); if (unlikely(err)) { - spin_unlock(pte_lock); + pte_unmap_unlock(start_pte, pte_lock); ret = err; remaining_pages_total -= pte_idx; goto out; @@ -1555,7 +1556,7 @@ more: addr += PAGE_SIZE; ++curr_page_idx; } - spin_unlock(pte_lock); + pte_unmap_unlock(start_pte, pte_lock); pages_to_write_in_pmd -= batch_size; remaining_pages_total -= batch_size; } @@ -3140,8 +3141,18 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) err = mem_cgroup_charge(page, vma->vm_mm, GFP_KERNEL); ClearPageSwapCache(page); - if (err) + if (err) { + ret = VM_FAULT_OOM; goto out_page; + } + + /* + * XXX: Move to lru_cache_add() when it + * supports new vs putback + */ + spin_lock_irq(&page_pgdat(page)->lru_lock); + lru_note_cost_page(page); + spin_unlock_irq(&page_pgdat(page)->lru_lock); lru_cache_add(page); swap_readpage(page, true); |