Commit 1974a3b4 authored by Miao Xie's avatar Miao Xie Committed by Chris Mason

btrfs: fix wrong calculation of stripe size

There are two tiny problem:
- One is When we check the chunk size is greater than the max chunk size or not,
  we should take mirrors into account, but the original code didn't.
- The other is btrfs shouldn't use the size of the residual free space as the
  length of of a dup chunk when doing chunk allocation. It is because the device
  space that a dup chunk needs is twice as large as the chunk size, if we use
  the size of the residual free space as the length of a dup chunk, we can not
  get enough free space. Fix it.
Signed-off-by: default avatarMiao Xie <miaox@cn.fujitsu.com>
Reviewed-by: default avatarJosef Bacik <josef@redhat.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent d52a5b5f
...@@ -2177,6 +2177,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, ...@@ -2177,6 +2177,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
int num_stripes = 1; int num_stripes = 1;
int min_stripes = 1; int min_stripes = 1;
int sub_stripes = 0; int sub_stripes = 0;
int ncopies = 1;
int looped = 0; int looped = 0;
int ret; int ret;
int index; int index;
...@@ -2197,12 +2198,14 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, ...@@ -2197,12 +2198,14 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
if (type & (BTRFS_BLOCK_GROUP_DUP)) { if (type & (BTRFS_BLOCK_GROUP_DUP)) {
num_stripes = 2; num_stripes = 2;
min_stripes = 2; min_stripes = 2;
ncopies = 2;
} }
if (type & (BTRFS_BLOCK_GROUP_RAID1)) { if (type & (BTRFS_BLOCK_GROUP_RAID1)) {
if (fs_devices->rw_devices < 2) if (fs_devices->rw_devices < 2)
return -ENOSPC; return -ENOSPC;
num_stripes = 2; num_stripes = 2;
min_stripes = 2; min_stripes = 2;
ncopies = 2;
} }
if (type & (BTRFS_BLOCK_GROUP_RAID10)) { if (type & (BTRFS_BLOCK_GROUP_RAID10)) {
num_stripes = fs_devices->rw_devices; num_stripes = fs_devices->rw_devices;
...@@ -2210,6 +2213,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, ...@@ -2210,6 +2213,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
return -ENOSPC; return -ENOSPC;
num_stripes &= ~(u32)1; num_stripes &= ~(u32)1;
sub_stripes = 2; sub_stripes = 2;
ncopies = 2;
min_stripes = 4; min_stripes = 4;
} }
...@@ -2239,8 +2243,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, ...@@ -2239,8 +2243,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
map->num_stripes = num_stripes; map->num_stripes = num_stripes;
} }
if (calc_size * num_stripes > max_chunk_size) { if (calc_size * num_stripes > max_chunk_size * ncopies) {
calc_size = max_chunk_size; calc_size = max_chunk_size * ncopies;
do_div(calc_size, num_stripes); do_div(calc_size, num_stripes);
do_div(calc_size, stripe_len); do_div(calc_size, stripe_len);
calc_size *= stripe_len; calc_size *= stripe_len;
...@@ -2321,6 +2325,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, ...@@ -2321,6 +2325,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
if (!looped && max_avail > 0) { if (!looped && max_avail > 0) {
looped = 1; looped = 1;
calc_size = max_avail; calc_size = max_avail;
if (type & BTRFS_BLOCK_GROUP_DUP)
do_div(calc_size, 2);
goto again; goto again;
} }
kfree(map); kfree(map);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment