Btrfs: fix easily get into ENOSPC in mixed case

When a btrfs disk is created by mixed data & metadata option, it will have no
pure data or pure metadata space info.

In btrfs's for-linus branch, commit 78b1ea13838039cd88afdd62519b40b344d6c920
(Btrfs: fix OOPS of empty filesystem after balance) initializes space infos at
the very beginning.  The problem is this initialization does not take the mixed
case into account, which will cause btrfs will easily get into ENOSPC in mixed
case.

Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
liubo 2011-04-08 08:44:37 +00:00 committed by Chris Mason
parent f5de939149
commit 1aba86d67f

View File

@ -8856,23 +8856,38 @@ out:
int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
{
struct btrfs_space_info *space_info;
struct btrfs_super_block *disk_super;
u64 features;
u64 flags;
int mixed = 0;
int ret;
ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM, 0, 0,
&space_info);
if (ret)
return ret;
disk_super = &fs_info->super_copy;
if (!btrfs_super_root(disk_super))
return 1;
ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA, 0, 0,
&space_info);
if (ret)
return ret;
features = btrfs_super_incompat_flags(disk_super);
if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
mixed = 1;
ret = update_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA, 0, 0,
&space_info);
flags = BTRFS_BLOCK_GROUP_SYSTEM;
ret = update_space_info(fs_info, flags, 0, 0, &space_info);
if (ret)
return ret;
goto out;
if (mixed) {
flags = BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA;
ret = update_space_info(fs_info, flags, 0, 0, &space_info);
} else {
flags = BTRFS_BLOCK_GROUP_METADATA;
ret = update_space_info(fs_info, flags, 0, 0, &space_info);
if (ret)
goto out;
flags = BTRFS_BLOCK_GROUP_DATA;
ret = update_space_info(fs_info, flags, 0, 0, &space_info);
}
out:
return ret;
}