Josef Bacik
2013-May-03 12:54 UTC
[PATCH] Btrfs: free up reserved space if we fail to insert extent entry
If we are inserting an extent entry for the first allocation of an extent and the addition fails we need to clean up the reserved space otherwise we''ll get WARN_ON()''s on unmount because we have left over reserve space. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com> --- fs/btrfs/extent-tree.c | 45 +++++++++++++++++++++++++++++---------------- 1 files changed, 29 insertions(+), 16 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 2305b5c..7049bbc 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -6407,16 +6407,16 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, size = sizeof(*extent_item) + btrfs_extent_inline_ref_size(type); path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; + if (!path) { + ret = -ENOMEM; + goto out; + } path->leave_spinning = 1; ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, ins, size); - if (ret) { - btrfs_free_path(path); - return ret; - } + if (ret) + goto out; leaf = path->nodes[0]; extent_item = btrfs_item_ptr(leaf, path->slots[0], @@ -6444,14 +6444,21 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_free_path(path); + path = NULL; ret = update_block_group(root, ins->objectid, ins->offset, 1); - if (ret) { /* -ENOENT, logic error */ + if (ret) { btrfs_err(fs_info, "update block group failed for %llu %llu", (unsigned long long)ins->objectid, (unsigned long long)ins->offset); - BUG(); + goto out; } + + return ret; +out: + btrfs_free_path(path); + btrfs_pin_extent(root, ins->objectid, ins->offset, 1); + btrfs_del_csums(trans, root, ins->objectid, ins->offset); return ret; } @@ -6476,16 +6483,16 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, size += sizeof(*block_info); path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; + if (!path) { + ret = -ENOMEM; + goto out; + } path->leave_spinning = 1; ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, ins, size); - if (ret) { - btrfs_free_path(path); - return ret; - } + if (ret) + goto out; leaf = path->nodes[0]; extent_item = btrfs_item_ptr(leaf, path->slots[0], @@ -6517,14 +6524,20 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, btrfs_mark_buffer_dirty(leaf); btrfs_free_path(path); + path = NULL; ret = update_block_group(root, ins->objectid, root->leafsize, 1); - if (ret) { /* -ENOENT, logic error */ + if (ret) { btrfs_err(fs_info, "update block group failed for %llu %llu", (unsigned long long)ins->objectid, (unsigned long long)ins->offset); - BUG(); + goto out; } + + return ret; +out: + btrfs_free_path(path); + btrfs_pin_extent(root, ins->objectid, root->leafsize, 1); return ret; } -- 1.7.7.6 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html