aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-11-10 11:47:09 -0500
committerChris Mason <chris.mason@oracle.com>2008-11-10 11:47:09 -0500
commitf5a31e166772a7b9fff6725b697eb8b57633671e (patch)
tree16cbd822a7b56a0314d791902704754f06de233f /fs/btrfs/extent-tree.c
parente04ca626baee684bea9d6239e4e1119b696101b2 (diff)
Btrfs: Try harder while searching for free space
The loop searching for free space would exit out too soon when metadata clustering was trying to allocate a large extent. This makes sure a full scan of the free space is done searching for only the minimum extent size requested by the higher layers. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c38
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,
2254new_group: 2258new_group:
2255 mutex_unlock(&block_group->alloc_mutex); 2259 mutex_unlock(&block_group->alloc_mutex);
2256new_group_no_lock: 2260new_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 }