aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2011-01-05 05:07:24 -0500
committerChris Mason <chris.mason@oracle.com>2011-01-16 11:30:19 -0500
commit1974a3b42d8cf7a9c74f1e0310c593023617037a (patch)
tree73d7eb8dc071a095fbe424776ab7610dbc897c16 /fs
parentd52a5b5f1fa40804f681cf9868d4a8f90661bdf3 (diff)
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: Miao Xie <miaox@cn.fujitsu.com> Reviewed-by: Josef Bacik <josef@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/volumes.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 177b73179590..c50a85e0d08f 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2177,6 +2177,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
2177 int num_stripes = 1; 2177 int num_stripes = 1;
2178 int min_stripes = 1; 2178 int min_stripes = 1;
2179 int sub_stripes = 0; 2179 int sub_stripes = 0;
2180 int ncopies = 1;
2180 int looped = 0; 2181 int looped = 0;
2181 int ret; 2182 int ret;
2182 int index; 2183 int index;
@@ -2197,12 +2198,14 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
2197 if (type & (BTRFS_BLOCK_GROUP_DUP)) { 2198 if (type & (BTRFS_BLOCK_GROUP_DUP)) {
2198 num_stripes = 2; 2199 num_stripes = 2;
2199 min_stripes = 2; 2200 min_stripes = 2;
2201 ncopies = 2;
2200 } 2202 }
2201 if (type & (BTRFS_BLOCK_GROUP_RAID1)) { 2203 if (type & (BTRFS_BLOCK_GROUP_RAID1)) {
2202 if (fs_devices->rw_devices < 2) 2204 if (fs_devices->rw_devices < 2)
2203 return -ENOSPC; 2205 return -ENOSPC;
2204 num_stripes = 2; 2206 num_stripes = 2;
2205 min_stripes = 2; 2207 min_stripes = 2;
2208 ncopies = 2;
2206 } 2209 }
2207 if (type & (BTRFS_BLOCK_GROUP_RAID10)) { 2210 if (type & (BTRFS_BLOCK_GROUP_RAID10)) {
2208 num_stripes = fs_devices->rw_devices; 2211 num_stripes = fs_devices->rw_devices;
@@ -2210,6 +2213,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
2210 return -ENOSPC; 2213 return -ENOSPC;
2211 num_stripes &= ~(u32)1; 2214 num_stripes &= ~(u32)1;
2212 sub_stripes = 2; 2215 sub_stripes = 2;
2216 ncopies = 2;
2213 min_stripes = 4; 2217 min_stripes = 4;
2214 } 2218 }
2215 2219
@@ -2239,8 +2243,8 @@ again:
2239 map->num_stripes = num_stripes; 2243 map->num_stripes = num_stripes;
2240 } 2244 }
2241 2245
2242 if (calc_size * num_stripes > max_chunk_size) { 2246 if (calc_size * num_stripes > max_chunk_size * ncopies) {
2243 calc_size = max_chunk_size; 2247 calc_size = max_chunk_size * ncopies;
2244 do_div(calc_size, num_stripes); 2248 do_div(calc_size, num_stripes);
2245 do_div(calc_size, stripe_len); 2249 do_div(calc_size, stripe_len);
2246 calc_size *= stripe_len; 2250 calc_size *= stripe_len;
@@ -2321,6 +2325,8 @@ again:
2321 if (!looped && max_avail > 0) { 2325 if (!looped && max_avail > 0) {
2322 looped = 1; 2326 looped = 1;
2323 calc_size = max_avail; 2327 calc_size = max_avail;
2328 if (type & BTRFS_BLOCK_GROUP_DUP)
2329 do_div(calc_size, 2);
2324 goto again; 2330 goto again;
2325 } 2331 }
2326 kfree(map); 2332 kfree(map);