On Tue, May 21, 2024 at 11:47 PM Marcin Wanat <private@xxxxxxxxxxxxxx> wrote: > > On 21.05.2024 03:00, Zhaoyang Huang wrote: > > On Tue, May 21, 2024 at 8:58 AM Zhaoyang Huang <huangzhaoyang@xxxxxxxxx> wrote: > >> > >> On Tue, May 21, 2024 at 3:42 AM Marcin Wanat <private@xxxxxxxxxxxxxx> wrote: > >>> > >>> On 15.04.2024 03:50, Zhaoyang Huang wrote: > >>> I have around 50 hosts handling high I/O (each with 20Gbps+ uplinks > >>> and multiple NVMe drives), running RockyLinux 8/9. The stock RHEL > >>> kernel 8/9 is NOT affected, and the long-term kernel 5.15.X is NOT affected. > >>> However, with long-term kernels 6.1.XX and 6.6.XX, > >>> (tested at least 10 different versions), this lockup always appears > >>> after 2-30 days, similar to the report in the original thread. > >>> The more load (for example, copying a lot of local files while > >>> serving 20Gbps traffic), the higher the chance that the bug will appear. > >>> > >>> I haven't been able to reproduce this during synthetic tests, > >>> but it always occurs in production on 6.1.X and 6.6.X within 2-30 days. > >>> If anyone can provide a patch, I can test it on multiple machines > >>> over the next few days. > >> Could you please try this one which could be applied on 6.6 directly. Thank you! > > URL: https://lore.kernel.org/linux-mm/20240412064353.133497-1-zhaoyang.huang@xxxxxxxxxx/ > > > > Unfortunately, I am unable to cleanly apply this patch against the > latest 6.6.31 Please try below one which works on my v6.6 based android. Thank you for your test in advance :D mm/huge_memory.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 064fbd90822b..5899906c326a 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2498,7 +2498,7 @@ static void __split_huge_page(struct page *page, struct list_head *list, { struct folio *folio = page_folio(page); struct page *head = &folio->page; - struct lruvec *lruvec; + struct lruvec *lruvec = folio_lruvec(folio); struct address_space *swap_cache = NULL; unsigned long offset = 0; unsigned int nr = thp_nr_pages(head); @@ -2513,9 +2513,6 @@ static void __split_huge_page(struct page *page, struct list_head *list, xa_lock(&swap_cache->i_pages); } - /* lock lru list/PageCompound, ref frozen by page_ref_freeze */ - lruvec = folio_lruvec_lock(folio); - ClearPageHasHWPoisoned(head); for (i = nr - 1; i >= 1; i--) { @@ -2541,9 +2538,6 @@ static void __split_huge_page(struct page *page, struct list_head *list, } ClearPageCompound(head); - unlock_page_lruvec(lruvec); - /* Caller disabled irqs, so they are still disabled here */ - split_page_owner(head, nr); /* See comment in __split_huge_page_tail() */ @@ -2560,7 +2554,6 @@ static void __split_huge_page(struct page *page, struct list_head *list, page_ref_add(head, 2); xa_unlock(&head->mapping->i_pages); } - local_irq_enable(); if (nr_dropped) shmem_uncharge(head->mapping->host, nr_dropped); @@ -2631,6 +2624,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) int extra_pins, ret; pgoff_t end; bool is_hzp; + struct lruvec *lruvec; VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio); VM_BUG_ON_FOLIO(!folio_test_large(folio), folio); @@ -2714,6 +2708,14 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) /* block interrupt reentry in xa_lock and spinlock */ local_irq_disable(); + + /* + * take lruvec's lock before freeze the folio to prevent the folio + * remains in the page cache with refcnt == 0, which could lead to + * find_get_entry enters livelock by iterating the xarray. + */ + lruvec = folio_lruvec_lock(folio); + if (mapping) { /* * Check if the folio is present in page cache. @@ -2748,12 +2750,16 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) } __split_huge_page(page, list, end); + unlock_page_lruvec(lruvec); + local_irq_enable(); ret = 0; } else { spin_unlock(&ds_queue->split_queue_lock); fail: if (mapping) xas_unlock(&xas); + + unlock_page_lruvec(lruvec); local_irq_enable(); remap_page(folio, folio_nr_pages(folio)); ret = -EAGAIN; -- 2.25.1