2 * Copyright (C) 2007 Oracle. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
20 #include "kerncompat.h"
21 #include "extent-cache.h"
22 #include "rbtree-utils.h"
24 struct cache_extent_search_range {
30 static int cache_tree_comp_range(struct rb_node *node, void *data)
32 struct cache_extent *entry;
33 struct cache_extent_search_range *range;
35 range = (struct cache_extent_search_range *)data;
36 entry = rb_entry(node, struct cache_extent, rb_node);
38 if (entry->start + entry->size <= range->start)
40 else if (range->start + range->size <= entry->start)
46 static int cache_tree_comp_nodes(struct rb_node *node1, struct rb_node *node2)
48 struct cache_extent *entry;
49 struct cache_extent_search_range range;
51 entry = rb_entry(node2, struct cache_extent, rb_node);
52 range.start = entry->start;
53 range.size = entry->size;
55 return cache_tree_comp_range(node1, (void *)&range);
58 static int cache_tree_comp_range2(struct rb_node *node, void *data)
60 struct cache_extent *entry;
61 struct cache_extent_search_range *range;
63 range = (struct cache_extent_search_range *)data;
64 entry = rb_entry(node, struct cache_extent, rb_node);
66 if (entry->objectid < range->objectid)
68 else if (entry->objectid > range->objectid)
70 else if (entry->start + entry->size <= range->start)
72 else if (range->start + range->size <= entry->start)
78 static int cache_tree_comp_nodes2(struct rb_node *node1, struct rb_node *node2)
80 struct cache_extent *entry;
81 struct cache_extent_search_range range;
83 entry = rb_entry(node2, struct cache_extent, rb_node);
84 range.objectid = entry->objectid;
85 range.start = entry->start;
86 range.size = entry->size;
88 return cache_tree_comp_range2(node1, (void *)&range);
91 void cache_tree_init(struct cache_tree *tree)
96 static struct cache_extent *
97 alloc_cache_extent(u64 objectid, u64 start, u64 size)
99 struct cache_extent *pe = malloc(sizeof(*pe));
104 pe->objectid = objectid;
110 static int __add_cache_extent(struct cache_tree *tree,
111 u64 objectid, u64 start, u64 size)
113 struct cache_extent *pe = alloc_cache_extent(objectid, start, size);
117 fprintf(stderr, "memory allocation failed\n");
121 ret = insert_cache_extent(tree, pe);
128 int add_cache_extent(struct cache_tree *tree, u64 start, u64 size)
130 return __add_cache_extent(tree, 0, start, size);
133 int add_cache_extent2(struct cache_tree *tree,
134 u64 objectid, u64 start, u64 size)
136 return __add_cache_extent(tree, objectid, start, size);
139 int insert_cache_extent(struct cache_tree *tree, struct cache_extent *pe)
141 return rb_insert(&tree->root, &pe->rb_node, cache_tree_comp_nodes);
144 int insert_cache_extent2(struct cache_tree *tree, struct cache_extent *pe)
146 return rb_insert(&tree->root, &pe->rb_node, cache_tree_comp_nodes2);
149 struct cache_extent *lookup_cache_extent(struct cache_tree *tree,
152 struct rb_node *node;
153 struct cache_extent *entry;
154 struct cache_extent_search_range range;
158 node = rb_search(&tree->root, &range, cache_tree_comp_range, NULL);
162 entry = rb_entry(node, struct cache_extent, rb_node);
166 struct cache_extent *lookup_cache_extent2(struct cache_tree *tree,
167 u64 objectid, u64 start, u64 size)
169 struct rb_node *node;
170 struct cache_extent *entry;
171 struct cache_extent_search_range range;
173 range.objectid = objectid;
176 node = rb_search(&tree->root, &range, cache_tree_comp_range2, NULL);
180 entry = rb_entry(node, struct cache_extent, rb_node);
184 struct cache_extent *search_cache_extent(struct cache_tree *tree, u64 start)
186 struct rb_node *next;
187 struct rb_node *node;
188 struct cache_extent *entry;
189 struct cache_extent_search_range range;
193 node = rb_search(&tree->root, &range, cache_tree_comp_range, &next);
199 entry = rb_entry(node, struct cache_extent, rb_node);
203 struct cache_extent *search_cache_extent2(struct cache_tree *tree,
204 u64 objectid, u64 start)
206 struct rb_node *next;
207 struct rb_node *node;
208 struct cache_extent *entry;
209 struct cache_extent_search_range range;
211 range.objectid = objectid;
214 node = rb_search(&tree->root, &range, cache_tree_comp_range2, &next);
220 entry = rb_entry(node, struct cache_extent, rb_node);
224 struct cache_extent *first_cache_extent(struct cache_tree *tree)
226 struct rb_node *node = rb_first(&tree->root);
230 return rb_entry(node, struct cache_extent, rb_node);
233 struct cache_extent *last_cache_extent(struct cache_tree *tree)
235 struct rb_node *node = rb_last(&tree->root);
239 return rb_entry(node, struct cache_extent, rb_node);
242 struct cache_extent *prev_cache_extent(struct cache_extent *pe)
244 struct rb_node *node = rb_prev(&pe->rb_node);
248 return rb_entry(node, struct cache_extent, rb_node);
251 struct cache_extent *next_cache_extent(struct cache_extent *pe)
253 struct rb_node *node = rb_next(&pe->rb_node);
257 return rb_entry(node, struct cache_extent, rb_node);
260 void remove_cache_extent(struct cache_tree *tree, struct cache_extent *pe)
262 rb_erase(&pe->rb_node, &tree->root);
265 void cache_tree_free_extents(struct cache_tree *tree,
266 free_cache_extent free_func)
268 struct cache_extent *ce;
270 while ((ce = first_cache_extent(tree))) {
271 remove_cache_extent(tree, ce);
276 static void free_extent_cache(struct cache_extent *pe)
281 void free_extent_cache_tree(struct cache_tree *tree)
283 cache_tree_free_extents(tree, free_extent_cache);
286 int add_merge_cache_extent(struct cache_tree *tree, u64 start, u64 size)
288 struct cache_extent *cache;
289 struct cache_extent *next = NULL;
290 struct cache_extent *prev = NULL;
295 if (cache_tree_empty(tree))
298 cache = search_cache_extent(tree, start);
301 * Either the tree is completely empty, or the no range after
303 * Either way, the last cache_extent should be prev.
305 prev = last_cache_extent(tree);
306 } else if (start <= cache->start) {
308 prev = prev_cache_extent(cache);
311 next = next_cache_extent(cache);
315 * Ensure the range to be inserted won't cover with existings
316 * Or we will need extra loop to do merge
318 BUG_ON(next && start + size > next->start);
319 BUG_ON(prev && prev->start + prev->size > start);
321 if (next && start + size == next->start) {
323 next->size = next->start + next->size - start;
326 if (prev && prev->start + prev->size == start) {
329 next->size = next->start + next->size - prev->start;
330 next->start = prev->start;
331 remove_cache_extent(tree, prev);
334 prev->size = start + size - prev->start;
338 if (!prev_merged && !next_merged)
339 ret = add_cache_extent(tree, start, size);