Split_huge_page() must start with PageLRU(head), and we are holding the lru_lock here. If the head was cleared lru bit unexpected, keep tracking it.
Signed-off-by: Alex Shi <[email protected]> Reviewed-by: Kirill A. Shutemov <[email protected]> Cc: Kirill A. Shutemov <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Johannes Weiner <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Mika Penttilä <[email protected]> Cc: [email protected] Cc: [email protected] --- mm/huge_memory.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 0132d363253e..6380c925e904 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2321,17 +2321,20 @@ static void lru_add_page_tail(struct page *head, struct page *page_tail, VM_BUG_ON_PAGE(PageLRU(page_tail), head); lockdep_assert_held(&lruvec_pgdat(lruvec)->lru_lock); - if (!list) - SetPageLRU(page_tail); - - if (likely(PageLRU(head))) - list_add_tail(&page_tail->lru, &head->lru); - else if (list) { + if (list) { /* page reclaim is reclaiming a huge page */ get_page(page_tail); list_add_tail(&page_tail->lru, list); - } else + } else { + /* + * Split start from PageLRU(head), and we are holding the + * lru_lock. Do a warning if the head's lru bit was cleared + * unexpected. + */ VM_WARN_ON(!PageLRU(head)); + SetPageLRU(page_tail); + list_add_tail(&page_tail->lru, &head->lru); + } } static void __split_huge_page_tail(struct page *head, int tail, -- 1.8.3.1

