diff mbox

Btrfs: fix easily get into ENOSPC in mixed case

Message ID 4D9ECAF5.50108@cn.fujitsu.com (mailing list archive)
State New, archived
Headers show

Commit Message

liubo April 8, 2011, 8:44 a.m. UTC
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>
---
 fs/btrfs/extent-tree.c |   37 ++++++++++++++++++++++++++-----------
 1 files changed, 26 insertions(+), 11 deletions(-)

Comments

Sergei Trofimovich April 8, 2011, 9:09 p.m. UTC | #1
On Fri, 08 Apr 2011 16:44:37 +0800
liubo <liubo2009@cn.fujitsu.com> wrote:

> 
> 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>
> ---

Tried to apply this patch on top of 2.6.39-rc2 and booted on the same partition.
It has 3.2 GBs free. With patch it started to report -ENOSPC right out.
Attempt to delete some files caused OOps:

[  220.784098] ------------[ cut here ]------------
[  220.784416] kernel BUG at /mnt/archive/src/linux-2.6/fs/btrfs/inode.c:2962!
[  220.784700] invalid opcode: 0000 [#1] PREEMPT SMP 
[  220.784969] last sysfs file: /sys/devices/virtual/bdi/0:26/uevent
[  220.785011] CPU 0 
[  220.785011] Modules linked in: bridge stp llc btrfs zlib_deflate lzo_decompress lzo_compress crc32c libcrc32c tun kvm_amd kvm fuse nouveau ttm drm_kms_helper drm i2c_algo_bit i2c_core cfbcopyarea cfbimgblt 8139cp cfbfillrect 8139too forcedeth
[  220.785011] 
[  220.785011] Pid: 2881, comm: mc Not tainted 2.6.39-rc2+ #2 To Be Filled By O.E.M. To Be Filled By O.E.M./ALiveNF6G-VSTA
[  220.785011] RIP: 0010:[<ffffffffa024a141>]  [<ffffffffa024a141>] btrfs_unlink+0xd1/0xe0 [btrfs]
[  220.785011] RSP: 0018:ffff88006898fe28  EFLAGS: 00010286
[  220.785011] RAX: 00000000ffffffe4 RBX: 00000000ffffffe4 RCX: 0000000000006d32
[  220.785011] RDX: 0000000000006d30 RSI: 00000000000196d0 RDI: ffffea0001a3d2b8
[  220.785011] RBP: ffff88006898fe58 R08: ffffffffa021e02a R09: ffff88006898fb48
[  220.785011] R10: ffffffffffffffe4 R11: 0000000000000001 R12: ffff88005b5e2540
[  220.785011] R13: ffff88005b668040 R14: ffff880077344800 R15: ffff88005b674578
[  220.785011] FS:  00007f8587265700(0000) GS:ffff88007bc00000(0000) knlGS:0000000000000000
[  220.785011] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[  220.785011] CR2: 00007f8587277000 CR3: 0000000068a29000 CR4: 00000000000006f0
[  220.785011] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  220.785011] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[  220.785011] Process mc (pid: 2881, threadinfo ffff88006898e000, task ffff880070a64230)
[  220.785011] Stack:
[  220.785011]  ffff88006898fe48 00000000fffffff0 ffff88005b5e2540 ffff88005b674198
[  220.785011]  0000000000000000 00007fff6ee8d6b0 ffff88006898fe88 ffffffff810ed420
[  220.785011]  ffff88006898fe88 ffff88006898fe98 ffff88005b5e2540 ffff88005b674578
[  220.785011] Call Trace:
[  220.785011]  [<ffffffff810ed420>] vfs_unlink+0x80/0xf0
[  220.785011]  [<ffffffff810ef773>] do_unlinkat+0x173/0x1b0
[  220.785011]  [<ffffffff81051a88>] ? sys_rt_sigaction+0x68/0xc0
[  220.785011]  [<ffffffff810f0cc1>] sys_unlink+0x11/0x20
[  220.785011]  [<ffffffff81574bbb>] system_call_fastpath+0x16/0x1b
[  220.785011] Code: 4c 8b 65 e0 48 8b 5d d8 4c 8b 6d e8 4c 8b 75 f0 4c 8b 7d f8 c9 c3 0f 1f 40 00 4c 89 fe 4c 89 ef e8 25 d0 ff ff 85 c0 74 bb 0f 0b <0f> 0b 89 c3 eb cd 66 0f 1f 84 00 00 00 00 00 55 48 89 e5 41 57 
[  220.785011] RIP  [<ffffffffa024a141>] btrfs_unlink+0xd1/0xe0 [btrfs]
[  220.785011]  RSP <ffff88006898fe28>
[  220.809847] ---[ end trace ca8cb79df9da2e2a ]---
Sergei Trofimovich April 8, 2011, 9:19 p.m. UTC | #2
> > 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>
> > ---
> 
> Tried to apply this patch on top of 2.6.39-rc2 and booted on the same partition.
> It has 3.2 GBs free. With patch it started to report -ENOSPC right out.
> Attempt to delete some files caused OOps:

