btrfs: free qgroup pertrans reserve on transaction abort
[ Upstream commit b321a52cce062ec7ed385333a33905d22159ce36 ] 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: Qu Wenruo <wqu@suse.com> Signed-off-by: Boris Burkov <boris@bur.io> Signed-off-by: David Sterba <dsterba@suse.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
1a80999ba3
commit
624bc6f62c
|
@ -4836,6 +4836,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)
|
||||
{
|
||||
|
@ -4864,6 +4890,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);
|
||||
}
|
||||
|
|
|
@ -4124,8 +4124,9 @@ 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);
|
||||
qgroup_rsv_add(fs_info, qgroup, num_bytes,
|
||||
BTRFS_QGROUP_RSV_META_PERTRANS);
|
||||
if (!sb_rdonly(fs_info->sb))
|
||||
qgroup_rsv_add(fs_info, qgroup, num_bytes,
|
||||
BTRFS_QGROUP_RSV_META_PERTRANS);
|
||||
|
||||
list_for_each_entry(glist, &qgroup->groups, next_group)
|
||||
qgroup_iterator_add(&qgroup_list, glist->group);
|
||||
|
|
|
@ -37,8 +37,6 @@
|
|||
|
||||
static struct kmem_cache *btrfs_trans_handle_cachep;
|
||||
|
||||
#define BTRFS_ROOT_TRANS_TAG 0
|
||||
|
||||
/*
|
||||
* Transaction states and transitions
|
||||
*
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue