rbtree: Add support for augmented rbtrees

Add support for augmented rbtrees in core rbtree code.

This will be used in subsequent patches, in x86 PAT code, which needs
interval trees to efficiently keep track of PAT ranges.

Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
LKML-Reference: <20100210232343.GA11465@linux-os.sc.intel.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>

authored by Pallipadi, Venkatesh and committed by H. Peter Anvin 17d9ddc7 724e6d3f

+106 -5
+58
Documentation/rbtree.txt
··· 190 for (node = rb_first(&mytree); node; node = rb_next(node)) 191 printk("key=%s\n", rb_entry(node, struct mytype, node)->keystring); 192
··· 190 for (node = rb_first(&mytree); node; node = rb_next(node)) 191 printk("key=%s\n", rb_entry(node, struct mytype, node)->keystring); 192 193 + Support for Augmented rbtrees 194 + ----------------------------- 195 + 196 + Augmented rbtree is an rbtree with "some" additional data stored in each node. 197 + This data can be used to augment some new functionality to rbtree. 198 + Augmented rbtree is an optional feature built on top of basic rbtree 199 + infrastructure. rbtree user who wants this feature will have an augment 200 + callback function in rb_root initialized. 201 + 202 + This callback function will be called from rbtree core routines whenever 203 + a node has a change in one or both of its children. It is the responsibility 204 + of the callback function to recalculate the additional data that is in the 205 + rb node using new children information. Note that if this new additional 206 + data affects the parent node's additional data, then callback function has 207 + to handle it and do the recursive updates. 208 + 209 + 210 + Interval tree is an example of augmented rb tree. Reference - 211 + "Introduction to Algorithms" by Cormen, Leiserson, Rivest and Stein. 212 + More details about interval trees: 213 + 214 + Classical rbtree has a single key and it cannot be directly used to store 215 + interval ranges like [lo:hi] and do a quick lookup for any overlap with a new 216 + lo:hi or to find whether there is an exact match for a new lo:hi. 217 + 218 + However, rbtree can be augmented to store such interval ranges in a structured 219 + way making it possible to do efficient lookup and exact match. 220 + 221 + This "extra information" stored in each node is the maximum hi 222 + (max_hi) value among all the nodes that are its descendents. This 223 + information can be maintained at each node just be looking at the node 224 + and its immediate children. And this will be used in O(log n) lookup 225 + for lowest match (lowest start address among all possible matches) 226 + with something like: 227 + 228 + find_lowest_match(lo, hi, node) 229 + { 230 + lowest_match = NULL; 231 + while (node) { 232 + if (max_hi(node->left) > lo) { 233 + // Lowest overlap if any must be on left side 234 + node = node->left; 235 + } else if (overlap(lo, hi, node)) { 236 + lowest_match = node; 237 + break; 238 + } else if (lo > node->lo) { 239 + // Lowest overlap if any must be on right side 240 + node = node->right; 241 + } else { 242 + break; 243 + } 244 + } 245 + return lowest_match; 246 + } 247 + 248 + Finding exact match will be to first find lowest match and then to follow 249 + successor nodes looking for exact match, until the start of a node is beyond 250 + the hi value we are looking for.
+4 -1
include/linux/rbtree.h
··· 110 struct rb_root 111 { 112 struct rb_node *rb_node; 113 }; 114 115 ··· 130 rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; 131 } 132 133 - #define RB_ROOT (struct rb_root) { NULL, } 134 #define rb_entry(ptr, type, member) container_of(ptr, type, member) 135 136 #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
··· 110 struct rb_root 111 { 112 struct rb_node *rb_node; 113 + void (*augment_cb)(struct rb_node *node); 114 }; 115 116 ··· 129 rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; 130 } 131 132 + #define RB_ROOT (struct rb_root) { NULL, NULL, } 133 + #define RB_AUGMENT_ROOT(x) (struct rb_root) { NULL, x} 134 + 135 #define rb_entry(ptr, type, member) container_of(ptr, type, member) 136 137 #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
+44 -4
lib/rbtree.c
··· 44 else 45 root->rb_node = right; 46 rb_set_parent(node, right); 47 } 48 49 static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) ··· 72 else 73 root->rb_node = left; 74 rb_set_parent(node, left); 75 } 76 77 void rb_insert_color(struct rb_node *node, struct rb_root *root) 78 { 79 struct rb_node *parent, *gparent; 80 81 while ((parent = rb_parent(node)) && rb_is_red(parent)) 82 { ··· 240 else 241 { 242 struct rb_node *old = node, *left; 243 244 node = node->rb_right; 245 while ((left = node->rb_left) != NULL) 246 node = left; 247 248 if (rb_parent(old)) { 249 if (rb_parent(old)->rb_left == old) 250 rb_parent(old)->rb_left = node; 251 else ··· 263 if (parent == old) { 264 parent = node; 265 } else { 266 if (child) 267 rb_set_parent(child, parent); 268 parent->rb_left = child; 269 270 node->rb_right = old->rb_right; ··· 277 node->rb_left = old->rb_left; 278 rb_set_parent(old->rb_left, node); 279 280 goto color; 281 } 282 ··· 303 304 if (child) 305 rb_set_parent(child, parent); 306 - if (parent) 307 - { 308 if (parent->rb_left == node) 309 parent->rb_left = child; 310 else 311 parent->rb_right = child; 312 - } 313 - else 314 root->rb_node = child; 315 316 color: 317 if (color == RB_BLACK)
··· 44 else 45 root->rb_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 } 53 54 static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) ··· 67 else 68 root->rb_node = left; 69 rb_set_parent(node, left); 70 + 71 + if (root->augment_cb) { 72 + root->augment_cb(node); 73 + root->augment_cb(left); 74 + } 75 } 76 77 void rb_insert_color(struct rb_node *node, struct rb_root *root) 78 { 79 struct rb_node *parent, *gparent; 80 + 81 + if (root->augment_cb) 82 + root->augment_cb(node); 83 84 while ((parent = rb_parent(node)) && rb_is_red(parent)) 85 { ··· 227 else 228 { 229 struct rb_node *old = node, *left; 230 + int old_parent_cb = 0; 231 + int successor_parent_cb = 0; 232 233 node = node->rb_right; 234 while ((left = node->rb_left) != NULL) 235 node = left; 236 237 if (rb_parent(old)) { 238 + old_parent_cb = 1; 239 if (rb_parent(old)->rb_left == old) 240 rb_parent(old)->rb_left = node; 241 else ··· 247 if (parent == old) { 248 parent = node; 249 } else { 250 + successor_parent_cb = 1; 251 if (child) 252 rb_set_parent(child, parent); 253 + 254 parent->rb_left = child; 255 256 node->rb_right = old->rb_right; ··· 259 node->rb_left = old->rb_left; 260 rb_set_parent(old->rb_left, node); 261 262 + if (root->augment_cb) { 263 + /* 264 + * Here, three different nodes can have new children. 265 + * The parent of the successor node that was selected 266 + * to replace the node to be erased. 267 + * The node that is getting erased and is now replaced 268 + * by its successor. 269 + * The parent of the node getting erased-replaced. 270 + */ 271 + if (successor_parent_cb) 272 + root->augment_cb(parent); 273 + 274 + root->augment_cb(node); 275 + 276 + if (old_parent_cb) 277 + root->augment_cb(rb_parent(old)); 278 + } 279 + 280 goto color; 281 } 282 ··· 267 268 if (child) 269 rb_set_parent(child, parent); 270 + 271 + if (parent) { 272 if (parent->rb_left == node) 273 parent->rb_left = child; 274 else 275 parent->rb_right = child; 276 + 277 + if (root->augment_cb) 278 + root->augment_cb(parent); 279 + 280 + } else { 281 root->rb_node = child; 282 + } 283 284 color: 285 if (color == RB_BLACK)