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 <[email protected]> --- 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 [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
