XArray: Update the LRU list in xas_split()
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: 8fc75643c5
("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>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
3b9fabe8f6
commit
381636f33f
@@ -1080,6 +1080,7 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order)
|
|||||||
xa_mk_node(child));
|
xa_mk_node(child));
|
||||||
if (xa_is_value(curr))
|
if (xa_is_value(curr))
|
||||||
values--;
|
values--;
|
||||||
|
xas_update(xas, child);
|
||||||
} else {
|
} else {
|
||||||
unsigned int canon = offset - xas->xa_sibs;
|
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);
|
} while (offset-- > xas->xa_offset);
|
||||||
|
|
||||||
node->nr_values += values;
|
node->nr_values += values;
|
||||||
|
xas_update(xas, node);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(xas_split);
|
EXPORT_SYMBOL_GPL(xas_split);
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user