diff options
-rw-r--r-- | fs/btrfs/free-space-cache.c | 54 |
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 | */ |
2145 | static int setup_cluster_no_bitmap(struct btrfs_block_group_cache *block_group, | 2145 | static 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 | */ |
2241 | static int setup_cluster_bitmap(struct btrfs_block_group_cache *block_group, | 2248 | static 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 | ||
2293 | search: | ||
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); |