diff options
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 67b48b9a03e0..c4124de4435b 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1665,6 +1665,21 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) | |||
1665 | return 0; | 1665 | return 0; |
1666 | } | 1666 | } |
1667 | 1667 | ||
1668 | /* | ||
1669 | * Calculate numbers for 'df', pessimistic in case of mixed raid profiles. | ||
1670 | * | ||
1671 | * If there's a redundant raid level at DATA block groups, use the respective | ||
1672 | * multiplier to scale the sizes. | ||
1673 | * | ||
1674 | * Unused device space usage is based on simulating the chunk allocator | ||
1675 | * algorithm that respects the device sizes, order of allocations and the | ||
1676 | * 'alloc_start' value, this is a close approximation of the actual use but | ||
1677 | * there are other factors that may change the result (like a new metadata | ||
1678 | * chunk). | ||
1679 | * | ||
1680 | * FIXME: not accurate for mixed block groups, total and free/used are ok, | ||
1681 | * available appears slightly larger. | ||
1682 | */ | ||
1668 | static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 1683 | static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
1669 | { | 1684 | { |
1670 | struct btrfs_fs_info *fs_info = btrfs_sb(dentry->d_sb); | 1685 | struct btrfs_fs_info *fs_info = btrfs_sb(dentry->d_sb); |
@@ -1675,6 +1690,8 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
1675 | u64 total_free_data = 0; | 1690 | u64 total_free_data = 0; |
1676 | int bits = dentry->d_sb->s_blocksize_bits; | 1691 | int bits = dentry->d_sb->s_blocksize_bits; |
1677 | __be32 *fsid = (__be32 *)fs_info->fsid; | 1692 | __be32 *fsid = (__be32 *)fs_info->fsid; |
1693 | unsigned factor = 1; | ||
1694 | struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; | ||
1678 | int ret; | 1695 | int ret; |
1679 | 1696 | ||
1680 | /* holding chunk_muext to avoid allocating new chunks */ | 1697 | /* holding chunk_muext to avoid allocating new chunks */ |
@@ -1682,30 +1699,52 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
1682 | rcu_read_lock(); | 1699 | rcu_read_lock(); |
1683 | list_for_each_entry_rcu(found, head, list) { | 1700 | list_for_each_entry_rcu(found, head, list) { |
1684 | if (found->flags & BTRFS_BLOCK_GROUP_DATA) { | 1701 | if (found->flags & BTRFS_BLOCK_GROUP_DATA) { |
1702 | int i; | ||
1703 | |||
1685 | total_free_data += found->disk_total - found->disk_used; | 1704 | total_free_data += found->disk_total - found->disk_used; |
1686 | total_free_data -= | 1705 | total_free_data -= |
1687 | btrfs_account_ro_block_groups_free_space(found); | 1706 | btrfs_account_ro_block_groups_free_space(found); |
1707 | |||
1708 | for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { | ||
1709 | if (!list_empty(&found->block_groups[i])) { | ||
1710 | switch (i) { | ||
1711 | case BTRFS_RAID_DUP: | ||
1712 | case BTRFS_RAID_RAID1: | ||
1713 | case BTRFS_RAID_RAID10: | ||
1714 | factor = 2; | ||
1715 | } | ||
1716 | } | ||
1717 | } | ||
1688 | } | 1718 | } |
1689 | 1719 | ||
1690 | total_used += found->disk_used; | 1720 | total_used += found->disk_used; |
1691 | } | 1721 | } |
1722 | |||
1692 | rcu_read_unlock(); | 1723 | rcu_read_unlock(); |
1693 | 1724 | ||
1694 | buf->f_namelen = BTRFS_NAME_LEN; | 1725 | buf->f_blocks = div_u64(btrfs_super_total_bytes(disk_super), factor); |
1695 | buf->f_blocks = btrfs_super_total_bytes(disk_super) >> bits; | 1726 | buf->f_blocks >>= bits; |
1696 | buf->f_bfree = buf->f_blocks - (total_used >> bits); | 1727 | buf->f_bfree = buf->f_blocks - (div_u64(total_used, factor) >> bits); |
1697 | buf->f_bsize = dentry->d_sb->s_blocksize; | 1728 | |
1698 | buf->f_type = BTRFS_SUPER_MAGIC; | 1729 | /* Account global block reserve as used, it's in logical size already */ |
1730 | spin_lock(&block_rsv->lock); | ||
1731 | buf->f_bfree -= block_rsv->size >> bits; | ||
1732 | spin_unlock(&block_rsv->lock); | ||
1733 | |||
1699 | buf->f_bavail = total_free_data; | 1734 | buf->f_bavail = total_free_data; |
1700 | ret = btrfs_calc_avail_data_space(fs_info->tree_root, &total_free_data); | 1735 | ret = btrfs_calc_avail_data_space(fs_info->tree_root, &total_free_data); |
1701 | if (ret) { | 1736 | if (ret) { |
1702 | mutex_unlock(&fs_info->chunk_mutex); | 1737 | mutex_unlock(&fs_info->chunk_mutex); |
1703 | return ret; | 1738 | return ret; |
1704 | } | 1739 | } |
1705 | buf->f_bavail += total_free_data; | 1740 | buf->f_bavail += div_u64(total_free_data, factor); |
1706 | buf->f_bavail = buf->f_bavail >> bits; | 1741 | buf->f_bavail = buf->f_bavail >> bits; |
1707 | mutex_unlock(&fs_info->chunk_mutex); | 1742 | mutex_unlock(&fs_info->chunk_mutex); |
1708 | 1743 | ||
1744 | buf->f_type = BTRFS_SUPER_MAGIC; | ||
1745 | buf->f_bsize = dentry->d_sb->s_blocksize; | ||
1746 | buf->f_namelen = BTRFS_NAME_LEN; | ||
1747 | |||
1709 | /* We treat it as constant endianness (it doesn't matter _which_) | 1748 | /* We treat it as constant endianness (it doesn't matter _which_) |
1710 | because we want the fsid to come out the same whether mounted | 1749 | because we want the fsid to come out the same whether mounted |
1711 | on a big-endian or little-endian host */ | 1750 | on a big-endian or little-endian host */ |