diff options
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/ctree.h | 5 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 56 | ||||
| -rw-r--r-- | fs/btrfs/root-tree.c | 29 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 37 |
4 files changed, 80 insertions, 47 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 1372057e1ec1..399521ab61da 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -3400,6 +3400,11 @@ static inline void __btrfs_set_fs_incompat(struct btrfs_fs_info *fs_info, | |||
| 3400 | } | 3400 | } |
| 3401 | } | 3401 | } |
| 3402 | 3402 | ||
| 3403 | /* | ||
| 3404 | * Call btrfs_abort_transaction as early as possible when an error condition is | ||
| 3405 | * detected, that way the exact line number is reported. | ||
| 3406 | */ | ||
| 3407 | |||
| 3403 | #define btrfs_abort_transaction(trans, root, errno) \ | 3408 | #define btrfs_abort_transaction(trans, root, errno) \ |
| 3404 | do { \ | 3409 | do { \ |
| 3405 | __btrfs_abort_transaction(trans, root, __func__, \ | 3410 | __btrfs_abort_transaction(trans, root, __func__, \ |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a3a902fdeb49..395e222e39ab 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -5123,8 +5123,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
| 5123 | ret = remove_extent_backref(trans, extent_root, path, | 5123 | ret = remove_extent_backref(trans, extent_root, path, |
| 5124 | NULL, refs_to_drop, | 5124 | NULL, refs_to_drop, |
| 5125 | is_data); | 5125 | is_data); |
| 5126 | if (ret) | 5126 | if (ret) { |
| 5127 | goto abort; | 5127 | btrfs_abort_transaction(trans, extent_root, ret); |
| 5128 | goto out; | ||
| 5129 | } | ||
| 5128 | btrfs_release_path(path); | 5130 | btrfs_release_path(path); |
| 5129 | path->leave_spinning = 1; | 5131 | path->leave_spinning = 1; |
| 5130 | 5132 | ||
| @@ -5142,8 +5144,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
| 5142 | btrfs_print_leaf(extent_root, | 5144 | btrfs_print_leaf(extent_root, |
| 5143 | path->nodes[0]); | 5145 | path->nodes[0]); |
| 5144 | } | 5146 | } |
| 5145 | if (ret < 0) | 5147 | if (ret < 0) { |
| 5146 | goto abort; | 5148 | btrfs_abort_transaction(trans, extent_root, ret); |
| 5149 | goto out; | ||
| 5150 | } | ||
| 5147 | extent_slot = path->slots[0]; | 5151 | extent_slot = path->slots[0]; |
| 5148 | } | 5152 | } |
| 5149 | } else if (ret == -ENOENT) { | 5153 | } else if (ret == -ENOENT) { |
| @@ -5157,7 +5161,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
| 5157 | (unsigned long long)owner_objectid, | 5161 | (unsigned long long)owner_objectid, |
| 5158 | (unsigned long long)owner_offset); | 5162 | (unsigned long long)owner_offset); |
| 5159 | } else { | 5163 | } else { |
| 5160 | goto abort; | 5164 | btrfs_abort_transaction(trans, extent_root, ret); |
| 5165 | goto out; | ||
| 5161 | } | 5166 | } |
| 5162 | 5167 | ||
| 5163 | leaf = path->nodes[0]; | 5168 | leaf = path->nodes[0]; |
| @@ -5167,8 +5172,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
| 5167 | BUG_ON(found_extent || extent_slot != path->slots[0]); | 5172 | BUG_ON(found_extent || extent_slot != path->slots[0]); |
| 5168 | ret = convert_extent_item_v0(trans, extent_root, path, | 5173 | ret = convert_extent_item_v0(trans, extent_root, path, |
| 5169 | owner_objectid, 0); | 5174 | owner_objectid, 0); |
| 5170 | if (ret < 0) | 5175 | if (ret < 0) { |
| 5171 | goto abort; | 5176 | btrfs_abort_transaction(trans, extent_root, ret); |
| 5177 | goto out; | ||
| 5178 | } | ||
| 5172 | 5179 | ||
| 5173 | btrfs_release_path(path); | 5180 | btrfs_release_path(path); |
| 5174 | path->leave_spinning = 1; | 5181 | path->leave_spinning = 1; |
| @@ -5185,8 +5192,11 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
| 5185 | (unsigned long long)bytenr); | 5192 | (unsigned long long)bytenr); |
| 5186 | btrfs_print_leaf(extent_root, path->nodes[0]); | 5193 | btrfs_print_leaf(extent_root, path->nodes[0]); |
| 5187 | } | 5194 | } |
| 5188 | if (ret < 0) | 5195 | if (ret < 0) { |
| 5189 | goto abort; | 5196 | btrfs_abort_transaction(trans, extent_root, ret); |
| 5197 | goto out; | ||
| 5198 | } | ||
| 5199 | |||
| 5190 | extent_slot = path->slots[0]; | 5200 | extent_slot = path->slots[0]; |
| 5191 | leaf = path->nodes[0]; | 5201 | leaf = path->nodes[0]; |
| 5192 | item_size = btrfs_item_size_nr(leaf, extent_slot); | 5202 | item_size = btrfs_item_size_nr(leaf, extent_slot); |
| @@ -5223,8 +5233,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
| 5223 | ret = remove_extent_backref(trans, extent_root, path, | 5233 | ret = remove_extent_backref(trans, extent_root, path, |
| 5224 | iref, refs_to_drop, | 5234 | iref, refs_to_drop, |
| 5225 | is_data); | 5235 | is_data); |
| 5226 | if (ret) | 5236 | if (ret) { |
| 5227 | goto abort; | 5237 | btrfs_abort_transaction(trans, extent_root, ret); |
| 5238 | goto out; | ||
| 5239 | } | ||
| 5228 | } | 5240 | } |
| 5229 | } else { | 5241 | } else { |
| 5230 | if (found_extent) { | 5242 | if (found_extent) { |
| @@ -5241,27 +5253,29 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, | |||
| 5241 | 5253 | ||
| 5242 | ret = btrfs_del_items(trans, extent_root, path, path->slots[0], | 5254 | ret = btrfs_del_items(trans, extent_root, path, path->slots[0], |
| 5243 | num_to_del); | 5255 | num_to_del); |
| 5244 | if (ret) | 5256 | if (ret) { |
| 5245 | goto abort; | 5257 | btrfs_abort_transaction(trans, extent_root, ret); |
| 5258 | goto out; | ||
| 5259 | } | ||
| 5246 | btrfs_release_path(path); | 5260 | btrfs_release_path(path); |
| 5247 | 5261 | ||
| 5248 | if (is_data) { | 5262 | if (is_data) { |
| 5249 | ret = btrfs_del_csums(trans, root, bytenr, num_bytes); | 5263 | ret = btrfs_del_csums(trans, root, bytenr, num_bytes); |
| 5250 | if (ret) | 5264 | if (ret) { |
| 5251 | goto abort; | 5265 | btrfs_abort_transaction(trans, extent_root, ret); |
| 5266 | goto out; | ||
| 5267 | } | ||
| 5252 | } | 5268 | } |
| 5253 | 5269 | ||
| 5254 | ret = update_block_group(trans, root, bytenr, num_bytes, 0); | 5270 | ret = update_block_group(trans, root, bytenr, num_bytes, 0); |
| 5255 | if (ret) | 5271 | if (ret) { |
| 5256 | goto abort; | 5272 | btrfs_abort_transaction(trans, extent_root, ret); |
| 5273 | goto out; | ||
| 5274 | } | ||
| 5257 | } | 5275 | } |
| 5258 | out: | 5276 | out: |
| 5259 | btrfs_free_path(path); | 5277 | btrfs_free_path(path); |
| 5260 | return ret; | 5278 | return ret; |
| 5261 | |||
| 5262 | abort: | ||
| 5263 | btrfs_abort_transaction(trans, extent_root, ret); | ||
| 5264 | goto out; | ||
| 5265 | } | 5279 | } |
| 5266 | 5280 | ||
| 5267 | /* | 5281 | /* |
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 10d8e4d88071..eb923d087da7 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
| @@ -141,8 +141,10 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 141 | return -ENOMEM; | 141 | return -ENOMEM; |
| 142 | 142 | ||
| 143 | ret = btrfs_search_slot(trans, root, key, path, 0, 1); | 143 | ret = btrfs_search_slot(trans, root, key, path, 0, 1); |
| 144 | if (ret < 0) | 144 | if (ret < 0) { |
| 145 | goto out_abort; | 145 | btrfs_abort_transaction(trans, root, ret); |
| 146 | goto out; | ||
| 147 | } | ||
| 146 | 148 | ||
| 147 | if (ret != 0) { | 149 | if (ret != 0) { |
| 148 | btrfs_print_leaf(root, path->nodes[0]); | 150 | btrfs_print_leaf(root, path->nodes[0]); |
| @@ -166,16 +168,23 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 166 | btrfs_release_path(path); | 168 | btrfs_release_path(path); |
| 167 | ret = btrfs_search_slot(trans, root, key, path, | 169 | ret = btrfs_search_slot(trans, root, key, path, |
| 168 | -1, 1); | 170 | -1, 1); |
| 169 | if (ret < 0) | 171 | if (ret < 0) { |
| 170 | goto out_abort; | 172 | btrfs_abort_transaction(trans, root, ret); |
| 173 | goto out; | ||
| 174 | } | ||
| 175 | |||
| 171 | ret = btrfs_del_item(trans, root, path); | 176 | ret = btrfs_del_item(trans, root, path); |
| 172 | if (ret < 0) | 177 | if (ret < 0) { |
| 173 | goto out_abort; | 178 | btrfs_abort_transaction(trans, root, ret); |
| 179 | goto out; | ||
| 180 | } | ||
| 174 | btrfs_release_path(path); | 181 | btrfs_release_path(path); |
| 175 | ret = btrfs_insert_empty_item(trans, root, path, | 182 | ret = btrfs_insert_empty_item(trans, root, path, |
| 176 | key, sizeof(*item)); | 183 | key, sizeof(*item)); |
| 177 | if (ret < 0) | 184 | if (ret < 0) { |
| 178 | goto out_abort; | 185 | btrfs_abort_transaction(trans, root, ret); |
| 186 | goto out; | ||
| 187 | } | ||
| 179 | l = path->nodes[0]; | 188 | l = path->nodes[0]; |
| 180 | slot = path->slots[0]; | 189 | slot = path->slots[0]; |
| 181 | ptr = btrfs_item_ptr_offset(l, slot); | 190 | ptr = btrfs_item_ptr_offset(l, slot); |
| @@ -192,10 +201,6 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 192 | out: | 201 | out: |
| 193 | btrfs_free_path(path); | 202 | btrfs_free_path(path); |
| 194 | return ret; | 203 | return ret; |
| 195 | |||
| 196 | out_abort: | ||
| 197 | btrfs_abort_transaction(trans, root, ret); | ||
| 198 | goto out; | ||
| 199 | } | 204 | } |
| 200 | 205 | ||
| 201 | int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 206 | int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 88b969aeeb71..4f4de51b5bdd 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -1775,15 +1775,21 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
| 1775 | 1775 | ||
| 1776 | if (seeding_dev) { | 1776 | if (seeding_dev) { |
| 1777 | ret = init_first_rw_device(trans, root, device); | 1777 | ret = init_first_rw_device(trans, root, device); |
| 1778 | if (ret) | 1778 | if (ret) { |
| 1779 | btrfs_abort_transaction(trans, root, ret); | ||
| 1779 | goto error_trans; | 1780 | goto error_trans; |
| 1781 | } | ||
| 1780 | ret = btrfs_finish_sprout(trans, root); | 1782 | ret = btrfs_finish_sprout(trans, root); |
| 1781 | if (ret) | 1783 | if (ret) { |
| 1784 | btrfs_abort_transaction(trans, root, ret); | ||
| 1782 | goto error_trans; | 1785 | goto error_trans; |
| 1786 | } | ||
| 1783 | } else { | 1787 | } else { |
| 1784 | ret = btrfs_add_device(trans, root, device); | 1788 | ret = btrfs_add_device(trans, root, device); |
| 1785 | if (ret) | 1789 | if (ret) { |
| 1790 | btrfs_abort_transaction(trans, root, ret); | ||
| 1786 | goto error_trans; | 1791 | goto error_trans; |
| 1792 | } | ||
| 1787 | } | 1793 | } |
| 1788 | 1794 | ||
| 1789 | /* | 1795 | /* |
| @@ -1814,7 +1820,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
| 1814 | 1820 | ||
| 1815 | error_trans: | 1821 | error_trans: |
| 1816 | unlock_chunks(root); | 1822 | unlock_chunks(root); |
| 1817 | btrfs_abort_transaction(trans, root, ret); | ||
| 1818 | btrfs_end_transaction(trans, root); | 1823 | btrfs_end_transaction(trans, root); |
| 1819 | rcu_string_free(device->name); | 1824 | rcu_string_free(device->name); |
| 1820 | kfree(device); | 1825 | kfree(device); |
| @@ -3608,12 +3613,16 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans, | |||
| 3608 | ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map, | 3613 | ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map, |
| 3609 | &sys_chunk_size, &sys_stripe_size, | 3614 | &sys_chunk_size, &sys_stripe_size, |
| 3610 | sys_chunk_offset, alloc_profile); | 3615 | sys_chunk_offset, alloc_profile); |
| 3611 | if (ret) | 3616 | if (ret) { |
| 3612 | goto abort; | 3617 | btrfs_abort_transaction(trans, root, ret); |
| 3618 | goto out; | ||
| 3619 | } | ||
| 3613 | 3620 | ||
| 3614 | ret = btrfs_add_device(trans, fs_info->chunk_root, device); | 3621 | ret = btrfs_add_device(trans, fs_info->chunk_root, device); |
| 3615 | if (ret) | 3622 | if (ret) { |
| 3616 | goto abort; | 3623 | btrfs_abort_transaction(trans, root, ret); |
| 3624 | goto out; | ||
| 3625 | } | ||
| 3617 | 3626 | ||
| 3618 | /* | 3627 | /* |
| 3619 | * Modifying chunk tree needs allocating new blocks from both | 3628 | * Modifying chunk tree needs allocating new blocks from both |
| @@ -3623,19 +3632,19 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans, | |||
| 3623 | */ | 3632 | */ |
| 3624 | ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset, | 3633 | ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset, |
| 3625 | chunk_size, stripe_size); | 3634 | chunk_size, stripe_size); |
| 3626 | if (ret) | 3635 | if (ret) { |
| 3627 | goto abort; | 3636 | btrfs_abort_transaction(trans, root, ret); |
| 3637 | goto out; | ||
| 3638 | } | ||
| 3628 | 3639 | ||
| 3629 | ret = __finish_chunk_alloc(trans, extent_root, sys_map, | 3640 | ret = __finish_chunk_alloc(trans, extent_root, sys_map, |
| 3630 | sys_chunk_offset, sys_chunk_size, | 3641 | sys_chunk_offset, sys_chunk_size, |
| 3631 | sys_stripe_size); | 3642 | sys_stripe_size); |
| 3632 | if (ret) | 3643 | if (ret) |
| 3633 | goto abort; | 3644 | btrfs_abort_transaction(trans, root, ret); |
| 3634 | 3645 | ||
| 3635 | return 0; | 3646 | out: |
| 3636 | 3647 | ||
| 3637 | abort: | ||
| 3638 | btrfs_abort_transaction(trans, root, ret); | ||
| 3639 | return ret; | 3648 | return ret; |
| 3640 | } | 3649 | } |
| 3641 | 3650 | ||
