diff mbox series

btrfs-progs: improve error handling in btrfs_split_item()

Message ID 2d164b3ee567836cb7d2111b293b53bdec6b9b65.1731194259.git.wqu@suse.com (mailing list archive)
State New
Headers show
Series btrfs-progs: improve error handling in btrfs_split_item() | expand

Commit Message

Qu Wenruo Nov. 9, 2024, 11:17 p.m. UTC
This involves the following error cases:

- Unable to find the original item
  Return -EAGAIN and release the path (which is not done in the original
  code)

- Error from split_leaf()
  Remove the BUG_ON() and handle the error.
  The most common error is ENOSPC.

- Error from kmalloc()
  Just handle the error and return -ENOMEM.

Issue: #312
Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 kernel-shared/ctree.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c
index cfcad0fec61f..c540cf7b1854 100644
--- a/kernel-shared/ctree.c
+++ b/kernel-shared/ctree.c
@@ -2450,7 +2450,7 @@  int btrfs_split_item(struct btrfs_trans_handle *trans,
 	u32 nritems;
 	u32 orig_offset;
 	struct btrfs_disk_key disk_key;
-	char *buf;
+	char *buf = NULL;
 
 	leaf = path->nodes[0];
 	btrfs_item_key_to_cpu(leaf, &orig_key, path->slots[0]);
@@ -2469,11 +2469,13 @@  int btrfs_split_item(struct btrfs_trans_handle *trans,
 	/* if our item isn't there or got smaller, return now */
 	if (ret != 0 || item_size != btrfs_item_size(path->nodes[0],
 							path->slots[0])) {
-		return -EAGAIN;
+		ret = -EAGAIN;
+		goto error;
 	}
 
 	ret = split_leaf(trans, root, &orig_key, path, 0, 0);
-	BUG_ON(ret);
+	if (ret < 0)
+		goto error;
 
 	BUG_ON(btrfs_leaf_free_space(leaf) < sizeof(struct btrfs_item));
 	leaf = path->nodes[0];
@@ -2484,7 +2486,10 @@  split:
 
 
 	buf = kmalloc(item_size, GFP_NOFS);
-	BUG_ON(!buf);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto error;
+	}
 	read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf,
 			    path->slots[0]), item_size);
 	slot = path->slots[0] + 1;
@@ -2530,6 +2535,10 @@  split:
 	}
 	kfree(buf);
 	return ret;
+error:
+	kfree(buf);
+	btrfs_release_path(path);
+	return ret;
 }
 
 void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end)