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
;
99 struct cache_extent
*entry
;
101 found
= tree_insert(&tree
->root
, pe
->start
, pe
->size
, &pe
->rb_node
);
103 entry
= rb_entry(found
, struct cache_extent
, rb_node
);
109 int insert_cache_extent(struct cache_tree
*tree
, u64 start
, u64 size
)
111 struct cache_extent
*pe
= alloc_cache_extent(start
, size
);
113 ret
= insert_existing_cache_extent(tree
, pe
);
119 struct cache_extent
*find_cache_extent(struct cache_tree
*tree
,
122 struct rb_node
*prev
;
124 struct cache_extent
*entry
;
125 ret
= __tree_search(&tree
->root
, start
, size
, &prev
);
129 entry
= rb_entry(ret
, struct cache_extent
, rb_node
);
133 struct cache_extent
*find_first_cache_extent(struct cache_tree
*tree
,
136 struct rb_node
*prev
;
138 struct cache_extent
*entry
;
140 ret
= __tree_search(&tree
->root
, start
, 1, &prev
);
145 entry
= rb_entry(ret
, struct cache_extent
, rb_node
);
149 struct cache_extent
*prev_cache_extent(struct cache_extent
*pe
)
151 struct rb_node
*node
= rb_prev(&pe
->rb_node
);
155 return rb_entry(node
, struct cache_extent
, rb_node
);
158 struct cache_extent
*next_cache_extent(struct cache_extent
*pe
)
160 struct rb_node
*node
= rb_next(&pe
->rb_node
);
164 return rb_entry(node
, struct cache_extent
, rb_node
);
167 void remove_cache_extent(struct cache_tree
*tree
,
168 struct cache_extent
*pe
)
170 rb_erase(&pe
->rb_node
, &tree
->root
);