aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2011-05-25 13:03:16 -0400
committerJosef Bacik <josef@redhat.com>2011-06-08 15:08:28 -0400
commit86d4a77ba3dc4ace238a0556541a41df2bd71d49 (patch)
treed59bdf911b0a360f87308c1499a320f1b6f7be06 /fs/btrfs
parentaa0467d8d2a00e75b2bb6a56a4ee6d70c5d1928f (diff)
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: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/free-space-cache.c54
1 files changed, 49 insertions, 5 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index ad144736a5fd..930c07f79b3d 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -2144,6 +2144,7 @@ again:
2144 */ 2144 */
2145static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, 2145static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
2146 struct btrfs_free_cluster *cluster, 2146 struct btrfs_free_cluster *cluster,
2147 struct list_head *bitmaps,
2147 u64 offset, u64 bytes, u64 min_bytes) 2148 u64 offset, u64 bytes, u64 min_bytes)
2148{ 2149{
2149 struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; 2150 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 * extent entry. 2167 * extent entry.
2167 */ 2168 */
2168 while (entry->bitmap) { 2169 while (entry->bitmap) {
2170 if (list_empty(&entry->list))
2171 list_add_tail(&entry->list, bitmaps);
2169 node = rb_next(&entry->offset_index); 2172 node = rb_next(&entry->offset_index);
2170 if (!node) 2173 if (!node)
2171 return -ENOSPC; 2174 return -ENOSPC;
@@ -2185,8 +2188,12 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
2185 return -ENOSPC; 2188 return -ENOSPC;
2186 entry = rb_entry(node, struct btrfs_free_space, offset_index); 2189 entry = rb_entry(node, struct btrfs_free_space, offset_index);
2187 2190
2188 if (entry->bitmap) 2191 if (entry->bitmap) {
2192 if (list_empty(&entry->list))
2193 list_add_tail(&entry->list, bitmaps);
2189 continue; 2194 continue;
2195 }
2196
2190 /* 2197 /*
2191 * we haven't filled the empty size and the window is 2198 * we haven't filled the empty size and the window is
2192 * very large. reset and try again 2199 * very large. reset and try again
@@ -2240,6 +2247,7 @@ static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group,
2240 */ 2247 */
2241static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, 2248static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
2242 struct btrfs_free_cluster *cluster, 2249 struct btrfs_free_cluster *cluster,
2250 struct list_head *bitmaps,
2243 u64 offset, u64 bytes, u64 min_bytes) 2251 u64 offset, u64 bytes, u64 min_bytes)
2244{ 2252{
2245 struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; 2253 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 if (ctl->total_bitmaps == 0) 2258 if (ctl->total_bitmaps == 0)
2251 return -ENOSPC; 2259 return -ENOSPC;
2252 2260
2261 /*
2262 * First check our cached list of bitmaps and see if there is an entry
2263 * here that will work.
2264 */
2265 list_for_each_entry(entry, bitmaps, list) {
2266 if (entry->bytes < min_bytes)
2267 continue;
2268 ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset,
2269 bytes, min_bytes);
2270 if (!ret)
2271 return 0;
2272 }
2273
2274 /*
2275 * If we do have entries on our list and we are here then we didn't find
2276 * anything, so go ahead and get the next entry after the last entry in
2277 * this list and start the search from there.
2278 */
2279 if (!list_empty(bitmaps)) {
2280 entry = list_entry(bitmaps->prev, struct btrfs_free_space,
2281 list);
2282 node = rb_next(&entry->offset_index);
2283 if (!node)
2284 return -ENOSPC;
2285 entry = rb_entry(node, struct btrfs_free_space, offset_index);
2286 goto search;
2287 }
2288
2253 entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1); 2289 entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1);
2254 if (!entry) 2290 if (!entry)
2255 return -ENOSPC; 2291 return -ENOSPC;
2256 2292
2293search:
2257 node = &entry->offset_index; 2294 node = &entry->offset_index;
2258 do { 2295 do {
2259 entry = rb_entry(node, struct btrfs_free_space, offset_index); 2296 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 u64 offset, u64 bytes, u64 empty_size) 2321 u64 offset, u64 bytes, u64 empty_size)
2285{ 2322{
2286 struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; 2323 struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
2324 struct list_head bitmaps;
2325 struct btrfs_free_space *entry, *tmp;
2287 u64 min_bytes; 2326 u64 min_bytes;
2288 int ret; 2327 int ret;
2289 2328
@@ -2322,11 +2361,16 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
2322 goto out; 2361 goto out;
2323 } 2362 }
2324 2363
2325 ret = setup_cluster_no_bitmap(block_group, cluster, offset, bytes, 2364 INIT_LIST_HEAD(&bitmaps);
2326 min_bytes); 2365 ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset,
2366 bytes, min_bytes);
2327 if (ret) 2367 if (ret)
2328 ret = setup_cluster_bitmap(block_group, cluster, offset, 2368 ret = setup_cluster_bitmap(block_group, cluster, &bitmaps,
2329 bytes, min_bytes); 2369 offset, bytes, min_bytes);
2370
2371 /* Clear our temporary list */
2372 list_for_each_entry_safe(entry, tmp, &bitmaps, list)
2373 list_del_init(&entry->list);
2330 2374
2331 if (!ret) { 2375 if (!ret) {
2332 atomic_inc(&block_group->count); 2376 atomic_inc(&block_group->count);