diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0d73a53c6763..b92e92c29e3b 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2152,11 +2152,13 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
2152 | } | 2152 | } |
2153 | search_start = max(search_start, first_logical_byte(root, 0)); | 2153 | search_start = max(search_start, first_logical_byte(root, 0)); |
2154 | search_start = max(search_start, hint_byte); | 2154 | search_start = max(search_start, hint_byte); |
2155 | total_needed += empty_size; | ||
2156 | 2155 | ||
2157 | if (search_start != last_wanted) | 2156 | if (last_wanted && search_start != last_wanted) { |
2158 | last_wanted = 0; | 2157 | last_wanted = 0; |
2158 | empty_size += empty_cluster; | ||
2159 | } | ||
2159 | 2160 | ||
2161 | total_needed += empty_size; | ||
2160 | block_group = btrfs_lookup_block_group(root->fs_info, search_start); | 2162 | block_group = btrfs_lookup_block_group(root->fs_info, search_start); |
2161 | if (!block_group) | 2163 | if (!block_group) |
2162 | block_group = btrfs_lookup_first_block_group(root->fs_info, | 2164 | block_group = btrfs_lookup_first_block_group(root->fs_info, |
@@ -2171,7 +2173,9 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
2171 | * group thats not of the proper type, while looping this | 2173 | * group thats not of the proper type, while looping this |
2172 | * should never happen | 2174 | * should never happen |
2173 | */ | 2175 | */ |
2174 | WARN_ON(!block_group); | 2176 | if (!block_group) |
2177 | goto new_group_no_lock; | ||
2178 | |||
2175 | mutex_lock(&block_group->alloc_mutex); | 2179 | mutex_lock(&block_group->alloc_mutex); |
2176 | if (unlikely(!block_group_bits(block_group, data))) | 2180 | if (unlikely(!block_group_bits(block_group, data))) |
2177 | goto new_group; | 2181 | goto new_group; |
@@ -2248,12 +2252,13 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
2248 | break; | 2252 | break; |
2249 | } | 2253 | } |
2250 | new_group: | 2254 | new_group: |
2255 | mutex_unlock(&block_group->alloc_mutex); | ||
2256 | new_group_no_lock: | ||
2251 | last_wanted = 0; | 2257 | last_wanted = 0; |
2252 | if (loop > 0) { | 2258 | if (!allowed_chunk_alloc && loop > 0) { |
2253 | total_needed -= empty_cluster; | 2259 | total_needed -= empty_cluster; |
2254 | empty_cluster = 0; | 2260 | empty_cluster = 0; |
2255 | } | 2261 | } |
2256 | mutex_unlock(&block_group->alloc_mutex); | ||
2257 | /* | 2262 | /* |
2258 | * Here's how this works. | 2263 | * Here's how this works. |
2259 | * loop == 0: we were searching a block group via a hint | 2264 | * loop == 0: we were searching a block group via a hint |
@@ -2271,6 +2276,10 @@ new_group: | |||
2271 | cur = head->next; | 2276 | cur = head->next; |
2272 | loop++; | 2277 | loop++; |
2273 | } else if (loop == 1 && cur == head) { | 2278 | } else if (loop == 1 && cur == head) { |
2279 | |||
2280 | total_needed -= empty_cluster; | ||
2281 | empty_cluster = 0; | ||
2282 | |||
2274 | if (allowed_chunk_alloc && !chunk_alloc_done) { | 2283 | if (allowed_chunk_alloc && !chunk_alloc_done) { |
2275 | up_read(&space_info->groups_sem); | 2284 | up_read(&space_info->groups_sem); |
2276 | ret = do_chunk_alloc(trans, root, num_bytes + | 2285 | ret = do_chunk_alloc(trans, root, num_bytes + |