Message ID | 1419386114-21703-1-git-send-email-quwenruo@cn.fujitsu.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Ping. Any comment? Thanks, Qu -------- Original Message -------- Subject: [PATCH 1/2] btrfs: Make the chunk size limit on on-disk/logical more clean. From: Qu Wenruo <quwenruo@cn.fujitsu.com> To: <linux-btrfs@vger.kernel.org> Date: 2014?12?24? 09:55 > 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 */ -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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 */
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(-)