btrfs: fix wrong calculation of stripe size
PATCH v3 3/6 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.
---
Changelog V1 -> V2:
- fix compiler errors x86_32 machines which were caused by u64 division.
fs/btrfs/volumes.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-)
fs/btrfs/volumes.c +8 -2
@@ -2177,6 +2177,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,int num_stripes =1 ;int min_stripes =1 ;int sub_stripes =0 ; +int ncopies =1 ;int looped =0 ;int ret;int index;
@@ -2197,12 +2198,14 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,if (type & (BTRFS_BLOCK_GROUP_DUP )) { num_stripes =2 ; min_stripes =2 ; + ncopies =2 ; }if (type & (BTRFS_BLOCK_GROUP_RAID1 )) {if (fs_devices->rw_devices <2 )return -ENOSPC ; num_stripes =2 ; min_stripes =2 ; + ncopies =2 ; }if (type & (BTRFS_BLOCK_GROUP_RAID10 )) { num_stripes = fs_devices->rw_devices;
@@ -2210,6 +2213,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,return -ENOSPC ; num_stripes &= ~(u32 )1 ; sub_stripes =2 ; + ncopies =2 ; min_stripes =4 ; }
@@ -2239,8 +2243,8 @@ again: map->num_stripes = num_stripes; } -if (calc_size * num_stripes > max_chunk_size) { - calc_size = max_chunk_size; +if (calc_size * num_stripes > max_chunk_size * ncopies) { + calc_size = max_chunk_size * ncopies;do_div (calc_size, num_stripes);do_div (calc_size, stripe_len); calc_size *= stripe_len;
@@ -2321,6 +2325,8 @@ again:if (!looped && max_avail >0 ) { looped =1 ; calc_size = max_avail; +if (type &BTRFS_BLOCK_GROUP_DUP ) +do_div (calc_size,2 ); goto again; }kfree (map);
Signature · 1 line
1.7.2.3
Quoted 10 lines · Miao Xie
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 Miao Xie <[email protected]>
Thanks,
Josef