aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/relocation.c
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2012-03-12 11:03:00 -0400
committerDavid Sterba <dsterba@suse.cz>2012-03-22 06:52:54 -0400
commit79787eaab46121d4713ed03c8fc63b9ec3eaec76 (patch)
treeee6b17d0811ee54ab74a03aa4e0bb92769d2f12a /fs/btrfs/relocation.c
parent49b25e0540904be0bf558b84475c69d72e4de66e (diff)
btrfs: replace many BUG_ONs with proper error handling
btrfs currently handles most errors with BUG_ON. This patch is a work-in- progress but aims to handle most errors other than internal logic errors and ENOMEM more gracefully. This iteration prevents most crashes but can run into lockups with the page lock on occasion when the timing "works out." Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r--fs/btrfs/relocation.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index cba7a0bf3667..017281dbb2a7 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -4102,10 +4102,11 @@ out:
4102static noinline_for_stack int mark_garbage_root(struct btrfs_root *root) 4102static noinline_for_stack int mark_garbage_root(struct btrfs_root *root)
4103{ 4103{
4104 struct btrfs_trans_handle *trans; 4104 struct btrfs_trans_handle *trans;
4105 int ret; 4105 int ret, err;
4106 4106
4107 trans = btrfs_start_transaction(root->fs_info->tree_root, 0); 4107 trans = btrfs_start_transaction(root->fs_info->tree_root, 0);
4108 BUG_ON(IS_ERR(trans)); 4108 if (IS_ERR(trans))
4109 return PTR_ERR(trans);
4109 4110
4110 memset(&root->root_item.drop_progress, 0, 4111 memset(&root->root_item.drop_progress, 0,
4111 sizeof(root->root_item.drop_progress)); 4112 sizeof(root->root_item.drop_progress));
@@ -4113,11 +4114,11 @@ static noinline_for_stack int mark_garbage_root(struct btrfs_root *root)
4113 btrfs_set_root_refs(&root->root_item, 0); 4114 btrfs_set_root_refs(&root->root_item, 0);
4114 ret = btrfs_update_root(trans, root->fs_info->tree_root, 4115 ret = btrfs_update_root(trans, root->fs_info->tree_root,
4115 &root->root_key, &root->root_item); 4116 &root->root_key, &root->root_item);
4116 BUG_ON(ret);
4117 4117
4118 ret = btrfs_end_transaction(trans, root->fs_info->tree_root); 4118 err = btrfs_end_transaction(trans, root->fs_info->tree_root);
4119 BUG_ON(ret); 4119 if (err)
4120 return 0; 4120 return err;
4121 return ret;
4121} 4122}
4122 4123
4123/* 4124/*
@@ -4185,7 +4186,11 @@ int btrfs_recover_relocation(struct btrfs_root *root)
4185 err = ret; 4186 err = ret;
4186 goto out; 4187 goto out;
4187 } 4188 }
4188 mark_garbage_root(reloc_root); 4189 ret = mark_garbage_root(reloc_root);
4190 if (ret < 0) {
4191 err = ret;
4192 goto out;
4193 }
4189 } 4194 }
4190 } 4195 }
4191 4196
@@ -4231,14 +4236,19 @@ int btrfs_recover_relocation(struct btrfs_root *root)
4231 4236
4232 fs_root = read_fs_root(root->fs_info, 4237 fs_root = read_fs_root(root->fs_info,
4233 reloc_root->root_key.offset); 4238 reloc_root->root_key.offset);
4234 BUG_ON(IS_ERR(fs_root)); 4239 if (IS_ERR(fs_root)) {
4240 err = PTR_ERR(fs_root);
4241 goto out_free;
4242 }
4235 4243
4236 err = __add_reloc_root(reloc_root); 4244 err = __add_reloc_root(reloc_root);
4237 BUG_ON(err < 0); 4245 BUG_ON(err < 0); /* -ENOMEM or logic error */
4238 fs_root->reloc_root = reloc_root; 4246 fs_root->reloc_root = reloc_root;
4239 } 4247 }
4240 4248
4241 btrfs_commit_transaction(trans, rc->extent_root); 4249 err = btrfs_commit_transaction(trans, rc->extent_root);
4250 if (err)
4251 goto out_free;
4242 4252
4243 merge_reloc_roots(rc); 4253 merge_reloc_roots(rc);
4244 4254
@@ -4248,7 +4258,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
4248 if (IS_ERR(trans)) 4258 if (IS_ERR(trans))
4249 err = PTR_ERR(trans); 4259 err = PTR_ERR(trans);
4250 else 4260 else
4251 btrfs_commit_transaction(trans, rc->extent_root); 4261 err = btrfs_commit_transaction(trans, rc->extent_root);
4252out_free: 4262out_free:
4253 kfree(rc); 4263 kfree(rc);
4254out: 4264out:
@@ -4297,6 +4307,8 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len)
4297 disk_bytenr = file_pos + BTRFS_I(inode)->index_cnt; 4307 disk_bytenr = file_pos + BTRFS_I(inode)->index_cnt;
4298 ret = btrfs_lookup_csums_range(root->fs_info->csum_root, disk_bytenr, 4308 ret = btrfs_lookup_csums_range(root->fs_info->csum_root, disk_bytenr,
4299 disk_bytenr + len - 1, &list, 0); 4309 disk_bytenr + len - 1, &list, 0);
4310 if (ret)
4311 goto out;
4300 4312
4301 while (!list_empty(&list)) { 4313 while (!list_empty(&list)) {
4302 sums = list_entry(list.next, struct btrfs_ordered_sum, list); 4314 sums = list_entry(list.next, struct btrfs_ordered_sum, list);
@@ -4314,6 +4326,7 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len)
4314 4326
4315 btrfs_add_ordered_sum(inode, ordered, sums); 4327 btrfs_add_ordered_sum(inode, ordered, sums);
4316 } 4328 }
4329out:
4317 btrfs_put_ordered_extent(ordered); 4330 btrfs_put_ordered_extent(ordered);
4318 return ret; 4331 return ret;
4319} 4332}