From: Chi Zhiling When reading small amounts of data from the page cache, only a single folio is typically returned from filemap_read_get_batch(). In this case, calling xas_advance() or xas_next() after adding the folio to the batch is unnecessary and only introduces extra branches. The same issue exists for large reads, where one additional xarray walk is always performed before termination. Quit the loop once we get the last folio in the range, so the final redundant xarray advancement can be avoided. The xas_next() does not update xa_index when xas->xa_node is set to XAS_RESTART, so the put and retry path would not update xa_index, hence the warning should therefore never trigger. During the 4k reads test, the overhead of this function dropped from 2.91% to 2.53%. Signed-off-by: Chi Zhiling --- mm/filemap.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index 4e636647100c..d54450e529bd 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2458,12 +2458,16 @@ static void filemap_get_read_batch(struct address_space *mapping, { XA_STATE(xas, &mapping->i_pages, index); struct folio *folio; + pgoff_t next; + + if (unlikely(index > max)) + return; rcu_read_lock(); for (folio = xas_load(&xas); folio; folio = xas_next(&xas)) { if (xas_retry(&xas, folio)) continue; - if (xas.xa_index > max || xa_is_value(folio)) + if (xa_is_value(folio) || WARN_ON(xas.xa_index > max)) break; if (xa_is_sibling(folio)) break; @@ -2479,7 +2483,11 @@ static void filemap_get_read_batch(struct address_space *mapping, break; if (folio_test_readahead(folio)) break; - xas_advance(&xas, folio_next_index(folio) - 1); + + next = folio_next_index(folio); + if (next > max) + break; + xas_advance(&xas, next - 1); continue; put_folio: folio_put(folio); -- 2.43.0