diff --git a/mm/filemap.c b/mm/filemap.c index ebd75684cb0a..9044a4087ce5 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -4048,17 +4048,22 @@ EXPORT_SYMBOL(generic_file_readonly_mmap_prepare); static struct folio *do_read_cache_folio(struct address_space *mapping, pgoff_t index, filler_t filler, struct file *file, gfp_t gfp) { + struct inode *inode = mapping->host; struct folio *folio; int err; if (!filler) filler = mapping->a_ops->read_folio; + inode_lock(inode); repeat: folio = filemap_get_folio(mapping, index); if (IS_ERR(folio)) { folio = filemap_alloc_folio(gfp, mapping_min_folio_order(mapping), NULL); - if (!folio) + if (!folio) { + inode_unlock(inode); return ERR_PTR(-ENOMEM); + } + index = mapping_align_index(mapping, index); err = filemap_add_folio(mapping, folio, index, gfp); if (unlikely(err)) { @@ -4066,13 +4071,16 @@ static struct folio *do_read_cache_folio(struct address_space *mapping, if (err == -EEXIST) goto repeat; /* Presumably ENOMEM for xarray node */ + inode_unlock(inode); return ERR_PTR(err); } goto filler; } - if (folio_test_uptodate(folio)) + if (folio_test_uptodate(folio)) { + inode_unlock(inode); goto out; + } if (!folio_trylock(folio)) { folio_put_wait_locked(folio, TASK_UNINTERRUPTIBLE); @@ -4089,11 +4097,13 @@ static struct folio *do_read_cache_folio(struct address_space *mapping, /* Someone else locked and filled the page in a very small window */ if (folio_test_uptodate(folio)) { folio_unlock(folio); + inode_unlock(inode); goto out; } filler: err = filemap_read_folio(file, filler, folio); + inode_unlock(inode); if (err) { folio_put(folio); if (err == AOP_TRUNCATED_PAGE)