summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2026-02-02 07:06:31 +0100
committerEric Biggers <ebiggers@kernel.org>2026-02-02 12:38:13 -0800
commitb244c89a70b306e5a91852e00fd8cdd289714505 (patch)
treedaaa408ed802cad328b2fdd97bbfc94070c3802e
parent23eec9fd64b2889286f31340371d67babfe54155 (diff)
readahead: push invalidate_lock out of page_cache_ra_unbounded
Require the invalidate_lock to be held over calls to page_cache_ra_unbounded instead of acquiring it in this function. This prepares for calling page_cache_ra_unbounded from ->readahead for fsverity read-ahead. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20260202060754.270269-3-hch@lst.de Signed-off-by: Eric Biggers <ebiggers@kernel.org>
-rw-r--r--fs/f2fs/file.c2
-rw-r--r--fs/verity/pagecache.c7
-rw-r--r--mm/readahead.c15
3 files changed, 16 insertions, 8 deletions
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index da029fed4e5a..c9b9fcdd0cae 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -4418,7 +4418,9 @@ static int redirty_blocks(struct inode *inode, pgoff_t page_idx, int len)
pgoff_t redirty_idx = page_idx;
int page_len = 0, ret = 0;
+ filemap_invalidate_lock_shared(mapping);
page_cache_ra_unbounded(&ractl, len, 0);
+ filemap_invalidate_unlock_shared(mapping);
do {
folio = read_cache_folio(mapping, page_idx, NULL, NULL);
diff --git a/fs/verity/pagecache.c b/fs/verity/pagecache.c
index 1a88decace53..8e0d6fde802f 100644
--- a/fs/verity/pagecache.c
+++ b/fs/verity/pagecache.c
@@ -26,10 +26,13 @@ struct page *generic_read_merkle_tree_page(struct inode *inode, pgoff_t index,
(!IS_ERR(folio) && !folio_test_uptodate(folio))) {
DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
- if (!IS_ERR(folio))
+ if (!IS_ERR(folio)) {
folio_put(folio);
- else if (num_ra_pages > 1)
+ } else if (num_ra_pages > 1) {
+ filemap_invalidate_lock_shared(inode->i_mapping);
page_cache_ra_unbounded(&ractl, num_ra_pages, 0);
+ filemap_invalidate_unlock_shared(inode->i_mapping);
+ }
folio = read_mapping_folio(inode->i_mapping, index, NULL);
}
if (IS_ERR(folio))
diff --git a/mm/readahead.c b/mm/readahead.c
index b415c9969176..f43d03558e62 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -204,8 +204,9 @@ static struct folio *ractl_alloc_folio(struct readahead_control *ractl,
* not the function you want to call. Use page_cache_async_readahead()
* or page_cache_sync_readahead() instead.
*
- * Context: File is referenced by caller. Mutexes may be held by caller.
- * May sleep, but will not reenter filesystem to reclaim memory.
+ * Context: File is referenced by caller, and ractl->mapping->invalidate_lock
+ * must be held by the caller at least in shared mode. Mutexes may be held by
+ * caller. May sleep, but will not reenter filesystem to reclaim memory.
*/
void page_cache_ra_unbounded(struct readahead_control *ractl,
unsigned long nr_to_read, unsigned long lookahead_size)
@@ -228,9 +229,10 @@ void page_cache_ra_unbounded(struct readahead_control *ractl,
*/
unsigned int nofs = memalloc_nofs_save();
+ lockdep_assert_held(&mapping->invalidate_lock);
+
trace_page_cache_ra_unbounded(mapping->host, index, nr_to_read,
lookahead_size);
- filemap_invalidate_lock_shared(mapping);
index = mapping_align_index(mapping, index);
/*
@@ -300,7 +302,6 @@ void page_cache_ra_unbounded(struct readahead_control *ractl,
* will then handle the error.
*/
read_pages(ractl);
- filemap_invalidate_unlock_shared(mapping);
memalloc_nofs_restore(nofs);
}
EXPORT_SYMBOL_GPL(page_cache_ra_unbounded);
@@ -314,9 +315,9 @@ EXPORT_SYMBOL_GPL(page_cache_ra_unbounded);
static void do_page_cache_ra(struct readahead_control *ractl,
unsigned long nr_to_read, unsigned long lookahead_size)
{
- struct inode *inode = ractl->mapping->host;
+ struct address_space *mapping = ractl->mapping;
unsigned long index = readahead_index(ractl);
- loff_t isize = i_size_read(inode);
+ loff_t isize = i_size_read(mapping->host);
pgoff_t end_index; /* The last page we want to read */
if (isize == 0)
@@ -329,7 +330,9 @@ static void do_page_cache_ra(struct readahead_control *ractl,
if (nr_to_read > end_index - index)
nr_to_read = end_index - index + 1;
+ filemap_invalidate_lock_shared(mapping);
page_cache_ra_unbounded(ractl, nr_to_read, lookahead_size);
+ filemap_invalidate_unlock_shared(mapping);
}
/*