Commit 51184ae3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -916,7 +916,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
	path = btrfs_alloc_path();
	if (!path) {
		ret = -ENOMEM;
		goto out;
		goto out_put_group;
	}

	/*
@@ -954,7 +954,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
		ret = btrfs_orphan_add(trans, BTRFS_I(inode));
		if (ret) {
			btrfs_add_delayed_iput(inode);
			goto out;
			goto out_put_group;
		}
		clear_nlink(inode);
		/* One for the block groups ref */
@@ -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);
	if (ret < 0)
		goto out;
		goto out_put_group;
	if (ret > 0)
		btrfs_release_path(path);
	if (ret == 0) {
		ret = btrfs_del_item(trans, tree_root, path);
		if (ret)
			goto out;
			goto out_put_group;
		btrfs_release_path(path);
	}

@@ -1102,9 +1102,9 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,

	ret = remove_block_group_free_space(trans, block_group);
	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);

	ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
@@ -1127,6 +1127,10 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
		/* once for the tree */
		free_extent_map(em);
	}

out_put_group:
	/* Once for the lookup reference */
	btrfs_put_block_group(block_group);
out:
	if (remove_rsv)
		btrfs_delayed_refs_rsv_release(fs_info, 1);
@@ -1288,11 +1292,15 @@ static bool clean_pinned_extents(struct btrfs_trans_handle *trans,
	if (ret)
		goto err;
	mutex_unlock(&fs_info->unused_bg_unpin_mutex);
	if (prev_trans)
		btrfs_put_transaction(prev_trans);

	return true;

err:
	mutex_unlock(&fs_info->unused_bg_unpin_mutex);
	if (prev_trans)
		btrfs_put_transaction(prev_trans);
	btrfs_dec_block_group_ro(bg);
	return false;
}
+1 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */

#ifndef BTRFS_DISCARD_H
#define BTRFS_DISCARD_H
+32 −4
Original line number Diff line number Diff line
@@ -2036,9 +2036,6 @@ void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info)
		for (i = 0; i < ret; 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)
@@ -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);

	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) {
			btrfs_put_root(root->reloc_root);
			root->reloc_root = NULL;
@@ -4211,6 +4208,36 @@ static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info)
	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)
{
	struct btrfs_ordered_extent *ordered;
@@ -4603,6 +4630,7 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info)
	btrfs_destroy_delayed_inodes(fs_info);
	btrfs_assert_delayed_root_empty(fs_info);
	btrfs_destroy_all_delalloc_inodes(fs_info);
	btrfs_drop_all_logs(fs_info);
	mutex_unlock(&fs_info->transaction_kthread_mutex);

	return 0;
+1 −0
Original line number Diff line number Diff line
@@ -4559,6 +4559,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
		if (IS_ERR(fs_root)) {
			err = PTR_ERR(fs_root);
			list_add_tail(&reloc_root->root_list, &reloc_roots);
			btrfs_end_transaction(trans);
			goto out_unset;
		}