All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] btrfs: Make the chunk size limit on on-disk/logical more clean.
@ 2014-12-24  1:55 Qu Wenruo
  2014-12-24  1:55 ` [PATCH v2 2/2] btrfs: Enhance btrfs chunk allocation algorithm to reduce ENOSPC caused by unbalanced data/metadata allocation Qu Wenruo
  2015-02-26  1:20 ` [PATCH 1/2] btrfs: Make the chunk size limit on on-disk/logical more clean Qu Wenruo
  0 siblings, 2 replies; 5+ messages in thread
From: Qu Wenruo @ 2014-12-24  1:55 UTC (permalink / raw)
  To: linux-btrfs

Original __btrfs_alloc_chunk() use max_chunk_size to limit chunk size,
however it mixed the on-disk space with logical space.
When comes to 10% of writable space, max_chunk_size is used with on-disk
size, but it is also used as logical space size limit, so it is very
confusing and causing inconsistence in different profile.

For example:
on M single, D single 5G btrfs single device,
data chunk is limited to 512M due to 10% limit.

on M RAID1, D RAID1 10Gx2 btrfs 2 devices,
data chunk is limited to 2G due to 10% limit is mixed with on-disk
space, causing the logical chunk space to 1G, twice than single device.

This patch will make the logical and on-disk space limit independent and
clear and solve the above inconsistence.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
---
changelog:
v2:
   Newly introduced.
---
 fs/btrfs/volumes.c | 40 ++++++++++++++++++++++++++--------------
 1 file changed, 26 insertions(+), 14 deletions(-)

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 0144790..8e74b34 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4235,10 +4235,12 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 	int ncopies;		/* how many copies to data has */
 	int ret;
 	u64 max_stripe_size;
-	u64 max_chunk_size;
+	u64 max_logical_size;	/* Up limit on chunk's logical size */
+	u64 max_physical_size;	/* Up limit on a chunk's on-disk size */
 	u64 stripe_size;
 	u64 num_bytes;
 	u64 raid_stripe_len = BTRFS_STRIPE_LEN;
+	int need_bump = 0;
 	int ndevs;
 	int i;
 	int j;
@@ -4260,7 +4262,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 
 	if (type & BTRFS_BLOCK_GROUP_DATA) {
 		max_stripe_size = 1024 * 1024 * 1024;
-		max_chunk_size = 10 * max_stripe_size;
+		max_logical_size = 10 * max_stripe_size;
 		if (!devs_max)
 			devs_max = BTRFS_MAX_DEVS(info->chunk_root);
 	} else if (type & BTRFS_BLOCK_GROUP_METADATA) {
@@ -4269,12 +4271,12 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 			max_stripe_size = 1024 * 1024 * 1024;
 		else
 			max_stripe_size = 256 * 1024 * 1024;
-		max_chunk_size = max_stripe_size;
+		max_logical_size = max_stripe_size;
 		if (!devs_max)
 			devs_max = BTRFS_MAX_DEVS(info->chunk_root);
 	} else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
 		max_stripe_size = 32 * 1024 * 1024;
-		max_chunk_size = 2 * max_stripe_size;
+		max_logical_size = 2 * max_stripe_size;
 		if (!devs_max)
 			devs_max = BTRFS_MAX_DEVS_SYS_CHUNK;
 	} else {
@@ -4284,8 +4286,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 	}
 
 	/* we don't want a chunk larger than 10% of writeable space */
-	max_chunk_size = min(div_factor(fs_devices->total_rw_bytes, 1),
-			     max_chunk_size);
+	max_physical_size = div_factor(fs_devices->total_rw_bytes, 1);
 
 	devices_info = kzalloc(sizeof(*devices_info) * fs_devices->rw_devices,
 			       GFP_NOFS);
@@ -4391,15 +4392,21 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 		data_stripes = num_stripes - 2;
 	}
 
-	/*
-	 * Use the number of data stripes to figure out how big this chunk
-	 * is really going to be in terms of logical address space,
-	 * and compare that answer with the max chunk size
-	 */
-	if (stripe_size * data_stripes > max_chunk_size) {
-		u64 mask = (1ULL << 24) - 1;
-		stripe_size = max_chunk_size;
+	/* Restrict on-disk chunk size */
+	if (stripe_size * num_stripes > max_physical_size) {
+		stripe_size = max_physical_size;
+		do_div(stripe_size, num_stripes);
+		need_bump = 1;
+	}
+	/* restrict logical chunk size  */
+	if (stripe_size * data_stripes > max_logical_size) {
+		stripe_size = max_logical_size;
 		do_div(stripe_size, data_stripes);
+		need_bump = 1;
+	}
+
+	if (need_bump) {
+		u64 mask = (1ULL << 24) - 1;
 
 		/* bump the answer up to a 16MB boundary */
 		stripe_size = (stripe_size + mask) & ~mask;
@@ -4411,6 +4418,11 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 			stripe_size = devices_info[ndevs-1].max_avail;
 	}
 
+	/*
+	 * Special handle for DUP, since stripe_size is the largest free extent
+	 * we found, DUP can only use half of it. Other profile's dev_stripes
+	 * is always 1.
+	 */
 	do_div(stripe_size, dev_stripes);
 
 	/* align to BTRFS_STRIPE_LEN */
-- 
2.2.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-02-26  1:20 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-24  1:55 [PATCH 1/2] btrfs: Make the chunk size limit on on-disk/logical more clean Qu Wenruo
2014-12-24  1:55 ` [PATCH v2 2/2] btrfs: Enhance btrfs chunk allocation algorithm to reduce ENOSPC caused by unbalanced data/metadata allocation Qu Wenruo
2014-12-29 14:56   ` David Sterba
2014-12-30  0:40     ` Qu Wenruo
2015-02-26  1:20 ` [PATCH 1/2] btrfs: Make the chunk size limit on on-disk/logical more clean Qu Wenruo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.