[PATCH] ext4: Handle error pointers being returned from __filemap_get_folio

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit "mm: return an ERR_PTR from __filemap_get_folio" changed from
returning NULL to returning an ERR_PTR().  This cannot be fixed in either
the ext4 tree or the mm tree, so this patch should be applied as part
of merging the two trees.

Reported-by: Eric Biggers <ebiggers@xxxxxxxxxx>
Reported-by: syzbot+d1ae544e6e9dc29bcba5@xxxxxxxxxxxxxxxxxxxxxxxxx
Debugged-by: William Kucharski <william.kucharski@xxxxxxxxxx>
Signed-off-by: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx>
---
 fs/ext4/inline.c | 17 +++++++++--------
 fs/ext4/inode.c  | 12 ++++++------
 fs/ext4/verity.c |  6 ++++--
 3 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index b9fb1177fff6..ab220d4bf73f 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -566,8 +566,9 @@ static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
 	 * started */
 	folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,
 			mapping_gfp_mask(mapping));
-	if (!folio) {
-		ret = -ENOMEM;
+	if (IS_ERR(folio)) {
+		ret = PTR_ERR(folio);
+		folio = NULL;
 		goto out;
 	}
 
@@ -693,8 +694,8 @@ int ext4_try_to_write_inline_data(struct address_space *mapping,
 
 	folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,
 					mapping_gfp_mask(mapping));
-	if (!folio) {
-		ret = -ENOMEM;
+	if (IS_ERR(folio)) {
+		ret = PTR_ERR(folio);
 		goto out;
 	}
 
@@ -854,8 +855,8 @@ static int ext4_da_convert_inline_data_to_extent(struct address_space *mapping,
 
 	folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN,
 					mapping_gfp_mask(mapping));
-	if (!folio)
-		return -ENOMEM;
+	if (IS_ERR(folio))
+		return PTR_ERR(folio);
 
 	down_read(&EXT4_I(inode)->xattr_sem);
 	if (!ext4_has_inline_data(inode)) {
@@ -947,8 +948,8 @@ int ext4_da_write_inline_data_begin(struct address_space *mapping,
 	 */
 	folio = __filemap_get_folio(mapping, 0, FGP_WRITEBEGIN | FGP_NOFS,
 					mapping_gfp_mask(mapping));
-	if (!folio) {
-		ret = -ENOMEM;
+	if (IS_ERR(folio)) {
+		ret = PTR_ERR(folio);
 		goto out_journal;
 	}
 
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 974747a6eb99..9052c90215eb 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -1177,8 +1177,8 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping,
 retry_grab:
 	folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN,
 					mapping_gfp_mask(mapping));
-	if (!folio)
-		return -ENOMEM;
+	if (IS_ERR(folio))
+		return PTE_ERR(folio);
 	/*
 	 * The same as page allocation, we prealloc buffer heads before
 	 * starting the handle.
@@ -2932,8 +2932,8 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
 retry:
 	folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN,
 			mapping_gfp_mask(mapping));
-	if (!folio)
-		return -ENOMEM;
+	if (IS_ERR(folio))
+		return PTR_ERR(folio);
 
 	/* In case writeback began while the folio was unlocked */
 	folio_wait_stable(folio);
@@ -3675,8 +3675,8 @@ static int __ext4_block_zero_page_range(handle_t *handle,
 	folio = __filemap_get_folio(mapping, from >> PAGE_SHIFT,
 				    FGP_LOCK | FGP_ACCESSED | FGP_CREAT,
 				    mapping_gfp_constraint(mapping, ~__GFP_FS));
-	if (!folio)
-		return -ENOMEM;
+	if (IS_ERR(folio))
+		return PTR_ERR(folio);
 
 	blocksize = inode->i_sb->s_blocksize;
 
diff --git a/fs/ext4/verity.c b/fs/ext4/verity.c
index 3b01247066dd..ce4b720f19a1 100644
--- a/fs/ext4/verity.c
+++ b/fs/ext4/verity.c
@@ -366,14 +366,16 @@ static struct page *ext4_read_merkle_tree_page(struct inode *inode,
 	index += ext4_verity_metadata_pos(inode) >> PAGE_SHIFT;
 
 	folio = __filemap_get_folio(inode->i_mapping, index, FGP_ACCESSED, 0);
-	if (!folio || !folio_test_uptodate(folio)) {
+	if (IS_ERR(folio) || !folio_test_uptodate(folio)) {
 		DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
 
-		if (folio)
+		if (!IS_ERR(folio))
 			folio_put(folio);
 		else if (num_ra_pages > 1)
 			page_cache_ra_unbounded(&ractl, num_ra_pages, 0);
 		folio = read_mapping_folio(inode->i_mapping, index, NULL);
+		if (IS_ERR(folio))
+			return &folio->page;
 	}
 	return folio_file_page(folio, index);
 }
-- 
2.39.2




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [NTFS 3]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [NTFS 3]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux