]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - mm/huge_memory.c
PCI: PM: Skip devices in D0 for suspend-to-idle
[mirror_ubuntu-bionic-kernel.git] / mm / huge_memory.c
index 0e7ded98d114d184877d2fc9bd0f02c3187f2ed5..fe29b2bde36ee20f730b85feca087a2941703d40 100644 (file)
@@ -555,7 +555,8 @@ static int __do_huge_pmd_anonymous_page(struct vm_fault *vmf, struct page *page,
 
        VM_BUG_ON_PAGE(!PageCompound(page), page);
 
-       if (mem_cgroup_try_charge(page, vma->vm_mm, gfp, &memcg, true)) {
+       if (mem_cgroup_try_charge(page, vma->vm_mm, gfp | __GFP_NORETRY, &memcg,
+                                 true)) {
                put_page(page);
                count_vm_event(THP_FAULT_FALLBACK);
                return VM_FAULT_FALLBACK;
@@ -1316,7 +1317,7 @@ alloc:
        }
 
        if (unlikely(mem_cgroup_try_charge(new_page, vma->vm_mm,
-                                       huge_gfp, &memcg, true))) {
+                               huge_gfp | __GFP_NORETRY, &memcg, true))) {
                put_page(new_page);
                split_huge_pmd(vma, vmf->pmd, vmf->address);
                if (page)
@@ -1781,7 +1782,7 @@ static pmd_t move_soft_dirty_pmd(pmd_t pmd)
 
 bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
                  unsigned long new_addr, unsigned long old_end,
-                 pmd_t *old_pmd, pmd_t *new_pmd, bool *need_flush)
+                 pmd_t *old_pmd, pmd_t *new_pmd)
 {
        spinlock_t *old_ptl, *new_ptl;
        pmd_t pmd;
@@ -1812,7 +1813,7 @@ bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
                if (new_ptl != old_ptl)
                        spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING);
                pmd = pmdp_huge_get_and_clear(mm, old_addr, old_pmd);
-               if (pmd_present(pmd) && pmd_dirty(pmd))
+               if (pmd_present(pmd))
                        force_flush = true;
                VM_BUG_ON(!pmd_none(*new_pmd));
 
@@ -1823,12 +1824,10 @@ bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
                }
                pmd = move_soft_dirty_pmd(pmd);
                set_pmd_at(mm, new_addr, new_pmd, pmd);
-               if (new_ptl != old_ptl)
-                       spin_unlock(new_ptl);
                if (force_flush)
                        flush_tlb_range(vma, old_addr, old_addr + PMD_SIZE);
-               else
-                       *need_flush = true;
+               if (new_ptl != old_ptl)
+                       spin_unlock(new_ptl);
                spin_unlock(old_ptl);
                return true;
        }
@@ -2097,6 +2096,8 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
                if (vma_is_dax(vma))
                        return;
                page = pmd_page(_pmd);
+               if (!PageDirty(page) && pmd_dirty(_pmd))
+                       set_page_dirty(page);
                if (!PageReferenced(page) && pmd_young(_pmd))
                        SetPageReferenced(page);
                page_remove_rmap(page, true);
@@ -2439,7 +2440,7 @@ static void __split_huge_page(struct page *page, struct list_head *list,
                __split_huge_page_tail(head, i, lruvec, list);
                /* Some pages can be beyond i_size: drop them from page cache */
                if (head[i].index >= end) {
-                       __ClearPageDirty(head + i);
+                       ClearPageDirty(head + i);
                        __delete_from_page_cache(head + i, NULL);
                        if (IS_ENABLED(CONFIG_SHMEM) && PageSwapBacked(head))
                                shmem_uncharge(head->mapping->host, 1);
@@ -2791,11 +2792,13 @@ static unsigned long deferred_split_scan(struct shrinker *shrink,
 
        list_for_each_safe(pos, next, &list) {
                page = list_entry((void *)pos, struct page, mapping);
-               lock_page(page);
+               if (!trylock_page(page))
+                       goto next;
                /* split_huge_page() removes page from list on success */
                if (!split_huge_page(page))
                        split++;
                unlock_page(page);
+next:
                put_page(page);
        }