mm/migrate: fix race between lock page and clear PG_Isolated

Bugzilla: https://bugzilla.redhat.com/2120352

commit 356ea3865687926e5da7579d1f3351d3f0a322a1
Author: andrew.yang <andrew.yang@mediatek.com>
Date:   Tue Mar 22 14:46:08 2022 -0700

    mm/migrate: fix race between lock page and clear PG_Isolated

    When memory is tight, system may start to compact memory for large
    continuous memory demands.  If one process tries to lock a memory page
    that is being locked and isolated for compaction, it may wait a long time
    or even forever.  This is because compaction will perform non-atomic
    PG_Isolated clear while holding page lock, this may overwrite PG_waiters
    set by the process that can't obtain the page lock and add itself to the
    waiting queue to wait for the lock to be unlocked.

      CPU1                            CPU2
      lock_page(page); (successful)
                                      lock_page(); (failed)
      __ClearPageIsolated(page);      SetPageWaiters(page) (may be overwritten)
      unlock_page(page);

    The solution is to not perform non-atomic operation on page flags while
    holding page lock.

    Link: https://lkml.kernel.org/r/20220315030515.20263-1-andrew.yang@mediatek.com
    Signed-off-by: andrew.yang <andrew.yang@mediatek.com>
    Cc: Matthias Brugger <matthias.bgg@gmail.com>
    Cc: Matthew Wilcox <willy@infradead.org>
    Cc: "Vlastimil Babka" <vbabka@suse.cz>
    Cc: David Howells <dhowells@redhat.com>
    Cc: "William Kucharski" <william.kucharski@oracle.com>
    Cc: David Hildenbrand <david@redhat.com>
    Cc: Yang Shi <shy828301@gmail.com>
    Cc: Marc Zyngier <maz@kernel.org>
    Cc: Nicholas Tang <nicholas.tang@mediatek.com>
    Cc: Kuan-Ying Lee <Kuan-Ying.Lee@mediatek.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Signed-off-by: Chris von Recklinghausen <crecklin@redhat.com>
This commit is contained in:
Chris von Recklinghausen 2022-10-12 07:09:17 -04:00
parent 40a64b9480
commit 4ba2af444f
2 changed files with 7 additions and 7 deletions

View File

@ -1000,7 +1000,7 @@ PAGE_TYPE_OPS(Guard, guard)
extern bool is_free_buddy_page(struct page *page);
__PAGEFLAG(Isolated, isolated, PF_ANY);
PAGEFLAG(Isolated, isolated, PF_ANY);
#ifdef CONFIG_MMU
#define __PG_MLOCKED (1UL << PG_mlocked)

View File

@ -104,7 +104,7 @@ int isolate_movable_page(struct page *page, isolate_mode_t mode)
/* Driver shouldn't use PG_isolated bit of page->flags */
WARN_ON_ONCE(PageIsolated(page));
__SetPageIsolated(page);
SetPageIsolated(page);
unlock_page(page);
return 0;
@ -123,7 +123,7 @@ static void putback_movable_page(struct page *page)
mapping = page_mapping(page);
mapping->a_ops->putback_page(page);
__ClearPageIsolated(page);
ClearPageIsolated(page);
}
/*
@ -156,7 +156,7 @@ void putback_movable_pages(struct list_head *l)
if (PageMovable(page))
putback_movable_page(page);
else
__ClearPageIsolated(page);
ClearPageIsolated(page);
unlock_page(page);
put_page(page);
} else {
@ -871,7 +871,7 @@ static int move_to_new_page(struct page *newpage, struct page *page,
VM_BUG_ON_PAGE(!PageIsolated(page), page);
if (!PageMovable(page)) {
rc = MIGRATEPAGE_SUCCESS;
__ClearPageIsolated(page);
ClearPageIsolated(page);
goto out;
}
@ -893,7 +893,7 @@ static int move_to_new_page(struct page *newpage, struct page *page,
* We clear PG_movable under page_lock so any compactor
* cannot try to migrate this page.
*/
__ClearPageIsolated(page);
ClearPageIsolated(page);
}
/*
@ -1088,7 +1088,7 @@ static int unmap_and_move(new_page_t get_new_page,
if (unlikely(__PageMovable(page))) {
lock_page(page);
if (!PageMovable(page))
__ClearPageIsolated(page);
ClearPageIsolated(page);
unlock_page(page);
}
goto out;