diff options
author | David Sterba <dsterba@suse.com> | 2016-05-16 15:46:23 +0200 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-05-16 15:46:23 +0200 |
commit | 73d32ce21e1701eaafcea3cbc2a8f27ab1967abe (patch) | |
tree | 136c03e4be575e4466ef9df119b8debdf768a56a /fs/btrfs/super.c | |
parent | 02da2d72174c61988eb4456b53f405e3ebdebce4 (diff) | |
parent | 4673272f43ae790ab9ec04e38a7542f82bb8f020 (diff) |
Merge branch 'misc-4.7' into for-chris-4.7-20160516
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 00b8f37cc306..fe03efb5bec0 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -2051,6 +2051,7 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; int ret; u64 thresh = 0; + int mixed = 0; /* * holding chunk_muext to avoid allocating new chunks, holding @@ -2076,8 +2077,17 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) } } } - if (found->flags & BTRFS_BLOCK_GROUP_METADATA) - total_free_meta += found->disk_total - found->disk_used; + + /* + * Metadata in mixed block goup profiles are accounted in data + */ + if (!mixed && found->flags & BTRFS_BLOCK_GROUP_METADATA) { + if (found->flags & BTRFS_BLOCK_GROUP_DATA) + mixed = 1; + else + total_free_meta += found->disk_total - + found->disk_used; + } total_used += found->disk_used; } @@ -2090,7 +2100,11 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) /* Account global block reserve as used, it's in logical size already */ spin_lock(&block_rsv->lock); - buf->f_bfree -= block_rsv->size >> bits; + /* Mixed block groups accounting is not byte-accurate, avoid overflow */ + if (buf->f_bfree >= block_rsv->size >> bits) + buf->f_bfree -= block_rsv->size >> bits; + else + buf->f_bfree = 0; spin_unlock(&block_rsv->lock); buf->f_bavail = div_u64(total_free_data, factor); @@ -2115,7 +2129,7 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) */ thresh = 4 * 1024 * 1024; - if (total_free_meta - thresh < block_rsv->size) + if (!mixed && total_free_meta - thresh < block_rsv->size) buf->f_bavail = 0; buf->f_type = BTRFS_SUPER_MAGIC; |