Commit 3612b495 authored by Tsutomu Itoh's avatar Tsutomu Itoh Committed by Chris Mason

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: default avatarTsutomu Itoh <t-itoh@jp.fujitsu.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 34d19bad
...@@ -1550,6 +1550,7 @@ static int transaction_kthread(void *arg) ...@@ -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) ...@@ -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) ...@@ -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 @@ static noinline int compress_file_range(struct inode *inode, ...@@ -416,7 +416,7 @@ static noinline int compress_file_range(struct inode *inode,
} }
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 @@ static noinline int submit_compressed_extents(struct inode *inode, ...@@ -612,6 +612,7 @@ static noinline int submit_compressed_extents(struct inode *inode,
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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, ...@@ -5179,6 +5185,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
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, ...@@ -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, ...@@ -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 @@ static void btrfs_endio_direct_write(struct bio *bio, int err) ...@@ -5643,7 +5651,7 @@ static void btrfs_endio_direct_write(struct bio *bio, int err)
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) ...@@ -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 @@ int prepare_to_merge(struct reloc_control *rc, int err) ...@@ -2147,6 +2147,12 @@ int prepare_to_merge(struct reloc_control *rc, int err)
} }
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 @@ static int delete_block_group_cache(struct btrfs_fs_info *fs_info, ...@@ -3222,6 +3228,7 @@ static int delete_block_group_cache(struct btrfs_fs_info *fs_info,
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) ...@@ -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,6 +3812,9 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) ...@@ -3804,6 +3812,9 @@ 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);
if (IS_ERR(trans))
err = PTR_ERR(trans);
else
btrfs_commit_transaction(trans, rc->extent_root); 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);
...@@ -4125,6 +4136,11 @@ int btrfs_recover_relocation(struct btrfs_root *root) ...@@ -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) ...@@ -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);
if (IS_ERR(trans))
err = PTR_ERR(trans);
else
btrfs_commit_transaction(trans, rc->extent_root); btrfs_commit_transaction(trans, rc->extent_root);
out: 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, ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment