Skip to content

Commit

Permalink
Btrfs: Try harder while searching for free space
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Chris Mason committed Nov 10, 2008
1 parent e04ca62 commit f5a31e1
Showing 1 changed file with 30 additions and 8 deletions.
38 changes: 30 additions & 8 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -2123,6 +2123,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
int allowed_chunk_alloc = 0;
struct list_head *head = NULL, *cur = NULL;
int loop = 0;
int extra_loop = 0;
struct btrfs_space_info *space_info;

WARN_ON(num_bytes < root->sectorsize);
Expand Down Expand Up @@ -2191,6 +2192,9 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,

free_space = btrfs_find_free_space(block_group, search_start,
total_needed);
if (empty_size)
extra_loop = 1;

if (free_space) {
u64 start = block_group->key.objectid;
u64 end = block_group->key.objectid +
Expand Down Expand Up @@ -2254,11 +2258,11 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
new_group:
mutex_unlock(&block_group->alloc_mutex);
new_group_no_lock:
/* don't try to compare new allocations against the
* last allocation any more
*/
last_wanted = 0;
if (!allowed_chunk_alloc) {
total_needed -= empty_size;
empty_size = 0;
}

/*
* Here's how this works.
* loop == 0: we were searching a block group via a hint
Expand All @@ -2276,9 +2280,21 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
cur = head->next;
loop++;
} else if (loop == 1 && cur == head) {

int keep_going;

/* at this point we give up on the empty_size
* allocations and just try to allocate the min
* space.
*
* The extra_loop field was set if an empty_size
* allocation was attempted above, and if this
* is try we need to try the loop again without
* the additional empty_size.
*/
total_needed -= empty_size;
empty_size = 0;
keep_going = extra_loop;
loop++;

if (allowed_chunk_alloc && !chunk_alloc_done) {
up_read(&space_info->groups_sem);
Expand All @@ -2287,13 +2303,19 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
if (ret < 0)
break;
down_read(&space_info->groups_sem);
loop++;
head = &space_info->block_groups;
cur = head->next;
/*
* we've allocated a new chunk, keep
* trying
*/
keep_going = 1;
chunk_alloc_done = 1;
} else if (!allowed_chunk_alloc) {
space_info->force_alloc = 1;
break;
}
if (keep_going) {
cur = head->next;
extra_loop = 0;
} else {
break;
}
Expand Down

0 comments on commit f5a31e1

Please sign in to comment.