diff options
-rw-r--r-- | fs/btrfs/extent-tree.c | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 2451717d36de..55d6a66c622d 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2123,6 +2123,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
2123 | int allowed_chunk_alloc = 0; | 2123 | int allowed_chunk_alloc = 0; |
2124 | struct list_head *head = NULL, *cur = NULL; | 2124 | struct list_head *head = NULL, *cur = NULL; |
2125 | int loop = 0; | 2125 | int loop = 0; |
2126 | int extra_loop = 0; | ||
2126 | struct btrfs_space_info *space_info; | 2127 | struct btrfs_space_info *space_info; |
2127 | 2128 | ||
2128 | WARN_ON(num_bytes < root->sectorsize); | 2129 | WARN_ON(num_bytes < root->sectorsize); |
@@ -2191,6 +2192,9 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
2191 | 2192 | ||
2192 | free_space = btrfs_find_free_space(block_group, search_start, | 2193 | free_space = btrfs_find_free_space(block_group, search_start, |
2193 | total_needed); | 2194 | total_needed); |
2195 | if (empty_size) | ||
2196 | extra_loop = 1; | ||
2197 | |||
2194 | if (free_space) { | 2198 | if (free_space) { |
2195 | u64 start = block_group->key.objectid; | 2199 | u64 start = block_group->key.objectid; |
2196 | u64 end = block_group->key.objectid + | 2200 | u64 end = block_group->key.objectid + |
@@ -2254,11 +2258,11 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
2254 | new_group: | 2258 | new_group: |
2255 | mutex_unlock(&block_group->alloc_mutex); | 2259 | mutex_unlock(&block_group->alloc_mutex); |
2256 | new_group_no_lock: | 2260 | new_group_no_lock: |
2261 | /* don't try to compare new allocations against the | ||
2262 | * last allocation any more | ||
2263 | */ | ||
2257 | last_wanted = 0; | 2264 | last_wanted = 0; |
2258 | if (!allowed_chunk_alloc) { | 2265 | |
2259 | total_needed -= empty_size; | ||
2260 | empty_size = 0; | ||
2261 | } | ||
2262 | /* | 2266 | /* |
2263 | * Here's how this works. | 2267 | * Here's how this works. |
2264 | * loop == 0: we were searching a block group via a hint | 2268 | * loop == 0: we were searching a block group via a hint |
@@ -2276,9 +2280,21 @@ new_group_no_lock: | |||
2276 | cur = head->next; | 2280 | cur = head->next; |
2277 | loop++; | 2281 | loop++; |
2278 | } else if (loop == 1 && cur == head) { | 2282 | } else if (loop == 1 && cur == head) { |
2279 | 2283 | int keep_going; | |
2284 | |||
2285 | /* at this point we give up on the empty_size | ||
2286 | * allocations and just try to allocate the min | ||
2287 | * space. | ||
2288 | * | ||
2289 | * The extra_loop field was set if an empty_size | ||
2290 | * allocation was attempted above, and if this | ||
2291 | * is try we need to try the loop again without | ||
2292 | * the additional empty_size. | ||
2293 | */ | ||
2280 | total_needed -= empty_size; | 2294 | total_needed -= empty_size; |
2281 | empty_size = 0; | 2295 | empty_size = 0; |
2296 | keep_going = extra_loop; | ||
2297 | loop++; | ||
2282 | 2298 | ||
2283 | if (allowed_chunk_alloc && !chunk_alloc_done) { | 2299 | if (allowed_chunk_alloc && !chunk_alloc_done) { |
2284 | up_read(&space_info->groups_sem); | 2300 | up_read(&space_info->groups_sem); |
@@ -2287,13 +2303,19 @@ new_group_no_lock: | |||
2287 | if (ret < 0) | 2303 | if (ret < 0) |
2288 | break; | 2304 | break; |
2289 | down_read(&space_info->groups_sem); | 2305 | down_read(&space_info->groups_sem); |
2290 | loop++; | ||
2291 | head = &space_info->block_groups; | 2306 | head = &space_info->block_groups; |
2292 | cur = head->next; | 2307 | /* |
2308 | * we've allocated a new chunk, keep | ||
2309 | * trying | ||
2310 | */ | ||
2311 | keep_going = 1; | ||
2293 | chunk_alloc_done = 1; | 2312 | chunk_alloc_done = 1; |
2294 | } else if (!allowed_chunk_alloc) { | 2313 | } else if (!allowed_chunk_alloc) { |
2295 | space_info->force_alloc = 1; | 2314 | space_info->force_alloc = 1; |
2296 | break; | 2315 | } |
2316 | if (keep_going) { | ||
2317 | cur = head->next; | ||
2318 | extra_loop = 0; | ||
2297 | } else { | 2319 | } else { |
2298 | break; | 2320 | break; |
2299 | } | 2321 | } |