Btrfs: change the calculation of available space since the data profile can be degenerated
RFC PATCH 2/2 Btrfs: change the calculation of available space since the data profile can be degenerated
Since the data profile can be degenerated(RAID10 -> RAID1 -> DUP, RAID0 -> SINGLE), btrfs can utilize almost the whole disk space, we can simplify the calculation of the available space in btrfs_statfs(). The new method just ignore the disk space(one BTRFS_STRIPE_LEN at most) that can not be used to allocate a DUP chunk, the other space will be considered as the available space, and be count.
Signed-off-by Miao Xie <[email protected]>
--- fs/btrfs/super.c | 105 +++++++++++------------------------------------------ 1 files changed, 22 insertions(+), 83 deletions(-)
fs/btrfs/super.c +22 -83
@@ -1039,32 +1039,6 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)return 0 ; } -/* Used to sort the devices by max_avail(descending sort) */ -static int btrfs_cmp_device_free_bytes (const void *dev_info1, -const void *dev_info2) -{ -if (((struct btrfs_device_info *)dev_info1)->max_avail > - ((struct btrfs_device_info *)dev_info2)->max_avail) -return -1 ; -else if (((struct btrfs_device_info *)dev_info1)->max_avail < - ((struct btrfs_device_info *)dev_info2)->max_avail) -return 1 ; -else -return 0 ; -} - -/* -* sort the devices by max_avail, in which max free extent size of each device -* is stored.(Descending Sort) -*/ -static inline void btrfs_descending_sort_devices ( -struct btrfs_device_info *devices, -size_t nr_devices) -{ -sort (devices, nr_devices,sizeof (struct btrfs_device_info ), - btrfs_cmp_device_free_bytes,NULL ); -} -/* * The helper to calc the free space on the devices that can be used to store * file data.
@@ -1072,7 +1046,6 @@ static inline void btrfs_descending_sort_devices(static int btrfs_calc_avail_data_space (struct btrfs_root *root,u64 *free_bytes) {struct btrfs_fs_info *fs_info = root->fs_info; -struct btrfs_device_info *devices_info;struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;struct btrfs_device *device;u64 skip_space;
@@ -1080,31 +1053,12 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)u64 avail_space;u64 used_space;u64 min_stripe_size; -int min_stripes =1 , num_stripes =1 ; -int i =0 , nr_devices;int ret; - nr_devices = fs_info->fs_devices->open_devices; -BUG_ON (!nr_devices); - - devices_info =kmalloc (sizeof (*devices_info) * nr_devices, -GFP_NOFS ); -if (!devices_info) -return -ENOMEM ; + *free_bytes =0 ;/* calc min stripe number for data space alloction */ type =btrfs_get_alloc_profile (root,1 ); -if (type &BTRFS_BLOCK_GROUP_RAID0 ) { - min_stripes =2 ; - num_stripes = nr_devices; - }else if (type &BTRFS_BLOCK_GROUP_RAID1 ) { - min_stripes =2 ; - num_stripes =2 ; - }else if (type &BTRFS_BLOCK_GROUP_RAID10 ) { - min_stripes =4 ; - num_stripes =4 ; - } -if (type &BTRFS_BLOCK_GROUP_DUP ) min_stripe_size =2 *BTRFS_STRIPE_LEN ;else
@@ -1117,8 +1071,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes) avail_space = device->total_bytes - device->bytes_used;/* align with stripe_len */ -do_div (avail_space,BTRFS_STRIPE_LEN ); - avail_space *=BTRFS_STRIPE_LEN ; + avail_space =round_down (avail_space,BTRFS_STRIPE_LEN );/* * In order to avoid overwritting the superblock on the drive,
@@ -1139,10 +1092,8 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)*/ ret =btrfs_account_dev_extents_size (device,0 , skip_space -1 , &used_space); -if (ret) { -kfree (devices_info); +if (ret)return ret; - }/* calc the free space in [0, skip_space - 1] */ skip_space -= used_space;
@@ -1156,40 +1107,28 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)else avail_space =0 ; -if (avail_space < min_stripe_size) -continue ; - - devices_info[i].dev = device; - devices_info[i].max_avail = avail_space; - - i++; + avail_space =round_down (avail_space, min_stripe_size); + *free_bytes += avail_space; } - nr_devices = i; - -btrfs_descending_sort_devices (devices_info, nr_devices); - - i = nr_devices -1 ; - avail_space =0 ; -while (nr_devices >= min_stripes) { -if (num_stripes > nr_devices) - num_stripes = nr_devices; - -if (devices_info[i].max_avail >= min_stripe_size) { -int j; -u64 alloc_size; - - avail_space += devices_info[i].max_avail * num_stripes; - alloc_size = devices_info[i].max_avail; -for (j = i +1 - num_stripes; j <= i; j++) - devices_info[j].max_avail -= alloc_size; - } - i--; - nr_devices--; - } +/* +* If there is no enough disk space for new RAID chunk allocation, +* the chunk allocator will degenerate the profile: +* RAID0 -> SINGLE +* RAID10 -> RAID1 -> DUP +* +* So if the profile is RAID0, the profile will be degenerated to +* SINGLE at last, and we can utilize the whole free disk space. +* Note: aligned with BTRFS_STRIPE_LEN, it is dealt with above, we +* needn't do anything here. +* +* If the profile is RAID1 or RAID10, the profile will be DUP at last. +* So the free size must be even times BTRFS_STRIPE_LEN. +*/ +if (type & (BTRFS_BLOCK_GROUP_RAID1 | +BTRFS_BLOCK_GROUP_RAID10 )) + *free_bytes =round_down (*free_bytes,2 *BTRFS_STRIPE_LEN ); -kfree (devices_info); - *free_bytes = avail_space;return 0 ; }
Signature · 1 line
1.7.6.5