Commit 51184ae3 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-5.7-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba:

 - regression fixes:
     - transaction leak when deleting unused block group
     - log cleanup after transaction abort

 - fix block group leak when removing fails

 - transaction leak if relocation recovery fails

 - fix SPDX header

* tag 'for-5.7-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix transaction leak in btrfs_recover_relocation
  btrfs: fix block group leak when removing fails
  btrfs: drop logs when we've aborted a transaction
  btrfs: fix memory leak of transaction when deleting unused block group
  btrfs: discard: Use the correct style for SPDX License Identifier
parents 869997be 1402d17d
...@@ -916,7 +916,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, ...@@ -916,7 +916,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
path = btrfs_alloc_path(); path = btrfs_alloc_path();
if (!path) { if (!path) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out_put_group;
} }
/* /*
...@@ -954,7 +954,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, ...@@ -954,7 +954,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
ret = btrfs_orphan_add(trans, BTRFS_I(inode)); ret = btrfs_orphan_add(trans, BTRFS_I(inode));
if (ret) { if (ret) {
btrfs_add_delayed_iput(inode); btrfs_add_delayed_iput(inode);
goto out; goto out_put_group;
} }
clear_nlink(inode); clear_nlink(inode);
/* One for the block groups ref */ /* One for the block groups ref */
...@@ -977,13 +977,13 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, ...@@ -977,13 +977,13 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
if (ret < 0) if (ret < 0)
goto out; goto out_put_group;
if (ret > 0) if (ret > 0)
btrfs_release_path(path); btrfs_release_path(path);
if (ret == 0) { if (ret == 0) {
ret = btrfs_del_item(trans, tree_root, path); ret = btrfs_del_item(trans, tree_root, path);
if (ret) if (ret)
goto out; goto out_put_group;
btrfs_release_path(path); btrfs_release_path(path);
} }
...@@ -1102,9 +1102,9 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, ...@@ -1102,9 +1102,9 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
ret = remove_block_group_free_space(trans, block_group); ret = remove_block_group_free_space(trans, block_group);
if (ret) if (ret)
goto out; goto out_put_group;
btrfs_put_block_group(block_group); /* Once for the block groups rbtree */
btrfs_put_block_group(block_group); btrfs_put_block_group(block_group);
ret = btrfs_search_slot(trans, root, &key, path, -1, 1); ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
...@@ -1127,6 +1127,10 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, ...@@ -1127,6 +1127,10 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
/* once for the tree */ /* once for the tree */
free_extent_map(em); free_extent_map(em);
} }
out_put_group:
/* Once for the lookup reference */
btrfs_put_block_group(block_group);
out: out:
if (remove_rsv) if (remove_rsv)
btrfs_delayed_refs_rsv_release(fs_info, 1); btrfs_delayed_refs_rsv_release(fs_info, 1);
...@@ -1288,11 +1292,15 @@ static bool clean_pinned_extents(struct btrfs_trans_handle *trans, ...@@ -1288,11 +1292,15 @@ static bool clean_pinned_extents(struct btrfs_trans_handle *trans,
if (ret) if (ret)
goto err; goto err;
mutex_unlock(&fs_info->unused_bg_unpin_mutex); mutex_unlock(&fs_info->unused_bg_unpin_mutex);
if (prev_trans)
btrfs_put_transaction(prev_trans);
return true; return true;
err: err:
mutex_unlock(&fs_info->unused_bg_unpin_mutex); mutex_unlock(&fs_info->unused_bg_unpin_mutex);
if (prev_trans)
btrfs_put_transaction(prev_trans);
btrfs_dec_block_group_ro(bg); btrfs_dec_block_group_ro(bg);
return false; return false;
} }
......
// SPDX-License-Identifier: GPL-2.0 /* SPDX-License-Identifier: GPL-2.0 */
#ifndef BTRFS_DISCARD_H #ifndef BTRFS_DISCARD_H
#define BTRFS_DISCARD_H #define BTRFS_DISCARD_H
......
...@@ -2036,9 +2036,6 @@ void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info) ...@@ -2036,9 +2036,6 @@ void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info)
for (i = 0; i < ret; i++) for (i = 0; i < ret; i++)
btrfs_drop_and_free_fs_root(fs_info, gang[i]); btrfs_drop_and_free_fs_root(fs_info, gang[i]);
} }
if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state))
btrfs_free_log_root_tree(NULL, fs_info);
} }
static void btrfs_init_scrub(struct btrfs_fs_info *fs_info) static void btrfs_init_scrub(struct btrfs_fs_info *fs_info)
...@@ -3888,7 +3885,7 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info, ...@@ -3888,7 +3885,7 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
spin_unlock(&fs_info->fs_roots_radix_lock); spin_unlock(&fs_info->fs_roots_radix_lock);
if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) { if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
btrfs_free_log(NULL, root); ASSERT(root->log_root == NULL);
if (root->reloc_root) { if (root->reloc_root) {
btrfs_put_root(root->reloc_root); btrfs_put_root(root->reloc_root);
root->reloc_root = NULL; root->reloc_root = NULL;
...@@ -4211,6 +4208,36 @@ static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info) ...@@ -4211,6 +4208,36 @@ static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info)
up_write(&fs_info->cleanup_work_sem); up_write(&fs_info->cleanup_work_sem);
} }
static void btrfs_drop_all_logs(struct btrfs_fs_info *fs_info)
{
struct btrfs_root *gang[8];
u64 root_objectid = 0;
int ret;
spin_lock(&fs_info->fs_roots_radix_lock);
while ((ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix,
(void **)gang, root_objectid,
ARRAY_SIZE(gang))) != 0) {
int i;
for (i = 0; i < ret; i++)
gang[i] = btrfs_grab_root(gang[i]);
spin_unlock(&fs_info->fs_roots_radix_lock);
for (i = 0; i < ret; i++) {
if (!gang[i])
continue;
root_objectid = gang[i]->root_key.objectid;
btrfs_free_log(NULL, gang[i]);
btrfs_put_root(gang[i]);
}
root_objectid++;
spin_lock(&fs_info->fs_roots_radix_lock);
}
spin_unlock(&fs_info->fs_roots_radix_lock);
btrfs_free_log_root_tree(NULL, fs_info);
}
static void btrfs_destroy_ordered_extents(struct btrfs_root *root) static void btrfs_destroy_ordered_extents(struct btrfs_root *root)
{ {
struct btrfs_ordered_extent *ordered; struct btrfs_ordered_extent *ordered;
...@@ -4603,6 +4630,7 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info) ...@@ -4603,6 +4630,7 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info)
btrfs_destroy_delayed_inodes(fs_info); btrfs_destroy_delayed_inodes(fs_info);
btrfs_assert_delayed_root_empty(fs_info); btrfs_assert_delayed_root_empty(fs_info);
btrfs_destroy_all_delalloc_inodes(fs_info); btrfs_destroy_all_delalloc_inodes(fs_info);
btrfs_drop_all_logs(fs_info);
mutex_unlock(&fs_info->transaction_kthread_mutex); mutex_unlock(&fs_info->transaction_kthread_mutex);
return 0; return 0;
......
...@@ -4559,6 +4559,7 @@ int btrfs_recover_relocation(struct btrfs_root *root) ...@@ -4559,6 +4559,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
if (IS_ERR(fs_root)) { if (IS_ERR(fs_root)) {
err = PTR_ERR(fs_root); err = PTR_ERR(fs_root);
list_add_tail(&reloc_root->root_list, &reloc_roots); list_add_tail(&reloc_root->root_list, &reloc_roots);
btrfs_end_transaction(trans);
goto out_unset; goto out_unset;
} }
......
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