diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2010-11-09 01:56:50 -0500 |
---|---|---|
committer | Li Zefan <lizf@cn.fujitsu.com> | 2011-01-26 12:04:50 -0500 |
commit | 120d66eec0dcb966fbd03f743598b2ff2513436b (patch) | |
tree | fc2b1d1e9555f2f9de847ba4134d827613c66e73 /fs/btrfs/free-space-cache.c | |
parent | 5e71b5d5ec07e4b3fb4c78c4e4b108ff667f123f (diff) |
btrfs: Add a helper try_merge_free_space()
When adding a new extent, we'll firstly see if we can merge
this extent to the left or/and right extent. Extract this as
a helper try_merge_free_space().
As a side effect, we fix a small bug that if the new extent
has non-bitmap left entry but is unmergeble, we'll directly
link the extent without trying to drop it into bitmap.
This also prepares for the next patch.
Reviewed-by: Josef Bacik <josef@redhat.com>
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
-rw-r--r-- | fs/btrfs/free-space-cache.c | 75 |
1 files changed, 43 insertions, 32 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 2974c4744d5c..cf67dc3b7bf8 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -1363,22 +1363,14 @@ out: | |||
1363 | return ret; | 1363 | return ret; |
1364 | } | 1364 | } |
1365 | 1365 | ||
1366 | int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, | 1366 | bool try_merge_free_space(struct btrfs_block_group_cache *block_group, |
1367 | u64 offset, u64 bytes) | 1367 | struct btrfs_free_space *info) |
1368 | { | 1368 | { |
1369 | struct btrfs_free_space *right_info = NULL; | 1369 | struct btrfs_free_space *left_info; |
1370 | struct btrfs_free_space *left_info = NULL; | 1370 | struct btrfs_free_space *right_info; |
1371 | struct btrfs_free_space *info = NULL; | 1371 | bool merged = false; |
1372 | int ret = 0; | 1372 | u64 offset = info->offset; |
1373 | 1373 | u64 bytes = info->bytes; | |
1374 | info = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS); | ||
1375 | if (!info) | ||
1376 | return -ENOMEM; | ||
1377 | |||
1378 | info->offset = offset; | ||
1379 | info->bytes = bytes; | ||
1380 | |||
1381 | spin_lock(&block_group->tree_lock); | ||
1382 | 1374 | ||
1383 | /* | 1375 | /* |
1384 | * first we want to see if there is free space adjacent to the range we | 1376 | * first we want to see if there is free space adjacent to the range we |
@@ -1392,27 +1384,11 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, | |||
1392 | else | 1384 | else |
1393 | left_info = tree_search_offset(block_group, offset - 1, 0, 0); | 1385 | left_info = tree_search_offset(block_group, offset - 1, 0, 0); |
1394 | 1386 | ||
1395 | /* | ||
1396 | * If there was no extent directly to the left or right of this new | ||
1397 | * extent then we know we're going to have to allocate a new extent, so | ||
1398 | * before we do that see if we need to drop this into a bitmap | ||
1399 | */ | ||
1400 | if ((!left_info || left_info->bitmap) && | ||
1401 | (!right_info || right_info->bitmap)) { | ||
1402 | ret = insert_into_bitmap(block_group, info); | ||
1403 | |||
1404 | if (ret < 0) { | ||
1405 | goto out; | ||
1406 | } else if (ret) { | ||
1407 | ret = 0; | ||
1408 | goto out; | ||
1409 | } | ||
1410 | } | ||
1411 | |||
1412 | if (right_info && !right_info->bitmap) { | 1387 | if (right_info && !right_info->bitmap) { |
1413 | unlink_free_space(block_group, right_info); | 1388 | unlink_free_space(block_group, right_info); |
1414 | info->bytes += right_info->bytes; | 1389 | info->bytes += right_info->bytes; |
1415 | kfree(right_info); | 1390 | kfree(right_info); |
1391 | merged = true; | ||
1416 | } | 1392 | } |
1417 | 1393 | ||
1418 | if (left_info && !left_info->bitmap && | 1394 | if (left_info && !left_info->bitmap && |
@@ -1421,8 +1397,43 @@ int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, | |||
1421 | info->offset = left_info->offset; | 1397 | info->offset = left_info->offset; |
1422 | info->bytes += left_info->bytes; | 1398 | info->bytes += left_info->bytes; |
1423 | kfree(left_info); | 1399 | kfree(left_info); |
1400 | merged = true; | ||
1424 | } | 1401 | } |
1425 | 1402 | ||
1403 | return merged; | ||
1404 | } | ||
1405 | |||
1406 | int btrfs_add_free_space(struct btrfs_block_group_cache *block_group, | ||
1407 | u64 offset, u64 bytes) | ||
1408 | { | ||
1409 | struct btrfs_free_space *info; | ||
1410 | int ret = 0; | ||
1411 | |||
1412 | info = kzalloc(sizeof(struct btrfs_free_space), GFP_NOFS); | ||
1413 | if (!info) | ||
1414 | return -ENOMEM; | ||
1415 | |||
1416 | info->offset = offset; | ||
1417 | info->bytes = bytes; | ||
1418 | |||
1419 | spin_lock(&block_group->tree_lock); | ||
1420 | |||
1421 | if (try_merge_free_space(block_group, info)) | ||
1422 | goto link; | ||
1423 | |||
1424 | /* | ||
1425 | * There was no extent directly to the left or right of this new | ||
1426 | * extent then we know we're going to have to allocate a new extent, so | ||
1427 | * before we do that see if we need to drop this into a bitmap | ||
1428 | */ | ||
1429 | ret = insert_into_bitmap(block_group, info); | ||
1430 | if (ret < 0) { | ||
1431 | goto out; | ||
1432 | } else if (ret) { | ||
1433 | ret = 0; | ||
1434 | goto out; | ||
1435 | } | ||
1436 | link: | ||
1426 | ret = link_free_space(block_group, info); | 1437 | ret = link_free_space(block_group, info); |
1427 | if (ret) | 1438 | if (ret) |
1428 | kfree(info); | 1439 | kfree(info); |