btrfs: move transaction aborts to the point of failure
Call btrfs_abort_transaction as early as possible when an error condition is detected, that way the line number reported is useful and we're not clueless anymore which error path led to the abort. Signed-off-by: David Sterba <dsterba@suse.cz>
This commit is contained in:
parent
8732d44f80
commit
005d6427ac
|
@ -3400,6 +3400,11 @@ static inline void __btrfs_set_fs_incompat(struct btrfs_fs_info *fs_info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call btrfs_abort_transaction as early as possible when an error condition is
|
||||||
|
* detected, that way the exact line number is reported.
|
||||||
|
*/
|
||||||
|
|
||||||
#define btrfs_abort_transaction(trans, root, errno) \
|
#define btrfs_abort_transaction(trans, root, errno) \
|
||||||
do { \
|
do { \
|
||||||
__btrfs_abort_transaction(trans, root, __func__, \
|
__btrfs_abort_transaction(trans, root, __func__, \
|
||||||
|
|
|
@ -5123,8 +5123,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||||
ret = remove_extent_backref(trans, extent_root, path,
|
ret = remove_extent_backref(trans, extent_root, path,
|
||||||
NULL, refs_to_drop,
|
NULL, refs_to_drop,
|
||||||
is_data);
|
is_data);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, extent_root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
btrfs_release_path(path);
|
btrfs_release_path(path);
|
||||||
path->leave_spinning = 1;
|
path->leave_spinning = 1;
|
||||||
|
|
||||||
|
@ -5142,8 +5144,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||||
btrfs_print_leaf(extent_root,
|
btrfs_print_leaf(extent_root,
|
||||||
path->nodes[0]);
|
path->nodes[0]);
|
||||||
}
|
}
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, extent_root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
extent_slot = path->slots[0];
|
extent_slot = path->slots[0];
|
||||||
}
|
}
|
||||||
} else if (ret == -ENOENT) {
|
} else if (ret == -ENOENT) {
|
||||||
|
@ -5157,7 +5161,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||||
(unsigned long long)owner_objectid,
|
(unsigned long long)owner_objectid,
|
||||||
(unsigned long long)owner_offset);
|
(unsigned long long)owner_offset);
|
||||||
} else {
|
} else {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, extent_root, ret);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
leaf = path->nodes[0];
|
leaf = path->nodes[0];
|
||||||
|
@ -5167,8 +5172,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||||
BUG_ON(found_extent || extent_slot != path->slots[0]);
|
BUG_ON(found_extent || extent_slot != path->slots[0]);
|
||||||
ret = convert_extent_item_v0(trans, extent_root, path,
|
ret = convert_extent_item_v0(trans, extent_root, path,
|
||||||
owner_objectid, 0);
|
owner_objectid, 0);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, extent_root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
btrfs_release_path(path);
|
btrfs_release_path(path);
|
||||||
path->leave_spinning = 1;
|
path->leave_spinning = 1;
|
||||||
|
@ -5185,8 +5192,11 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||||
(unsigned long long)bytenr);
|
(unsigned long long)bytenr);
|
||||||
btrfs_print_leaf(extent_root, path->nodes[0]);
|
btrfs_print_leaf(extent_root, path->nodes[0]);
|
||||||
}
|
}
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, extent_root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
extent_slot = path->slots[0];
|
extent_slot = path->slots[0];
|
||||||
leaf = path->nodes[0];
|
leaf = path->nodes[0];
|
||||||
item_size = btrfs_item_size_nr(leaf, extent_slot);
|
item_size = btrfs_item_size_nr(leaf, extent_slot);
|
||||||
|
@ -5223,8 +5233,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||||
ret = remove_extent_backref(trans, extent_root, path,
|
ret = remove_extent_backref(trans, extent_root, path,
|
||||||
iref, refs_to_drop,
|
iref, refs_to_drop,
|
||||||
is_data);
|
is_data);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, extent_root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (found_extent) {
|
if (found_extent) {
|
||||||
|
@ -5241,27 +5253,29 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||||
|
|
||||||
ret = btrfs_del_items(trans, extent_root, path, path->slots[0],
|
ret = btrfs_del_items(trans, extent_root, path, path->slots[0],
|
||||||
num_to_del);
|
num_to_del);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, extent_root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
btrfs_release_path(path);
|
btrfs_release_path(path);
|
||||||
|
|
||||||
if (is_data) {
|
if (is_data) {
|
||||||
ret = btrfs_del_csums(trans, root, bytenr, num_bytes);
|
ret = btrfs_del_csums(trans, root, bytenr, num_bytes);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, extent_root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = update_block_group(trans, root, bytenr, num_bytes, 0);
|
ret = update_block_group(trans, root, bytenr, num_bytes, 0);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, extent_root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
abort:
|
|
||||||
btrfs_abort_transaction(trans, extent_root, ret);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -141,8 +141,10 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = btrfs_search_slot(trans, root, key, path, 0, 1);
|
ret = btrfs_search_slot(trans, root, key, path, 0, 1);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
goto out_abort;
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
btrfs_print_leaf(root, path->nodes[0]);
|
btrfs_print_leaf(root, path->nodes[0]);
|
||||||
|
@ -166,16 +168,23 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
btrfs_release_path(path);
|
btrfs_release_path(path);
|
||||||
ret = btrfs_search_slot(trans, root, key, path,
|
ret = btrfs_search_slot(trans, root, key, path,
|
||||||
-1, 1);
|
-1, 1);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
goto out_abort;
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = btrfs_del_item(trans, root, path);
|
ret = btrfs_del_item(trans, root, path);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
goto out_abort;
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
btrfs_release_path(path);
|
btrfs_release_path(path);
|
||||||
ret = btrfs_insert_empty_item(trans, root, path,
|
ret = btrfs_insert_empty_item(trans, root, path,
|
||||||
key, sizeof(*item));
|
key, sizeof(*item));
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
goto out_abort;
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
l = path->nodes[0];
|
l = path->nodes[0];
|
||||||
slot = path->slots[0];
|
slot = path->slots[0];
|
||||||
ptr = btrfs_item_ptr_offset(l, slot);
|
ptr = btrfs_item_ptr_offset(l, slot);
|
||||||
|
@ -192,10 +201,6 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
out:
|
out:
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
out_abort:
|
|
||||||
btrfs_abort_transaction(trans, root, ret);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||||
|
|
|
@ -1775,16 +1775,22 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
|
||||||
|
|
||||||
if (seeding_dev) {
|
if (seeding_dev) {
|
||||||
ret = init_first_rw_device(trans, root, device);
|
ret = init_first_rw_device(trans, root, device);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
goto error_trans;
|
goto error_trans;
|
||||||
|
}
|
||||||
ret = btrfs_finish_sprout(trans, root);
|
ret = btrfs_finish_sprout(trans, root);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
goto error_trans;
|
goto error_trans;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = btrfs_add_device(trans, root, device);
|
ret = btrfs_add_device(trans, root, device);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
goto error_trans;
|
goto error_trans;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we've got more storage, clear any full flags on the space
|
* we've got more storage, clear any full flags on the space
|
||||||
|
@ -1814,7 +1820,6 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
|
||||||
|
|
||||||
error_trans:
|
error_trans:
|
||||||
unlock_chunks(root);
|
unlock_chunks(root);
|
||||||
btrfs_abort_transaction(trans, root, ret);
|
|
||||||
btrfs_end_transaction(trans, root);
|
btrfs_end_transaction(trans, root);
|
||||||
rcu_string_free(device->name);
|
rcu_string_free(device->name);
|
||||||
kfree(device);
|
kfree(device);
|
||||||
|
@ -3608,12 +3613,16 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
|
||||||
ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map,
|
ret = __btrfs_alloc_chunk(trans, extent_root, &sys_map,
|
||||||
&sys_chunk_size, &sys_stripe_size,
|
&sys_chunk_size, &sys_stripe_size,
|
||||||
sys_chunk_offset, alloc_profile);
|
sys_chunk_offset, alloc_profile);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = btrfs_add_device(trans, fs_info->chunk_root, device);
|
ret = btrfs_add_device(trans, fs_info->chunk_root, device);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Modifying chunk tree needs allocating new blocks from both
|
* 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,
|
||||||
*/
|
*/
|
||||||
ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset,
|
ret = __finish_chunk_alloc(trans, extent_root, map, chunk_offset,
|
||||||
chunk_size, stripe_size);
|
chunk_size, stripe_size);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto abort;
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = __finish_chunk_alloc(trans, extent_root, sys_map,
|
ret = __finish_chunk_alloc(trans, extent_root, sys_map,
|
||||||
sys_chunk_offset, sys_chunk_size,
|
sys_chunk_offset, sys_chunk_size,
|
||||||
sys_stripe_size);
|
sys_stripe_size);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto abort;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
abort:
|
|
||||||
btrfs_abort_transaction(trans, root, ret);
|
btrfs_abort_transaction(trans, root, ret);
|
||||||
|
|
||||||
|
out:
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue