Re: [syzbot] [btrfs?] general protection fault in create_empty_buffers (5)

From: Edward Adam Davis
Date: Fri Jan 09 2026 - 05:52:41 EST


#syz test

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)