• Barry Song's avatar
    mm: use folio_add_new_anon_rmap() if folio_test_anon(folio)==false · 9ae2feac
    Barry Song authored
    For the !folio_test_anon(folio) case, we can now invoke
    folio_add_new_anon_rmap() with the rmap flags set to either EXCLUSIVE or
    non-EXCLUSIVE.  This action will suppress the VM_WARN_ON_FOLIO check
    within __folio_add_anon_rmap() while initiating the process of bringing up
    mTHP swapin.
    
     static __always_inline void __folio_add_anon_rmap(struct folio *folio,
                     struct page *page, int nr_pages, struct vm_area_struct *vma,
                     unsigned long address, rmap_t flags, enum rmap_level level)
     {
             ...
             if (unlikely(!folio_test_anon(folio))) {
                     VM_WARN_ON_FOLIO(folio_test_large(folio) &&
                                      level != RMAP_LEVEL_PMD, folio);
             }
             ...
     }
    
    It also improves the code's readability.  Currently, all new anonymous
    folios calling folio_add_anon_rmap_ptes() are order-0.  This ensures that
    new folios cannot be partially exclusive; they are either entirely
    exclusive or entirely shared.
    
    A useful comment from Hugh's fix:
    
    : Commit "mm: use folio_add_new_anon_rmap() if folio_test_anon(folio)==
    : false" has extended folio_add_new_anon_rmap() to use on non-exclusive
    : folios, already visible to others in swap cache and on LRU.
    : 
    : That renders its non-atomic __folio_set_swapbacked() unsafe: it risks
    : overwriting concurrent atomic operations on folio->flags, losing bits
    : added or restoring bits cleared.  Since it's only used in this risky way
    : when folio_test_locked and !folio_test_anon, many such races are excluded;
    : but, for example, isolations by folio_test_clear_lru() are vulnerable, and
    : setting or clearing active.
    : 
    : It could just use the atomic folio_set_swapbacked(); but this function
    : does try to avoid atomics where it can, so use a branch instead: just
    : avoid setting swapbacked when it is already set, that is good enough. 
    : (Swapbacked is normally stable once set: lazyfree can undo it, but only
    : later, when found anon in a page table.)
    : 
    : This fixes a lot of instability under compaction and swapping loads:
    : assorted "Bad page"s, VM_BUG_ON_FOLIO()s, apparently even page double
    : frees - though I've not worked out what races could lead to the latter.
    
    [akpm@linux-foundation.org: comment fixes, per David and akpm]
    [v-songbaohua@oppo.com: lock the folio to avoid race]
      Link: https://lkml.kernel.org/r/20240622032002.53033-1-21cnbao@gmail.com
    [hughd@google.com: folio_add_new_anon_rmap() careful __folio_set_swapbacked()]
      Link: https://lkml.kernel.org/r/f3599b1d-8323-0dc5-e9e0-fdb3cfc3dd5a@google.com
    Link: https://lkml.kernel.org/r/20240617231137.80726-3-21cnbao@gmail.comSigned-off-by: default avatarBarry Song <v-songbaohua@oppo.com>
    Signed-off-by: default avatarHugh Dickins <hughd@google.com>
    Suggested-by: default avatarDavid Hildenbrand <david@redhat.com>
    Tested-by: default avatarShuai Yuan <yuanshuai@oppo.com>
    Acked-by: default avatarDavid Hildenbrand <david@redhat.com>
    Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
    Cc: Chris Li <chrisl@kernel.org>
    Cc: "Huang, Ying" <ying.huang@intel.com>
    Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
    Cc: Michal Hocko <mhocko@suse.com>
    Cc: Ryan Roberts <ryan.roberts@arm.com>
    Cc: Suren Baghdasaryan <surenb@google.com>
    Cc: Yang Shi <shy828301@gmail.com>
    Cc: Yosry Ahmed <yosryahmed@google.com>
    Cc: Yu Zhao <yuzhao@google.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    9ae2feac
memory.c 182 KB