diff options
author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2015-12-01 15:11:22 +0800 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-01-12 15:01:03 +0100 |
commit | f735b37466c293aa6ecc4d145b6251c162c519f6 (patch) | |
tree | c7bb26a6db860a23ba7230d323a87ba59c827edd /extent-cache.c | |
parent | 466e066837898ec047165b8f1081c529092c6d0a (diff) |
btrfs-progs: extent-tree: Add add_merge_cache_extent function
This add_merge_cache_extent() function will try to merge adjusted
cache_extent.
This is used for later btrfs-convert ext2 free space cache.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'extent-cache.c')
-rw-r--r-- | extent-cache.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/extent-cache.c b/extent-cache.c index d80aead6..38bed8b5 100644 --- a/extent-cache.c +++ b/extent-cache.c @@ -282,3 +282,60 @@ void free_extent_cache_tree(struct cache_tree *tree) { cache_tree_free_extents(tree, free_extent_cache); } + +int add_merge_cache_extent(struct cache_tree *tree, u64 start, u64 size) +{ + struct cache_extent *cache; + struct cache_extent *next = NULL; + struct cache_extent *prev = NULL; + int next_merged = 0; + int prev_merged = 0; + int ret = 0; + + if (cache_tree_empty(tree)) + goto insert; + + cache = search_cache_extent(tree, start); + if (!cache) { + /* + * Either the tree is completely empty, or the no range after + * start. + * Either way, the last cache_extent should be prev. + */ + prev = last_cache_extent(tree); + } else if (start <= cache->start) { + next = cache; + prev = prev_cache_extent(cache); + } else { + prev = cache; + next = next_cache_extent(cache); + } + + /* + * Ensure the range to be inserted won't cover with existings + * Or we will need extra loop to do merge + */ + BUG_ON(next && start + size > next->start); + BUG_ON(prev && prev->start + prev->size > start); + + if (next && start + size == next->start) { + next_merged = 1; + next->size = next->start + next->size - start; + next->start = start; + } + if (prev && prev->start + prev->size == start) { + prev_merged = 1; + if (next_merged) { + next->size = next->start + next->size - prev->start; + next->start = prev->start; + remove_cache_extent(tree, prev); + free(prev); + } else { + prev->size = start + size - prev->start; + } + } +insert: + if (!prev_merged && !next_merged) + ret = add_cache_extent(tree, start, size); + return ret; +} |