Sorry, I was too fast. The same OOps is reproducible on vanilla 2.6.39-rc2. Will retest on 2.6.39-rc1.
Sergei Trofimovich April 8, 2011, 9:55 p.m. UTC | #3
> > > 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>
> > > ---

> Sorry, I was too fast. The same OOps is reproducible on vanilla 2.6.39-rc2. Will retest on 2.6.39-rc1.

2.6.39-rc1 (no patch):

[  155.038094] ------------[ cut here ]------------
[  155.038388] kernel BUG at /mnt/archive/src/linux-2.6/fs/btrfs/inode.c:2967!
[  155.038643] invalid opcode: 0000 [#1] PREEMPT SMP 
[  155.038907] last sysfs file: /sys/devices/virtual/bdi/0:26/uevent
[  155.039011] CPU 0 
[  155.039011] Modules linked in: bridge stp llc btrfs zlib_deflate lzo_decompress lzo_compress crc32c libcrc32c tun kvm_amd kvm fuse nouveau ttm 8139cp drm_kms_helper drm i2c_algo_bit i2c_core cfbcopyarea cfbimgblt cfbfillrect 8139too forcedeth
[  155.039011] 
[  155.039011] Pid: 2620, comm: rm Not tainted 2.6.39-rc1 #3 To Be Filled By O.E.M. To Be Filled By O.E.M./ALiveNF6G-VSTA
[  155.039011] RIP: 0010:[<ffffffffa0249fd1>]  [<ffffffffa0249fd1>] btrfs_unlink+0xd1/0xe0 [btrfs]
[  155.039011] RSP: 0018:ffff880073687e28  EFLAGS: 00010286
[  155.039011] RAX: 00000000ffffffe4 RBX: 00000000ffffffe4 RCX: 00000000000000e0
[  155.039011] RDX: 00000000000000de RSI: 00000000000196d0 RDI: ffffea0001a3d980
[  155.039011] RBP: ffff880073687e58 R08: ffffffffa021df4a R09: ffff880073687b48
[  155.039011] R10: ffffffffffffffe4 R11: 0000000000000001 R12: ffff8800756eab40
[  155.039011] R13: ffff8800756eb000 R14: ffff880075e8e800 R15: ffff880077f7e858
[  155.039011] FS:  00007f99bdd9c700(0000) GS:ffff88007bc00000(0000) knlGS:0000000000000000
[  155.039011] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[  155.039011] CR2: 00007f99be7480a8 CR3: 0000000073610000 CR4: 00000000000006f0
[  155.039011] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  155.039011] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[  155.039011] Process rm (pid: 2620, threadinfo ffff880073686000, task ffff8800730cc230)
[  155.039011] Stack:
[  155.039011]  ffff880073687e48 00000000fffffff0 ffff8800756eab40 ffff880077f7e478
[  155.039011]  0000000000000000 0000000000000000 ffff880073687e88 ffffffff810ed3a0
[  155.039011]  ffff880073687e88 ffff880073687e98 ffff8800756eab40 ffff880077f7e858
[  155.039011] Call Trace:
[  155.039011]  [<ffffffff810ed3a0>] vfs_unlink+0x80/0xf0
[  155.039011]  [<ffffffff810ef6f3>] do_unlinkat+0x173/0x1b0
[  155.039011]  [<ffffffff8111727b>] ? fsnotify_find_inode_mark+0x3b/0x50
[  155.039011]  [<ffffffff810dff91>] ? filp_close+0x61/0x90
[  155.039011]  [<ffffffff810f0c0d>] sys_unlinkat+0x1d/0x40
[  155.039011]  [<ffffffff81574c3b>] system_call_fastpath+0x16/0x1b
[  155.039011] Code: 4c 8b 65 e0 48 8b 5d d8 4c 8b 6d e8 4c 8b 75 f0 4c 8b 7d f8 c9 c3 0f 1f 40 00 4c 89 fe 4c 89 ef e8 05 d0 ff ff 85 c0 74 bb 0f 0b <0f> 0b 89 c3 eb cd 66 0f 1f 84 00 00 00 00 00 55 48 89 e5 41 57 
[  155.039011] RIP  [<ffffffffa0249fd1>] btrfs_unlink+0xd1/0xe0 [btrfs]
[  155.039011]  RSP <ffff880073687e28>
[  155.064611] ---[ end trace 47dc7dae76c74a2a ]---

2.6.39-rc1 (+patch):
[  100.499105] ------------[ cut here ]------------
[  100.499405] kernel BUG at /mnt/archive/src/linux-2.6/fs/btrfs/inode.c:2967!
[  100.499686] invalid opcode: 0000 [#1] PREEMPT SMP 
[  100.499948] last sysfs file: /sys/devices/virtual/bdi/0:26/uevent
[  100.500011] CPU 1 
[  100.500011] Modules linked in: bridge stp llc btrfs zlib_deflate lzo_decompress lzo_compress crc32c libcrc32c tun kvm_amd kvm fuse nouveau ttm drm_kms_helper drm i2c_algo_bit i2c_core cfbcopyarea cfbimgblt cfbfillrect forcedeth 8139cp 8139too
[  100.500011] 
[  100.500011] Pid: 2447, comm: rm Not tainted 2.6.39-rc1+ #4 To Be Filled By O.E.M. To Be Filled By O.E.M./ALiveNF6G-VSTA
[  100.500011] RIP: 0010:[<ffffffffa024a011>]  [<ffffffffa024a011>] btrfs_unlink+0xd1/0xe0 [btrfs]
[  100.500011] RSP: 0018:ffff880070b55e28  EFLAGS: 00010286
[  100.500011] RAX: 00000000ffffffe4 RBX: 00000000ffffffe4 RCX: 0000000000000013
[  100.500011] RDX: 0000000000000011 RSI: 00000000000196d0 RDI: ffffea00019aef80
[  100.500011] RBP: ffff880070b55e58 R08: ffffffffa021df4a R09: ffff880070b55b48
[  100.500011] R10: ffffffffffffffe4 R11: 0000000000000001 R12: ffff8800756a0c00
[  100.500011] R13: ffff880075692000 R14: ffff880075e3c800 R15: ffff880077f5e478
[  100.500011] FS:  00007f01e95c5700(0000) GS:ffff88007bd00000(0000) knlGS:0000000000000000
[  100.500011] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[  100.500011] CR2: 00007fd0687a8ec4 CR3: 0000000070b29000 CR4: 00000000000006e0
[  100.500011] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  100.500011] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[  100.500011] Process rm (pid: 2447, threadinfo ffff880070b54000, task ffff8800709cc230)
[  100.500011] Stack:
[  100.500011]  ffff880070b55e48 00000000fffffff0 ffff8800756a0c00 ffff880077f5e098
[  100.500011]  0000000000000000 0000000000000000 ffff880070b55e88 ffffffff810ed3a0
[  100.500011]  ffff880070b55e88 ffff880070b55e98 ffff8800756a0c00 ffff880077f5e478
[  100.500011] Call Trace:
[  100.500011]  [<ffffffff810ed3a0>] vfs_unlink+0x80/0xf0
[  100.500011]  [<ffffffff810ef6f3>] do_unlinkat+0x173/0x1b0
[  100.500011]  [<ffffffff8111727b>] ? fsnotify_find_inode_mark+0x3b/0x50
[  100.500011]  [<ffffffff810dff91>] ? filp_close+0x61/0x90
[  100.500011]  [<ffffffff810f0c0d>] sys_unlinkat+0x1d/0x40
[  100.500011]  [<ffffffff81574c3b>] system_call_fastpath+0x16/0x1b
[  100.500011] Code: 4c 8b 65 e0 48 8b 5d d8 4c 8b 6d e8 4c 8b 75 f0 4c 8b 7d f8 c9 c3 0f 1f 40 00 4c 89 fe 4c 89 ef e8 05 d0 ff ff 85 c0 74 bb 0f 0b <0f> 0b 89 c3 eb cd 66 0f 1f 84 00 00 00 00 00 55 48 89 e5 41 57 
[  100.500011] RIP  [<ffffffffa024a011>] btrfs_unlink+0xd1/0xe0 [btrfs]
[  100.500011]  RSP <ffff880070b55e28>
[  100.525672] ---[ end trace 7e63b9144b7307fe ]---

