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
*alloc_cache_extent(u64 start
, u64 size
)
98 struct cache_extent
*pe
= malloc(sizeof(*pe
));
109 int add_cache_extent(struct cache_tree
*tree
, u64 start
, u64 size
)
111 struct cache_extent
*pe
= alloc_cache_extent(start
, size
);
115 fprintf(stderr
, "memory allocation failed\n");
119 ret
= insert_cache_extent(tree
, pe
);
126 int insert_cache_extent(struct cache_tree
*tree
, struct cache_extent
*pe
)
128 return rb_insert(&tree
->root
, &pe
->rb_node
, cache_tree_comp_nodes
);
131 int insert_cache_extent2(struct cache_tree
*tree
, struct cache_extent
*pe
)
133 return rb_insert(&tree
->root
, &pe
->rb_node
, cache_tree_comp_nodes2
);
136 struct cache_extent
*lookup_cache_extent(struct cache_tree
*tree
,
139 struct rb_node
*node
;
140 struct cache_extent
*entry
;
141 struct cache_extent_search_range range
;
145 node
= rb_search(&tree
->root
, &range
, cache_tree_comp_range
, NULL
);
149 entry
= rb_entry(node
, struct cache_extent
, rb_node
);
153 struct cache_extent
*lookup_cache_extent2(struct cache_tree
*tree
,
154 u64 objectid
, u64 start
, u64 size
)
156 struct rb_node
*node
;
157 struct cache_extent
*entry
;
158 struct cache_extent_search_range range
;
160 range
.objectid
= objectid
;
163 node
= rb_search(&tree
->root
, &range
, cache_tree_comp_range2
, NULL
);
167 entry
= rb_entry(node
, struct cache_extent
, rb_node
);
171 struct cache_extent
*search_cache_extent(struct cache_tree
*tree
, u64 start
)
173 struct rb_node
*next
;
174 struct rb_node
*node
;
175 struct cache_extent
*entry
;
176 struct cache_extent_search_range range
;
180 node
= rb_search(&tree
->root
, &range
, cache_tree_comp_range
, &next
);
186 entry
= rb_entry(node
, struct cache_extent
, rb_node
);
190 struct cache_extent
*search_cache_extent2(struct cache_tree
*tree
,
191 u64 objectid
, u64 start
)
193 struct rb_node
*next
;
194 struct rb_node
*node
;
195 struct cache_extent
*entry
;
196 struct cache_extent_search_range range
;
198 range
.objectid
= objectid
;
201 node
= rb_search(&tree
->root
, &range
, cache_tree_comp_range2
, &next
);
207 entry
= rb_entry(node
, struct cache_extent
, rb_node
);
211 struct cache_extent
*first_cache_extent(struct cache_tree
*tree
)
213 struct rb_node
*node
= rb_first(&tree
->root
);
217 return rb_entry(node
, struct cache_extent
, rb_node
);
220 struct cache_extent
*last_cache_extent(struct cache_tree
*tree
)
222 struct rb_node
*node
= rb_last(&tree
->root
);
226 return rb_entry(node
, struct cache_extent
, rb_node
);
229 struct cache_extent
*prev_cache_extent(struct cache_extent
*pe
)
231 struct rb_node
*node
= rb_prev(&pe
->rb_node
);
235 return rb_entry(node
, struct cache_extent
, rb_node
);
238 struct cache_extent
*next_cache_extent(struct cache_extent
*pe
)
240 struct rb_node
*node
= rb_next(&pe
->rb_node
);
244 return rb_entry(node
, struct cache_extent
, rb_node
);
247 void remove_cache_extent(struct cache_tree
*tree
, struct cache_extent
*pe
)
249 rb_erase(&pe
->rb_node
, &tree
->root
);
252 void cache_tree_free_extents(struct cache_tree
*tree
,
253 free_cache_extent free_func
)
255 struct cache_extent
*ce
;
257 while ((ce
= first_cache_extent(tree
))) {
258 remove_cache_extent(tree
, ce
);
263 static void free_extent_cache(struct cache_extent
*pe
)
268 void free_extent_cache_tree(struct cache_tree
*tree
)
270 cache_tree_free_extents(tree
, free_extent_cache
);
273 int add_merge_cache_extent(struct cache_tree
*tree
, u64 start
, u64 size
)
275 struct cache_extent
*cache
;
276 struct cache_extent
*next
= NULL
;
277 struct cache_extent
*prev
= NULL
;
282 if (cache_tree_empty(tree
))
285 cache
= search_cache_extent(tree
, start
);
288 * Either the tree is completely empty, or the no range after
290 * Either way, the last cache_extent should be prev.
292 prev
= last_cache_extent(tree
);
293 } else if (start
<= cache
->start
) {
295 prev
= prev_cache_extent(cache
);
298 next
= next_cache_extent(cache
);
302 * Ensure the range to be inserted won't cover with existings
303 * Or we will need extra loop to do merge
305 BUG_ON(next
&& start
+ size
> next
->start
);
306 BUG_ON(prev
&& prev
->start
+ prev
->size
> start
);
308 if (next
&& start
+ size
== next
->start
) {
310 next
->size
= next
->start
+ next
->size
- start
;
313 if (prev
&& prev
->start
+ prev
->size
== start
) {
316 next
->size
= next
->start
+ next
->size
- prev
->start
;
317 next
->start
= prev
->start
;
318 remove_cache_extent(tree
, prev
);
321 prev
->size
= start
+ size
- prev
->start
;
325 if (!prev_merged
&& !next_merged
)
326 ret
= add_cache_extent(tree
, start
, size
);