diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2011-01-05 05:07:24 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2011-01-16 11:30:19 -0500 |
commit | 1974a3b42d8cf7a9c74f1e0310c593023617037a (patch) | |
tree | 73d7eb8dc071a095fbe424776ab7610dbc897c16 /fs | |
parent | d52a5b5f1fa40804f681cf9868d4a8f90661bdf3 (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.c | 10 |
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); |