Looks like I won't be able to test your patch until this thing will go away first.
liubo April 11, 2011, 6:29 a.m. UTC | #4
On 04/09/2011 05:55 AM, Sergei Trofimovich wrote:
> [  100.500011] Call Trace:
> [  100.500011]  [<ffffffff810ed3a0>] vfs_unlink+0x80/0xf0
> [  100.500011]  [<ffffffff810ef6f3>] do_unlinkat+0x173/0x1b0
> [  100.500011]  [<ffffffff8111727b>] ? fsnotify_find_inode_mark+0x3b/0x50
> [  100.500011]  [<ffffffff810dff91>] ? filp_close+0x61/0x90
> [  100.500011]  [<ffffffff810f0c0d>] sys_unlinkat+0x1d/0x40
> [  100.500011]  [<ffffffff81574c3b>] system_call_fastpath+0x16/0x1b
> [  100.500011] Code: 4c 8b 65 e0 48 8b 5d d8 4c 8b 6d e8 4c 8b 75 f0 4c 8b 7d f8 c9 c3 0f 1f 40 00 4c 89 fe 4c 89 ef e8 05 d0 ff ff 85 c0 74 bb 0f 0b <0f> 0b 89 c3 eb cd 66 0f 1f 84 00 00 00 00 00 55 48 89 e5 41 57 
> [  100.500011] RIP  [<ffffffffa024a011>] btrfs_unlink+0xd1/0xe0 [btrfs]
> [  100.500011]  RSP <ffff880070b55e28>
> [  100.525672] ---[ end trace 7e63b9144b7307fe ]---
> 
> Looks like I won't be able to test your patch until this thing will go away first.

Thanks a lot for testing, though.

I guess something messed up your btrfs metadata, cause when btrfs_unlink() wanted to remove A,
it found that A was just missing...

thanks,
liubo
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sergei Trofimovich April 11, 2011, 8:27 p.m. UTC | #5
On Mon, 11 Apr 2011 14:29:21 +0800
liubo <liubo2009@cn.fujitsu.com> wrote:

