Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a5b7f429 authored by Lu Fengqi's avatar Lu Fengqi Committed by David Sterba
Browse files

btrfs: fix qgroup_free wrong num_bytes in btrfs_subvolume_reserve_metadata



After btrfs_qgroup_reserve_meta_prealloc(), num_bytes will be assigned
again by btrfs_calc_trans_metadata_size(). Once block_rsv fails, we
can't properly free the num_bytes of the previous qgroup_reserve. Use a
separate variable to store the num_bytes of the qgroup_reserve.

Delete the comment for the qgroup_reserved that does not exist and add a
comment about use_global_rsv.

Fixes: c4c129db ("btrfs: drop unused parameter qgroup_reserved")
CC: stable@vger.kernel.org # 4.18+
Signed-off-by: default avatarLu Fengqi <lufq.fnst@cn.fujitsu.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent de02b9f6
Loading
Loading
Loading
Loading
+8 −9
Original line number Diff line number Diff line
@@ -5800,7 +5800,7 @@ void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans)
 * root: the root of the parent directory
 * rsv: block reservation
 * items: the number of items that we need do reservation
 * qgroup_reserved: used to return the reserved size in qgroup
 * use_global_rsv: allow fallback to the global block reservation
 *
 * This function is used to reserve the space for snapshot/subvolume
 * creation and deletion. Those operations are different with the
@@ -5810,10 +5810,10 @@ void btrfs_trans_release_chunk_metadata(struct btrfs_trans_handle *trans)
 * the space reservation mechanism in start_transaction().
 */
int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
				     struct btrfs_block_rsv *rsv,
				     int items,
				     struct btrfs_block_rsv *rsv, int items,
				     bool use_global_rsv)
{
	u64 qgroup_num_bytes = 0;
	u64 num_bytes;
	int ret;
	struct btrfs_fs_info *fs_info = root->fs_info;
@@ -5821,12 +5821,11 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,

	if (test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags)) {
		/* One for parent inode, two for dir entries */
		num_bytes = 3 * fs_info->nodesize;
		ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true);
		qgroup_num_bytes = 3 * fs_info->nodesize;
		ret = btrfs_qgroup_reserve_meta_prealloc(root,
				qgroup_num_bytes, true);
		if (ret)
			return ret;
	} else {
		num_bytes = 0;
	}

	num_bytes = btrfs_calc_trans_metadata_size(fs_info, items);
@@ -5838,8 +5837,8 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
	if (ret == -ENOSPC && use_global_rsv)
		ret = btrfs_block_rsv_migrate(global_rsv, rsv, num_bytes, 1);

	if (ret && num_bytes)
		btrfs_qgroup_free_meta_prealloc(root, num_bytes);
	if (ret && qgroup_num_bytes)
		btrfs_qgroup_free_meta_prealloc(root, qgroup_num_bytes);

	return ret;
}