linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC][PATCH 2/2] Btrfs: change the calculation of available space since the data profile can be degenerated
@ 2012-01-17 10:03 Miao Xie
  0 siblings, 0 replies; only message in thread
From: Miao Xie @ 2012-01-17 10:03 UTC (permalink / raw)
  To: Linux Btrfs

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 <miaox@cn.fujitsu.com>
---
 fs/btrfs/super.c |  105 +++++++++++------------------------------------------
 1 files changed, 22 insertions(+), 83 deletions(-)

diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 34a8b61..0284620 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -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;
 }
 
-- 
1.7.6.5

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2012-01-17 10:03 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-17 10:03 [RFC][PATCH 2/2] Btrfs: change the calculation of available space since the data profile can be degenerated Miao Xie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).