From: "Matthew Wilcox (Oracle)" willy@infradead.org
stable inclusion from stable-v5.10.110 commit 381636f33fe4af41fec076c5d9346a7369bcb40e bugzilla: https://gitee.com/openeuler/kernel/issues/I574AL
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 3ed4bb77156da0bc732847c8c9df92454c1fbeea upstream.
When splitting a value entry, we may need to add the new nodes to the LRU list and remove the parent node from the LRU list. The WARN_ON checks in shadow_lru_isolate() catch this oversight. This bug was latent until we stopped splitting folios in shrink_page_list() with commit 820c4e2e6f51 ("mm/vmscan: Free non-shmem folios without splitting them"). That allows the creation of large shadow entries, and subsequently when trying to page in a small page, we will split the large shadow entry in __filemap_add_folio().
Fixes: 8fc75643c5e1 ("XArray: add xas_split") Reported-by: Hugh Dickins hughd@google.com Signed-off-by: Matthew Wilcox (Oracle) willy@infradead.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Yu Liao liaoyu15@huawei.com Reviewed-by: Wei Li liwei391@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com --- lib/xarray.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/lib/xarray.c b/lib/xarray.c index 90e72b9f4b94..75da19a7a933 100644 --- a/lib/xarray.c +++ b/lib/xarray.c @@ -1080,6 +1080,7 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order) xa_mk_node(child)); if (xa_is_value(curr)) values--; + xas_update(xas, child); } else { unsigned int canon = offset - xas->xa_sibs;
@@ -1094,6 +1095,7 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order) } while (offset-- > xas->xa_offset);
node->nr_values += values; + xas_update(xas, node); } EXPORT_SYMBOL_GPL(xas_split); #endif