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
);