> On 04/09/2011 05:55 AM, Sergei Trofimovich wrote:
> > [  100.500011] Call Trace:
> > [  100.500011]  [<ffffffff810ed3a0>] vfs_unlink+0x80/0xf0
> > [  100.500011]  [<ffffffff810ef6f3>] do_unlinkat+0x173/0x1b0
> > [  100.500011]  [<ffffffff8111727b>] ? fsnotify_find_inode_mark+0x3b/0x50
> > [  100.500011]  [<ffffffff810dff91>] ? filp_close+0x61/0x90
> > [  100.500011]  [<ffffffff810f0c0d>] sys_unlinkat+0x1d/0x40
> > [  100.500011]  [<ffffffff81574c3b>] system_call_fastpath+0x16/0x1b
> > [  100.500011] Code: 4c 8b 65 e0 48 8b 5d d8 4c 8b 6d e8 4c 8b 75 f0 4c 8b 7d f8 c9 c3 0f 1f 40 00 4c 89 fe 4c 89 ef e8 05 d0 ff ff 85 c0 74 bb 0f 0b <0f> 0b 89 c3 eb cd 66 0f 1f 84 00 00 00 00 00 55 48 89 e5 41 57 
> > [  100.500011] RIP  [<ffffffffa024a011>] btrfs_unlink+0xd1/0xe0 [btrfs]
> > [  100.500011]  RSP <ffff880070b55e28>
> > [  100.525672] ---[ end trace 7e63b9144b7307fe ]---
> > 
> > Looks like I won't be able to test your patch until this thing will go away first.
> 
> Thanks a lot for testing, though.
> 
> I guess something messed up your btrfs metadata, cause when btrfs_unlink() wanted to remove A,
> it found that A was just missing...
Looks like it's ret = -28 (a ENOSPC). Yes, you are right. Moreover, as Arne found out,
I used wrong patch for btrfs-progs to create --mixed filesystems. I set wrong bit in
superblock (the 8ULL << 0, not 4ULL << 0) - the COMPRESS_LZO, so my metadata is
really screwed.

Please, disregard all my OOpses reported against --mixed FS. Sorry.
Sergei Trofimovich May 5, 2011, 2:44 p.m. UTC | #6
On Fri, 08 Apr 2011 16:44:37 +0800
liubo <liubo2009@cn.fujitsu.com> wrote:

> 
> 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>

Hi Chris!

I confirm it fixes OOpses for me.
Some clarification of what happened down the thread with me in order to convince
this patch actually makes things better.

1. The initial OOps reported by me was a result of using bad mkfs (not interesting,
    but generated a lot of noise here)

2. Then I've patched mkfs properly (used tmp branch), reformatted my partitions and
    caught -ENOSPC on 'rm -rf /var/tmp/' (vanilla kernel), added debugging info and have come to the
    conclusion: this patch helps in this situation, as free space was completely miscomputed
    (it's a regression since 2.6.38). I've applied it and things _mostly_ (see 3.) solved (--mixed
    ~4G lzo filesystem) for me

3. Then I've caught more -ENOSPC oopses, which occured to be a bug in mkfs for which Arne posted
    a fix today, see his email:
        [PATCH] btrfs progs: fix extra metadata chunk allocation in --mixed case

    Arne's mkfs patch (or btrfs fi balance workaround) fixed rest of OOpses for me.

So, my thoughts:
    - this patch is quite critical for --mixed filesystems
    - it (or it's equivalent) should be considered for pulling-in to .39 kernel (ideally), as it's a regression since 2.6.38

Thanks!

> ---
>  fs/btrfs/extent-tree.c |   37 ++++++++++++++++++++++++++-----------
>  1 files changed, 26 insertions(+), 11 deletions(-)
> 
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index f619c3c..1b47ae4 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -8781,23 +8781,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;
>  }
>  
> -- 
> 1.6.5.2
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f619c3c..1b47ae4 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -8781,23 +8781,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;
 }