aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/mm/pat_rbtree.c34
-rw-r--r--include/linux/rbtree.h13
-rw-r--r--lib/rbtree.c116
3 files changed, 87 insertions, 76 deletions
diff --git a/arch/x86/mm/pat_rbtree.c b/arch/x86/mm/pat_rbtree.c
index f20eeec85a86..8acaddd0fb21 100644
--- a/arch/x86/mm/pat_rbtree.c
+++ b/arch/x86/mm/pat_rbtree.c
@@ -34,8 +34,7 @@
34 * memtype_lock protects the rbtree. 34 * memtype_lock protects the rbtree.
35 */ 35 */
36 36
37static void memtype_rb_augment_cb(struct rb_node *node); 37static struct rb_root memtype_rbroot = RB_ROOT;
38static struct rb_root memtype_rbroot = RB_AUGMENT_ROOT(&memtype_rb_augment_cb);
39 38
40static int is_node_overlap(struct memtype *node, u64 start, u64 end) 39static int is_node_overlap(struct memtype *node, u64 start, u64 end)
41{ 40{
@@ -56,7 +55,7 @@ static u64 get_subtree_max_end(struct rb_node *node)
56} 55}
57 56
58/* Update 'subtree_max_end' for a node, based on node and its children */ 57/* Update 'subtree_max_end' for a node, based on node and its children */
59static void update_node_max_end(struct rb_node *node) 58static void memtype_rb_augment_cb(struct rb_node *node, void *__unused)
60{ 59{
61 struct memtype *data; 60 struct memtype *data;
62 u64 max_end, child_max_end; 61 u64 max_end, child_max_end;
@@ -78,25 +77,6 @@ static void update_node_max_end(struct rb_node *node)
78 data->subtree_max_end = max_end; 77 data->subtree_max_end = max_end;
79} 78}
80 79
81/* Update 'subtree_max_end' for a node and all its ancestors */
82static void update_path_max_end(struct rb_node *node)
83{
84 u64 old_max_end, new_max_end;
85
86 while (node) {
87 struct memtype *data = container_of(node, struct memtype, rb);
88
89 old_max_end = data->subtree_max_end;
90 update_node_max_end(node);
91 new_max_end = data->subtree_max_end;
92
93 if (new_max_end == old_max_end)
94 break;
95
96 node = rb_parent(node);
97 }
98}
99
100/* Find the first (lowest start addr) overlapping range from rb tree */ 80/* Find the first (lowest start addr) overlapping range from rb tree */
101static struct memtype *memtype_rb_lowest_match(struct rb_root *root, 81static struct memtype *memtype_rb_lowest_match(struct rb_root *root,
102 u64 start, u64 end) 82 u64 start, u64 end)
@@ -190,12 +170,6 @@ failure:
190 return -EBUSY; 170 return -EBUSY;
191} 171}
192 172
193static void memtype_rb_augment_cb(struct rb_node *node)
194{
195 if (node)
196 update_path_max_end(node);
197}
198
199static void memtype_rb_insert(struct rb_root *root, struct memtype *newdata) 173static void memtype_rb_insert(struct rb_root *root, struct memtype *newdata)
200{ 174{
201 struct rb_node **node = &(root->rb_node); 175 struct rb_node **node = &(root->rb_node);
@@ -213,6 +187,7 @@ static void memtype_rb_insert(struct rb_root *root, struct memtype *newdata)
213 187
214 rb_link_node(&newdata->rb, parent, node); 188 rb_link_node(&newdata->rb, parent, node);
215 rb_insert_color(&newdata->rb, root); 189 rb_insert_color(&newdata->rb, root);
190 rb_augment_insert(&newdata->rb, memtype_rb_augment_cb, NULL);
216} 191}
217 192
218int rbt_memtype_check_insert(struct memtype *new, unsigned long *ret_type) 193int rbt_memtype_check_insert(struct memtype *new, unsigned long *ret_type)
@@ -234,13 +209,16 @@ int rbt_memtype_check_insert(struct memtype *new, unsigned long *ret_type)
234 209
235struct memtype *rbt_memtype_erase(u64 start, u64 end) 210struct memtype *rbt_memtype_erase(u64 start, u64 end)
236{ 211{
212 struct rb_node *deepest;
237 struct memtype *data; 213 struct memtype *data;
238 214
239 data = memtype_rb_exact_match(&memtype_rbroot, start, end); 215 data = memtype_rb_exact_match(&memtype_rbroot, start, end);
240 if (!data) 216 if (!data)
241 goto out; 217 goto out;
242 218
219 deepest = rb_augment_erase_begin(&data->rb);
243 rb_erase(&data->rb, &memtype_rbroot); 220 rb_erase(&data->rb, &memtype_rbroot);
221 rb_augment_erase_end(deepest, memtype_rb_augment_cb, NULL);
244out: 222out:
245 return data; 223 return data;
246} 224}
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h
index fe1872e5b37e..7066acb2c530 100644
--- a/include/linux/rbtree.h
+++ b/include/linux/rbtree.h
@@ -110,7 +110,6 @@ struct rb_node
110struct rb_root 110struct rb_root
111{ 111{
112 struct rb_node *rb_node; 112 struct rb_node *rb_node;
113 void (*augment_cb)(struct rb_node *node);
114}; 113};
115 114
116 115
@@ -130,9 +129,7 @@ static inline void rb_set_color(struct rb_node *rb, int color)
130 rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; 129 rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
131} 130}
132 131
133#define RB_ROOT (struct rb_root) { NULL, NULL, } 132#define RB_ROOT (struct rb_root) { NULL, }
134#define RB_AUGMENT_ROOT(x) (struct rb_root) { NULL, x}
135
136#define rb_entry(ptr, type, member) container_of(ptr, type, member) 133#define rb_entry(ptr, type, member) container_of(ptr, type, member)
137 134
138#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) 135#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
@@ -142,6 +139,14 @@ static inline void rb_set_color(struct rb_node *rb, int color)
142extern void rb_insert_color(struct rb_node *, struct rb_root *); 139extern void rb_insert_color(struct rb_node *, struct rb_root *);
143extern void rb_erase(struct rb_node *, struct rb_root *); 140extern void rb_erase(struct rb_node *, struct rb_root *);
144 141
142typedef void (*rb_augment_f)(struct rb_node *node, void *data);
143
144extern void rb_augment_insert(struct rb_node *node,
145 rb_augment_f func, void *data);
146extern struct rb_node *rb_augment_erase_begin(struct rb_node *node);
147extern void rb_augment_erase_end(struct rb_node *node,
148 rb_augment_f func, void *data);
149
145/* Find logical next and previous nodes in a tree */ 150/* Find logical next and previous nodes in a tree */
146extern struct rb_node *rb_next(const struct rb_node *); 151extern struct rb_node *rb_next(const struct rb_node *);
147extern struct rb_node *rb_prev(const struct rb_node *); 152extern struct rb_node *rb_prev(const struct rb_node *);
diff --git a/lib/rbtree.c b/lib/rbtree.c
index 15e10b1afdd2..4693f79195d3 100644
--- a/lib/rbtree.c
+++ b/lib/rbtree.c
@@ -44,11 +44,6 @@ static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
44 else 44 else
45 root->rb_node = right; 45 root->rb_node = right;
46 rb_set_parent(node, right); 46 rb_set_parent(node, right);
47
48 if (root->augment_cb) {
49 root->augment_cb(node);
50 root->augment_cb(right);
51 }
52} 47}
53 48
54static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) 49static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
@@ -72,20 +67,12 @@ static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
72 else 67 else
73 root->rb_node = left; 68 root->rb_node = left;
74 rb_set_parent(node, left); 69 rb_set_parent(node, left);
75
76 if (root->augment_cb) {
77 root->augment_cb(node);
78 root->augment_cb(left);
79 }
80} 70}
81 71
82void rb_insert_color(struct rb_node *node, struct rb_root *root) 72void rb_insert_color(struct rb_node *node, struct rb_root *root)
83{ 73{
84 struct rb_node *parent, *gparent; 74 struct rb_node *parent, *gparent;
85 75
86 if (root->augment_cb)
87 root->augment_cb(node);
88
89 while ((parent = rb_parent(node)) && rb_is_red(parent)) 76 while ((parent = rb_parent(node)) && rb_is_red(parent))
90 { 77 {
91 gparent = rb_parent(parent); 78 gparent = rb_parent(parent);
@@ -240,15 +227,12 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
240 else 227 else
241 { 228 {
242 struct rb_node *old = node, *left; 229 struct rb_node *old = node, *left;
243 int old_parent_cb = 0;
244 int successor_parent_cb = 0;
245 230
246 node = node->rb_right; 231 node = node->rb_right;
247 while ((left = node->rb_left) != NULL) 232 while ((left = node->rb_left) != NULL)
248 node = left; 233 node = left;
249 234
250 if (rb_parent(old)) { 235 if (rb_parent(old)) {
251 old_parent_cb = 1;
252 if (rb_parent(old)->rb_left == old) 236 if (rb_parent(old)->rb_left == old)
253 rb_parent(old)->rb_left = node; 237 rb_parent(old)->rb_left = node;
254 else 238 else
@@ -263,10 +247,8 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
263 if (parent == old) { 247 if (parent == old) {
264 parent = node; 248 parent = node;
265 } else { 249 } else {
266 successor_parent_cb = 1;
267 if (child) 250 if (child)
268 rb_set_parent(child, parent); 251 rb_set_parent(child, parent);
269
270 parent->rb_left = child; 252 parent->rb_left = child;
271 253
272 node->rb_right = old->rb_right; 254 node->rb_right = old->rb_right;
@@ -277,24 +259,6 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
277 node->rb_left = old->rb_left; 259 node->rb_left = old->rb_left;
278 rb_set_parent(old->rb_left, node); 260 rb_set_parent(old->rb_left, node);
279 261
280 if (root->augment_cb) {
281 /*
282 * Here, three different nodes can have new children.
283 * The parent of the successor node that was selected
284 * to replace the node to be erased.
285 * The node that is getting erased and is now replaced
286 * by its successor.
287 * The parent of the node getting erased-replaced.
288 */
289 if (successor_parent_cb)
290 root->augment_cb(parent);
291
292 root->augment_cb(node);
293
294 if (old_parent_cb)
295 root->augment_cb(rb_parent(old));
296 }
297
298 goto color; 262 goto color;
299 } 263 }
300 264
@@ -303,19 +267,15 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
303 267
304 if (child) 268 if (child)
305 rb_set_parent(child, parent); 269 rb_set_parent(child, parent);
306 270 if (parent)
307 if (parent) { 271 {
308 if (parent->rb_left == node) 272 if (parent->rb_left == node)
309 parent->rb_left = child; 273 parent->rb_left = child;
310 else 274 else
311 parent->rb_right = child; 275 parent->rb_right = child;
312
313 if (root->augment_cb)
314 root->augment_cb(parent);
315
316 } else {
317 root->rb_node = child;
318 } 276 }
277 else
278 root->rb_node = child;
319 279
320 color: 280 color:
321 if (color == RB_BLACK) 281 if (color == RB_BLACK)
@@ -323,6 +283,74 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
323} 283}
324EXPORT_SYMBOL(rb_erase); 284EXPORT_SYMBOL(rb_erase);
325 285
286static void rb_augment_path(struct rb_node *node, rb_augment_f func, void *data)
287{
288 struct rb_node *parent;
289
290up:
291 func(node, data);
292 parent = rb_parent(node);
293 if (!parent)
294 return;
295
296 if (node == parent->rb_left && parent->rb_right)
297 func(parent->rb_right, data);
298 else if (parent->rb_left)
299 func(parent->rb_left, data);
300
301 node = parent;
302 goto up;
303}
304
305/*
306 * after inserting @node into the tree, update the tree to account for
307 * both the new entry and any damage done by rebalance
308 */
309void rb_augment_insert(struct rb_node *node, rb_augment_f func, void *data)
310{
311 if (node->rb_left)
312 node = node->rb_left;
313 else if (node->rb_right)
314 node = node->rb_right;
315
316 rb_augment_path(node, func, data);
317}
318
319/*
320 * before removing the node, find the deepest node on the rebalance path
321 * that will still be there after @node gets removed
322 */
323struct rb_node *rb_augment_erase_begin(struct rb_node *node)
324{
325 struct rb_node *deepest;
326
327 if (!node->rb_right && !node->rb_left)
328 deepest = rb_parent(node);
329 else if (!node->rb_right)
330 deepest = node->rb_left;
331 else if (!node->rb_left)
332 deepest = node->rb_right;
333 else {
334 deepest = rb_next(node);
335 if (deepest->rb_right)
336 deepest = deepest->rb_right;
337 else if (rb_parent(deepest) != node)
338 deepest = rb_parent(deepest);
339 }
340
341 return deepest;
342}
343
344/*
345 * after removal, update the tree to account for the removed entry
346 * and any rebalance damage.
347 */
348void rb_augment_erase_end(struct rb_node *node, rb_augment_f func, void *data)
349{
350 if (node)
351 rb_augment_path(node, func, data);
352}
353
326/* 354/*
327 * This function returns the first node (in sort order) of the tree. 355 * This function returns the first node (in sort order) of the tree.
328 */ 356 */