Skip to content

Commit

Permalink
btrfs: handle ENOMEM in btrfs_alloc_tree_block
Browse files Browse the repository at this point in the history
This is one of the first places to give out when memory is tight. Handle
it properly rather than with a BUG_ON.

Also fix the comment about the return value, which is an ERR_PTR, not
NULL, on error.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
Reviewed-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <clm@fb.com>
  • Loading branch information
Omar Sandoval authored and Chris Mason committed Apr 26, 2015
1 parent 1b98450 commit 67b7859
Showing 1 changed file with 28 additions and 13 deletions.
41 changes: 28 additions & 13 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -7546,7 +7546,7 @@ static void unuse_block_rsv(struct btrfs_fs_info *fs_info,
* returns the key for the extent through ins, and a tree buffer for
* the first block of the extent through buf.
*
* returns the tree buffer or NULL.
* returns the tree buffer or an ERR_PTR on error.
*/
struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
Expand All @@ -7557,6 +7557,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
struct btrfs_key ins;
struct btrfs_block_rsv *block_rsv;
struct extent_buffer *buf;
struct btrfs_delayed_extent_op *extent_op;
u64 flags = 0;
int ret;
u32 blocksize = root->nodesize;
Expand All @@ -7577,13 +7578,14 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,

ret = btrfs_reserve_extent(root, blocksize, blocksize,
empty_size, hint, &ins, 0, 0);
if (ret) {
unuse_block_rsv(root->fs_info, block_rsv, blocksize);
return ERR_PTR(ret);
}
if (ret)
goto out_unuse;

buf = btrfs_init_new_buffer(trans, root, ins.objectid, level);
BUG_ON(IS_ERR(buf)); /* -ENOMEM */
if (IS_ERR(buf)) {
ret = PTR_ERR(buf);
goto out_free_reserved;
}

if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) {
if (parent == 0)
Expand All @@ -7593,9 +7595,11 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
BUG_ON(parent > 0);

if (root_objectid != BTRFS_TREE_LOG_OBJECTID) {
struct btrfs_delayed_extent_op *extent_op;
extent_op = btrfs_alloc_delayed_extent_op();
BUG_ON(!extent_op); /* -ENOMEM */
if (!extent_op) {
ret = -ENOMEM;
goto out_free_buf;
}
if (key)
memcpy(&extent_op->key, key, sizeof(extent_op->key));
else
Expand All @@ -7610,13 +7614,24 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
extent_op->level = level;

ret = btrfs_add_delayed_tree_ref(root->fs_info, trans,
ins.objectid,
ins.offset, parent, root_objectid,
level, BTRFS_ADD_DELAYED_EXTENT,
extent_op, 0);
BUG_ON(ret); /* -ENOMEM */
ins.objectid, ins.offset,
parent, root_objectid, level,
BTRFS_ADD_DELAYED_EXTENT,
extent_op, 0);
if (ret)
goto out_free_delayed;
}
return buf;

out_free_delayed:
btrfs_free_delayed_extent_op(extent_op);
out_free_buf:
free_extent_buffer(buf);
out_free_reserved:
btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 0);
out_unuse:
unuse_block_rsv(root->fs_info, block_rsv, blocksize);
return ERR_PTR(ret);
}

struct walk_control {
Expand Down

0 comments on commit 67b7859

Please sign in to comment.