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"
23 void cache_tree_init(struct cache_tree
*tree
)
25 tree
->root
.rb_node
= NULL
;
28 static struct rb_node
*tree_insert(struct rb_root
*root
, u64 offset
,
29 u64 size
, struct rb_node
*node
)
31 struct rb_node
** p
= &root
->rb_node
;
32 struct rb_node
* parent
= NULL
;
33 struct cache_extent
*entry
;
37 entry
= rb_entry(parent
, struct cache_extent
, rb_node
);
39 if (offset
+ size
<= entry
->start
)
41 else if (offset
>= entry
->start
+ entry
->size
)
47 entry
= rb_entry(parent
, struct cache_extent
, rb_node
);
48 rb_link_node(node
, parent
, p
);
49 rb_insert_color(node
, root
);
53 static struct rb_node
*__tree_search(struct rb_root
*root
, u64 offset
,
54 u64 size
, struct rb_node
**prev_ret
)
56 struct rb_node
* n
= root
->rb_node
;
57 struct rb_node
*prev
= NULL
;
58 struct cache_extent
*entry
;
59 struct cache_extent
*prev_entry
= NULL
;
62 entry
= rb_entry(n
, struct cache_extent
, rb_node
);
66 if (offset
+ size
<= entry
->start
)
68 else if (offset
>= entry
->start
+ entry
->size
)
76 while(prev
&& offset
>= prev_entry
->start
+ prev_entry
->size
) {
78 prev_entry
= rb_entry(prev
, struct cache_extent
, rb_node
);
84 struct cache_extent
*alloc_cache_extent(u64 start
, u64 size
)
86 struct cache_extent
*pe
= malloc(sizeof(*pe
));
95 int insert_existing_cache_extent(struct cache_tree
*tree
,
96 struct cache_extent
*pe
)
98 struct rb_node
*found
;
100 found
= tree_insert(&tree
->root
, pe
->start
, pe
->size
, &pe
->rb_node
);
107 int insert_cache_extent(struct cache_tree
*tree
, u64 start
, u64 size
)
109 struct cache_extent
*pe
= alloc_cache_extent(start
, size
);
111 ret
= insert_existing_cache_extent(tree
, pe
);
117 struct cache_extent
*find_cache_extent(struct cache_tree
*tree
,
120 struct rb_node
*prev
;
122 struct cache_extent
*entry
;
123 ret
= __tree_search(&tree
->root
, start
, size
, &prev
);
127 entry
= rb_entry(ret
, struct cache_extent
, rb_node
);
131 struct cache_extent
*find_first_cache_extent(struct cache_tree
*tree
,
134 struct rb_node
*prev
;
136 struct cache_extent
*entry
;
138 ret
= __tree_search(&tree
->root
, start
, 1, &prev
);
143 entry
= rb_entry(ret
, struct cache_extent
, rb_node
);
147 struct cache_extent
*prev_cache_extent(struct cache_extent
*pe
)
149 struct rb_node
*node
= rb_prev(&pe
->rb_node
);
153 return rb_entry(node
, struct cache_extent
, rb_node
);
156 struct cache_extent
*next_cache_extent(struct cache_extent
*pe
)
158 struct rb_node
*node
= rb_next(&pe
->rb_node
);
162 return rb_entry(node
, struct cache_extent
, rb_node
);
165 void remove_cache_extent(struct cache_tree
*tree
,
166 struct cache_extent
*pe
)
168 rb_erase(&pe
->rb_node
, &tree
->root
);