Commit 86d4a77b authored by Josef Bacik's avatar Josef Bacik

Btrfs: cache bitmaps when searching for a cluster

If we are looking for a cluster in a particularly sparse or fragmented block
group, we will do a lot of looping through the free space tree looking for
various things, and if we need to look at bitmaps we will endup doing the whole
dance twice.  So instead add the bitmap entries to a temporary list so if we
have to do the bitmap search we can just look through the list of entries we've
found quickly instead of having to loop through the entire tree again.  Thanks,
Signed-off-by: default avatarJosef Bacik <josef@redhat.com>
parent aa0467d8
...@@ -2144,6 +2144,7 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group, ...@@ -2144,6 +2144,7 @@ static int btrfs_bitmap_cluster(struct btrfs_block_group_cache *block_group,
*/ */
static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
struct btrfs_free_cluster *cluster, struct btrfs_free_cluster *cluster,
struct list_head *bitmaps,
u64 offset, u64 bytes, u64 min_bytes) u64 offset, u64 bytes, u64 min_bytes)
{ {
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
...@@ -2166,6 +2167,8 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, ...@@ -2166,6 +2167,8 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
* extent entry. * extent entry.
*/ */
while (entry->bitmap) { while (entry->bitmap) {
if (list_empty(&entry->list))
list_add_tail(&entry->list, bitmaps);
node = rb_next(&entry->offset_index); node = rb_next(&entry->offset_index);
if (!node) if (!node)
return -ENOSPC; return -ENOSPC;
...@@ -2185,8 +2188,12 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, ...@@ -2185,8 +2188,12 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
return -ENOSPC; return -ENOSPC;
entry = rb_entry(node, struct btrfs_free_space, offset_index); entry = rb_entry(node, struct btrfs_free_space, offset_index);
if (entry->bitmap) if (entry->bitmap) {
if (list_empty(&entry->list))
list_add_tail(&entry->list, bitmaps);
continue; continue;
}
/* /*
* we haven't filled the empty size and the window is * we haven't filled the empty size and the window is
* very large. reset and try again * very large. reset and try again
...@@ -2240,6 +2247,7 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, ...@@ -2240,6 +2247,7 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
*/ */
static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
struct btrfs_free_cluster *cluster, struct btrfs_free_cluster *cluster,
struct list_head *bitmaps,
u64 offset, u64 bytes, u64 min_bytes) u64 offset, u64 bytes, u64 min_bytes)
{ {
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
...@@ -2250,10 +2258,39 @@ static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, ...@@ -2250,10 +2258,39 @@ static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
if (ctl->total_bitmaps == 0) if (ctl->total_bitmaps == 0)
return -ENOSPC; return -ENOSPC;
/*
* First check our cached list of bitmaps and see if there is an entry
* here that will work.
*/
list_for_each_entry(entry, bitmaps, list) {
if (entry->bytes < min_bytes)
continue;
ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset,
bytes, min_bytes);
if (!ret)
return 0;
}
/*
* If we do have entries on our list and we are here then we didn't find
* anything, so go ahead and get the next entry after the last entry in
* this list and start the search from there.
*/
if (!list_empty(bitmaps)) {
entry = list_entry(bitmaps->prev, struct btrfs_free_space,
list);
node = rb_next(&entry->offset_index);
if (!node)
return -ENOSPC;
entry = rb_entry(node, struct btrfs_free_space, offset_index);
goto search;
}
entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1); entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1);
if (!entry) if (!entry)
return -ENOSPC; return -ENOSPC;
search:
node = &entry->offset_index; node = &entry->offset_index;
do { do {
entry = rb_entry(node, struct btrfs_free_space, offset_index); entry = rb_entry(node, struct btrfs_free_space, offset_index);
...@@ -2284,6 +2321,8 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, ...@@ -2284,6 +2321,8 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
u64 offset, u64 bytes, u64 empty_size) u64 offset, u64 bytes, u64 empty_size)
{ {
struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
struct list_head bitmaps;
struct btrfs_free_space *entry, *tmp;
u64 min_bytes; u64 min_bytes;
int ret; int ret;
...@@ -2322,11 +2361,16 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans, ...@@ -2322,11 +2361,16 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
goto out; goto out;
} }
ret = setup_cluster_no_bitmap(block_group, cluster, offset, bytes, INIT_LIST_HEAD(&bitmaps);
min_bytes); ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset,
bytes, min_bytes);
if (ret) if (ret)
ret = setup_cluster_bitmap(block_group, cluster, offset, ret = setup_cluster_bitmap(block_group, cluster, &bitmaps,
bytes, min_bytes); offset, bytes, min_bytes);
/* Clear our temporary list */
list_for_each_entry_safe(entry, tmp, &bitmaps, list)
list_del_init(&entry->list);
if (!ret) { if (!ret) {
atomic_inc(&block_group->count); atomic_inc(&block_group->count);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment