btrfs-progs: improve error handling in btrfs_split_item()

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>
This commit is contained in:
Qu Wenruo 2024-11-10 09:43:28 +10:30
parent 66f08f9528
commit 2d164b3ee5
1 changed files with 13 additions and 4 deletions

View File

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