Commit b321a52c authored by Boris Burkov's avatar Boris Burkov Committed by David Sterba
Browse files

btrfs: free qgroup pertrans reserve on transaction abort



If we abort a transaction, we never run the code that frees the pertrans
qgroup reservation. This results in warnings on unmount as that
reservation has been leaked. The leak isn't a huge issue since the fs is
read-only, but it's better to clean it up when we know we can/should. Do
it during the cleanup_transaction step of aborting.

CC: stable@vger.kernel.org # 5.15+
Reviewed-by: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarBoris Burkov <boris@bur.io>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 9e65bfca
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -4799,6 +4799,32 @@ void btrfs_cleanup_dirty_bgs(struct btrfs_transaction *cur_trans,
	}
}

static void btrfs_free_all_qgroup_pertrans(struct btrfs_fs_info *fs_info)
{
	struct btrfs_root *gang[8];
	int i;
	int ret;

	spin_lock(&fs_info->fs_roots_radix_lock);
	while (1) {
		ret = radix_tree_gang_lookup_tag(&fs_info->fs_roots_radix,
						 (void **)gang, 0,
						 ARRAY_SIZE(gang),
						 BTRFS_ROOT_TRANS_TAG);
		if (ret == 0)
			break;
		for (i = 0; i < ret; i++) {
			struct btrfs_root *root = gang[i];

			btrfs_qgroup_free_meta_all_pertrans(root);
			radix_tree_tag_clear(&fs_info->fs_roots_radix,
					(unsigned long)root->root_key.objectid,
					BTRFS_ROOT_TRANS_TAG);
		}
	}
	spin_unlock(&fs_info->fs_roots_radix_lock);
}

void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
				   struct btrfs_fs_info *fs_info)
{
@@ -4827,6 +4853,8 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
				     EXTENT_DIRTY);
	btrfs_destroy_pinned_extent(fs_info, &cur_trans->pinned_extents);

	btrfs_free_all_qgroup_pertrans(fs_info);

	cur_trans->state =TRANS_STATE_COMPLETED;
	wake_up(&cur_trans->commit_wait);
}
+3 −2
Original line number Diff line number Diff line
@@ -4337,6 +4337,7 @@ static void qgroup_convert_meta(struct btrfs_fs_info *fs_info, u64 ref_root,

		qgroup_rsv_release(fs_info, qgroup, num_bytes,
				BTRFS_QGROUP_RSV_META_PREALLOC);
		if (!sb_rdonly(fs_info->sb))
			qgroup_rsv_add(fs_info, qgroup, num_bytes,
				       BTRFS_QGROUP_RSV_META_PERTRANS);

+0 −2
Original line number Diff line number Diff line
@@ -37,8 +37,6 @@

static struct kmem_cache *btrfs_trans_handle_cachep;

#define BTRFS_ROOT_TRANS_TAG 0

/*
 * Transaction states and transitions
 *
+3 −0
Original line number Diff line number Diff line
@@ -12,6 +12,9 @@
#include "ctree.h"
#include "misc.h"

/* Radix-tree tag for roots that are part of the trasaction. */
#define BTRFS_ROOT_TRANS_TAG			0

enum btrfs_trans_state {
	TRANS_STATE_RUNNING,
	TRANS_STATE_COMMIT_PREP,