btrfs: fix return value check of btrfs_join_transaction()
The error check of btrfs_join_transaction()/btrfs_join_transaction_nolock() is added, and the mistake of the error check in several places is corrected. For more stable Btrfs, I think that we should reduce BUG_ON(). But, I think that long time is necessary for this. So, I propose this patch as a short-term solution. With this patch: - To more stable Btrfs, the part that should be corrected is clarified. - The panic isn't done by the NULL pointer reference etc. (even if BUG_ON() is increased temporarily) - The error code is returned in the place where the error can be easily returned. As a long-term plan: - BUG_ON() is reduced by using the forced-readonly framework, etc. Signed-off-by: Tsutomu Itoh <t-itoh@jp.fujitsu.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
34d19bada0
commit
3612b49598
|
@ -1550,6 +1550,7 @@ static int transaction_kthread(void *arg)
|
||||||
spin_unlock(&root->fs_info->new_trans_lock);
|
spin_unlock(&root->fs_info->new_trans_lock);
|
||||||
|
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
|
BUG_ON(IS_ERR(trans));
|
||||||
if (transid == trans->transid) {
|
if (transid == trans->transid) {
|
||||||
ret = btrfs_commit_transaction(trans, root);
|
ret = btrfs_commit_transaction(trans, root);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
@ -2464,10 +2465,14 @@ int btrfs_commit_super(struct btrfs_root *root)
|
||||||
up_write(&root->fs_info->cleanup_work_sem);
|
up_write(&root->fs_info->cleanup_work_sem);
|
||||||
|
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
|
if (IS_ERR(trans))
|
||||||
|
return PTR_ERR(trans);
|
||||||
ret = btrfs_commit_transaction(trans, root);
|
ret = btrfs_commit_transaction(trans, root);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
/* run commit again to drop the original snapshot */
|
/* run commit again to drop the original snapshot */
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
|
if (IS_ERR(trans))
|
||||||
|
return PTR_ERR(trans);
|
||||||
btrfs_commit_transaction(trans, root);
|
btrfs_commit_transaction(trans, root);
|
||||||
ret = btrfs_write_and_wait_transaction(NULL, root);
|
ret = btrfs_write_and_wait_transaction(NULL, root);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
|
@ -7478,7 +7478,7 @@ int btrfs_drop_dead_reloc_roots(struct btrfs_root *root)
|
||||||
BUG_ON(reloc_root->commit_root != NULL);
|
BUG_ON(reloc_root->commit_root != NULL);
|
||||||
while (1) {
|
while (1) {
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
BUG_ON(!trans);
|
BUG_ON(IS_ERR(trans));
|
||||||
|
|
||||||
mutex_lock(&root->fs_info->drop_mutex);
|
mutex_lock(&root->fs_info->drop_mutex);
|
||||||
ret = btrfs_drop_snapshot(trans, reloc_root);
|
ret = btrfs_drop_snapshot(trans, reloc_root);
|
||||||
|
|
|
@ -416,7 +416,7 @@ again:
|
||||||
}
|
}
|
||||||
if (start == 0) {
|
if (start == 0) {
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
BUG_ON(!trans);
|
BUG_ON(IS_ERR(trans));
|
||||||
btrfs_set_trans_block_group(trans, inode);
|
btrfs_set_trans_block_group(trans, inode);
|
||||||
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
||||||
|
|
||||||
|
@ -612,6 +612,7 @@ retry:
|
||||||
GFP_NOFS);
|
GFP_NOFS);
|
||||||
|
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
|
BUG_ON(IS_ERR(trans));
|
||||||
ret = btrfs_reserve_extent(trans, root,
|
ret = btrfs_reserve_extent(trans, root,
|
||||||
async_extent->compressed_size,
|
async_extent->compressed_size,
|
||||||
async_extent->compressed_size,
|
async_extent->compressed_size,
|
||||||
|
@ -771,7 +772,7 @@ static noinline int cow_file_range(struct inode *inode,
|
||||||
|
|
||||||
BUG_ON(root == root->fs_info->tree_root);
|
BUG_ON(root == root->fs_info->tree_root);
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
BUG_ON(!trans);
|
BUG_ON(IS_ERR(trans));
|
||||||
btrfs_set_trans_block_group(trans, inode);
|
btrfs_set_trans_block_group(trans, inode);
|
||||||
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
||||||
|
|
||||||
|
@ -1049,7 +1050,7 @@ static noinline int run_delalloc_nocow(struct inode *inode,
|
||||||
} else {
|
} else {
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
}
|
}
|
||||||
BUG_ON(!trans);
|
BUG_ON(IS_ERR(trans));
|
||||||
|
|
||||||
cow_start = (u64)-1;
|
cow_start = (u64)-1;
|
||||||
cur_offset = start;
|
cur_offset = start;
|
||||||
|
@ -1704,7 +1705,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
|
||||||
trans = btrfs_join_transaction_nolock(root, 1);
|
trans = btrfs_join_transaction_nolock(root, 1);
|
||||||
else
|
else
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
BUG_ON(!trans);
|
BUG_ON(IS_ERR(trans));
|
||||||
btrfs_set_trans_block_group(trans, inode);
|
btrfs_set_trans_block_group(trans, inode);
|
||||||
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
||||||
ret = btrfs_update_inode(trans, root, inode);
|
ret = btrfs_update_inode(trans, root, inode);
|
||||||
|
@ -1721,6 +1722,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
|
||||||
trans = btrfs_join_transaction_nolock(root, 1);
|
trans = btrfs_join_transaction_nolock(root, 1);
|
||||||
else
|
else
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
|
BUG_ON(IS_ERR(trans));
|
||||||
btrfs_set_trans_block_group(trans, inode);
|
btrfs_set_trans_block_group(trans, inode);
|
||||||
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
||||||
|
|
||||||
|
@ -2382,6 +2384,7 @@ void btrfs_orphan_cleanup(struct btrfs_root *root)
|
||||||
|
|
||||||
if (root->orphan_block_rsv || root->orphan_item_inserted) {
|
if (root->orphan_block_rsv || root->orphan_item_inserted) {
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
|
BUG_ON(IS_ERR(trans));
|
||||||
btrfs_end_transaction(trans, root);
|
btrfs_end_transaction(trans, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4350,6 +4353,8 @@ int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||||
trans = btrfs_join_transaction_nolock(root, 1);
|
trans = btrfs_join_transaction_nolock(root, 1);
|
||||||
else
|
else
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
|
if (IS_ERR(trans))
|
||||||
|
return PTR_ERR(trans);
|
||||||
btrfs_set_trans_block_group(trans, inode);
|
btrfs_set_trans_block_group(trans, inode);
|
||||||
if (nolock)
|
if (nolock)
|
||||||
ret = btrfs_end_transaction_nolock(trans, root);
|
ret = btrfs_end_transaction_nolock(trans, root);
|
||||||
|
@ -4375,6 +4380,7 @@ void btrfs_dirty_inode(struct inode *inode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
|
BUG_ON(IS_ERR(trans));
|
||||||
btrfs_set_trans_block_group(trans, inode);
|
btrfs_set_trans_block_group(trans, inode);
|
||||||
|
|
||||||
ret = btrfs_update_inode(trans, root, inode);
|
ret = btrfs_update_inode(trans, root, inode);
|
||||||
|
@ -5179,6 +5185,8 @@ again:
|
||||||
em = NULL;
|
em = NULL;
|
||||||
btrfs_release_path(root, path);
|
btrfs_release_path(root, path);
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
|
if (IS_ERR(trans))
|
||||||
|
return ERR_CAST(trans);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
map = kmap(page);
|
map = kmap(page);
|
||||||
|
@ -5283,8 +5291,8 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
|
||||||
btrfs_drop_extent_cache(inode, start, start + len - 1, 0);
|
btrfs_drop_extent_cache(inode, start, start + len - 1, 0);
|
||||||
|
|
||||||
trans = btrfs_join_transaction(root, 0);
|
trans = btrfs_join_transaction(root, 0);
|
||||||
if (!trans)
|
if (IS_ERR(trans))
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_CAST(trans);
|
||||||
|
|
||||||
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
|
||||||
|
|
||||||
|
@ -5508,7 +5516,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
|
||||||
* while we look for nocow cross refs
|
* while we look for nocow cross refs
|
||||||
*/
|
*/
|
||||||
trans = btrfs_join_transaction(root, 0);
|
trans = btrfs_join_transaction(root, 0);
|
||||||
if (!trans)
|
if (IS_ERR(trans))
|
||||||
goto must_cow;
|
goto must_cow;
|
||||||
|
|
||||||
if (can_nocow_odirect(trans, inode, start, len) == 1) {
|
if (can_nocow_odirect(trans, inode, start, len) == 1) {
|
||||||
|
@ -5643,7 +5651,7 @@ again:
|
||||||
BUG_ON(!ordered);
|
BUG_ON(!ordered);
|
||||||
|
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
if (!trans) {
|
if (IS_ERR(trans)) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,7 +203,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
|
||||||
|
|
||||||
|
|
||||||
trans = btrfs_join_transaction(root, 1);
|
trans = btrfs_join_transaction(root, 1);
|
||||||
BUG_ON(!trans);
|
BUG_ON(IS_ERR(trans));
|
||||||
|
|
||||||
ret = btrfs_update_inode(trans, root, inode);
|
ret = btrfs_update_inode(trans, root, inode);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
|
|
@ -2147,6 +2147,12 @@ again:
|
||||||
}
|
}
|
||||||
|
|
||||||
trans = btrfs_join_transaction(rc->extent_root, 1);
|
trans = btrfs_join_transaction(rc->extent_root, 1);
|
||||||
|
if (IS_ERR(trans)) {
|
||||||
|
if (!err)
|
||||||
|
btrfs_block_rsv_release(rc->extent_root,
|
||||||
|
rc->block_rsv, num_bytes);
|
||||||
|
return PTR_ERR(trans);
|
||||||
|
}
|
||||||
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
if (num_bytes != rc->merging_rsv_size) {
|
if (num_bytes != rc->merging_rsv_size) {
|
||||||
|
@ -3222,6 +3228,7 @@ truncate:
|
||||||
trans = btrfs_join_transaction(root, 0);
|
trans = btrfs_join_transaction(root, 0);
|
||||||
if (IS_ERR(trans)) {
|
if (IS_ERR(trans)) {
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
|
ret = PTR_ERR(trans);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3628,6 +3635,7 @@ int prepare_to_relocate(struct reloc_control *rc)
|
||||||
set_reloc_control(rc);
|
set_reloc_control(rc);
|
||||||
|
|
||||||
trans = btrfs_join_transaction(rc->extent_root, 1);
|
trans = btrfs_join_transaction(rc->extent_root, 1);
|
||||||
|
BUG_ON(IS_ERR(trans));
|
||||||
btrfs_commit_transaction(trans, rc->extent_root);
|
btrfs_commit_transaction(trans, rc->extent_root);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3804,7 +3812,10 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
|
||||||
|
|
||||||
/* get rid of pinned extents */
|
/* get rid of pinned extents */
|
||||||
trans = btrfs_join_transaction(rc->extent_root, 1);
|
trans = btrfs_join_transaction(rc->extent_root, 1);
|
||||||
btrfs_commit_transaction(trans, rc->extent_root);
|
if (IS_ERR(trans))
|
||||||
|
err = PTR_ERR(trans);
|
||||||
|
else
|
||||||
|
btrfs_commit_transaction(trans, rc->extent_root);
|
||||||
out_free:
|
out_free:
|
||||||
btrfs_free_block_rsv(rc->extent_root, rc->block_rsv);
|
btrfs_free_block_rsv(rc->extent_root, rc->block_rsv);
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
|
@ -4125,6 +4136,11 @@ int btrfs_recover_relocation(struct btrfs_root *root)
|
||||||
set_reloc_control(rc);
|
set_reloc_control(rc);
|
||||||
|
|
||||||
trans = btrfs_join_transaction(rc->extent_root, 1);
|
trans = btrfs_join_transaction(rc->extent_root, 1);
|
||||||
|
if (IS_ERR(trans)) {
|
||||||
|
unset_reloc_control(rc);
|
||||||
|
err = PTR_ERR(trans);
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
rc->merge_reloc_tree = 1;
|
rc->merge_reloc_tree = 1;
|
||||||
|
|
||||||
|
@ -4154,9 +4170,13 @@ int btrfs_recover_relocation(struct btrfs_root *root)
|
||||||
unset_reloc_control(rc);
|
unset_reloc_control(rc);
|
||||||
|
|
||||||
trans = btrfs_join_transaction(rc->extent_root, 1);
|
trans = btrfs_join_transaction(rc->extent_root, 1);
|
||||||
btrfs_commit_transaction(trans, rc->extent_root);
|
if (IS_ERR(trans))
|
||||||
out:
|
err = PTR_ERR(trans);
|
||||||
|
else
|
||||||
|
btrfs_commit_transaction(trans, rc->extent_root);
|
||||||
|
out_free:
|
||||||
kfree(rc);
|
kfree(rc);
|
||||||
|
out:
|
||||||
while (!list_empty(&reloc_roots)) {
|
while (!list_empty(&reloc_roots)) {
|
||||||
reloc_root = list_entry(reloc_roots.next,
|
reloc_root = list_entry(reloc_roots.next,
|
||||||
struct btrfs_root, root_list);
|
struct btrfs_root, root_list);
|
||||||
|
|
|
@ -1161,6 +1161,11 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,
|
||||||
INIT_DELAYED_WORK(&ac->work, do_async_commit);
|
INIT_DELAYED_WORK(&ac->work, do_async_commit);
|
||||||
ac->root = root;
|
ac->root = root;
|
||||||
ac->newtrans = btrfs_join_transaction(root, 0);
|
ac->newtrans = btrfs_join_transaction(root, 0);
|
||||||
|
if (IS_ERR(ac->newtrans)) {
|
||||||
|
int err = PTR_ERR(ac->newtrans);
|
||||||
|
kfree(ac);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* take transaction reference */
|
/* take transaction reference */
|
||||||
mutex_lock(&root->fs_info->trans_mutex);
|
mutex_lock(&root->fs_info->trans_mutex);
|
||||||
|
|
Loading…
Reference in a new issue