diff mbox

Btrfs: free up reserved space if we fail to insert extent entry

Message ID 1367585686-18020-1-git-send-email-jbacik@fusionio.com (mailing list archive)
State New, archived
Headers show

Commit Message

Josef Bacik May 3, 2013, 12:54 p.m. UTC
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 mbox

Patch

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;
 }