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

Commit 49303381 authored by Liu Bo's avatar Liu Bo Committed by David Sterba
Browse files

Btrfs: bail out if block group has different mixed flag



Currently we allow inconsistence about mixed flag
 (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA).

We'd get ENOSPC if block group has mixed flag and btrfs doesn't.
If that happens, we have one space_info with mixed flag and another
space_info only with BTRFS_BLOCK_GROUP_METADATA, and
global_block_rsv.space_info points to the latter one, but all bytes
from block_group contributes to the mixed space_info, thus all the
allocation will fail with ENOSPC.

This adds a check for the above case.

Reported-by: default avatarVegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: default avatarLiu Bo <bo.li.liu@oracle.com>
[ updated message ]
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 2571e739
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -10129,6 +10129,11 @@ int btrfs_read_block_groups(struct btrfs_root *root)
	struct extent_buffer *leaf;
	int need_clear = 0;
	u64 cache_gen;
	u64 feature;
	int mixed;

	feature = btrfs_super_incompat_flags(info->super_copy);
	mixed = !!(feature & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS);

	root = info->extent_root;
	key.objectid = 0;
@@ -10182,6 +10187,15 @@ int btrfs_read_block_groups(struct btrfs_root *root)
				   btrfs_item_ptr_offset(leaf, path->slots[0]),
				   sizeof(cache->item));
		cache->flags = btrfs_block_group_flags(&cache->item);
		if (!mixed &&
		    ((cache->flags & BTRFS_BLOCK_GROUP_METADATA) &&
		    (cache->flags & BTRFS_BLOCK_GROUP_DATA))) {
			btrfs_err(info,
"bg %llu is a mixed block group but filesystem hasn't enabled mixed block groups",
				  cache->key.objectid);
			ret = -EINVAL;
			goto error;
		}

		key.objectid = found_key.objectid + found_key.offset;
		btrfs_release_path(path);