diff options
author | Jeff Mahoney <jeffm@suse.com> | 2012-03-12 11:03:00 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.cz> | 2012-03-22 06:52:54 -0400 |
commit | 79787eaab46121d4713ed03c8fc63b9ec3eaec76 (patch) | |
tree | ee6b17d0811ee54ab74a03aa4e0bb92769d2f12a /fs/btrfs/relocation.c | |
parent | 49b25e0540904be0bf558b84475c69d72e4de66e (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.c | 35 |
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: | |||
4102 | static noinline_for_stack int mark_garbage_root(struct btrfs_root *root) | 4102 | static 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); |
4252 | out_free: | 4262 | out_free: |
4253 | kfree(rc); | 4263 | kfree(rc); |
4254 | out: | 4264 | out: |
@@ -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 | } |
4329 | out: | ||
4317 | btrfs_put_ordered_extent(ordered); | 4330 | btrfs_put_ordered_extent(ordered); |
4318 | return ret; | 4331 | return ret; |
4319 | } | 4332 | } |