[PATCH 1/3] btrfs: unlock inode and extent on pages alloc failure in uring read

Yang Xiuwei <[email protected]>
Newsgroups org.kernel.vger.linux-btrfs
Message-ID <[email protected]>
btrfs_uring_read_extent() is only reached after btrfs_encoded_read()
has taken the inode shared lock and the extent lock.  If allocating
the pages array fails it returned -ENOMEM directly and left both
locks held.

Fixes: 34310c442e17 ("btrfs: add io_uring command for encoded reads (ENCODED_READ ioctl)")
Signed-off-by: Yang Xiuwei <[email protected]>
---
 fs/btrfs/ioctl.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 68b33f365fda..c953e4409d5b 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -4626,8 +4626,10 @@ static int btrfs_uring_read_extent(struct kiocb *iocb, struct iov_iter *iter,
 
 	nr_pages = DIV_ROUND_UP(disk_io_size, PAGE_SIZE);
 	pages = kzalloc_objs(struct page *, nr_pages, GFP_NOFS);
-	if (!pages)
-		return -ENOMEM;
+	if (!pages) {
+		ret = -ENOMEM;
+		goto out_fail;
+	}
 	ret = btrfs_alloc_page_array(nr_pages, pages, GFP_NOFS);
 	if (ret) {
 		ret = -ENOMEM;
@@ -4677,9 +4679,11 @@ static int btrfs_uring_read_extent(struct kiocb *iocb, struct iov_iter *iter,
 	btrfs_unlock_extent(io_tree, start, lockend, &cached_state);
 	btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
 	kfree(priv);
-	for (int i = 0; i < nr_pages; i++) {
-		if (pages[i])
-			__free_page(pages[i]);
+	if (pages) {
+		for (int i = 0; i < nr_pages; i++) {
+			if (pages[i])
+				__free_page(pages[i]);
+		}
 	}
 	kfree(pages);
 	return ret;
-- 
2.25.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.