1e358b4fbSSasha Levin #include <kvm/rbtree-interval.h> 2e358b4fbSSasha Levin #include <stddef.h> 3495fbd4eSSasha Levin #include <errno.h> 4e358b4fbSSasha Levin 5e358b4fbSSasha Levin struct rb_int_node *rb_int_search_single(struct rb_root *root, u64 point) 6e358b4fbSSasha Levin { 7e358b4fbSSasha Levin struct rb_node *node = root->rb_node; 8e358b4fbSSasha Levin 9e358b4fbSSasha Levin while (node) { 10e358b4fbSSasha Levin struct rb_int_node *cur = rb_int(node); 11e358b4fbSSasha Levin 12*ffc83de3SMichel Lespinasse if (point < cur->low) 13e358b4fbSSasha Levin node = node->rb_left; 14*ffc83de3SMichel Lespinasse else if (cur->high <= point) 15e358b4fbSSasha Levin node = node->rb_right; 16*ffc83de3SMichel Lespinasse else 17*ffc83de3SMichel Lespinasse return cur; 18e358b4fbSSasha Levin } 19e358b4fbSSasha Levin 20e358b4fbSSasha Levin return NULL; 21e358b4fbSSasha Levin } 22e358b4fbSSasha Levin 23e358b4fbSSasha Levin struct rb_int_node *rb_int_search_range(struct rb_root *root, u64 low, u64 high) 24e358b4fbSSasha Levin { 25e358b4fbSSasha Levin struct rb_int_node *range; 26e358b4fbSSasha Levin 27e358b4fbSSasha Levin range = rb_int_search_single(root, low); 28e358b4fbSSasha Levin if (range == NULL) 29e358b4fbSSasha Levin return NULL; 30e358b4fbSSasha Levin 31e358b4fbSSasha Levin /* We simply verify that 'high' is smaller than the end of the range where 'low' is located */ 32e358b4fbSSasha Levin if (range->high < high) 33e358b4fbSSasha Levin return NULL; 34e358b4fbSSasha Levin 35e358b4fbSSasha Levin return range; 36e358b4fbSSasha Levin } 37e358b4fbSSasha Levin 3886824900SIngo Molnar /* 3986824900SIngo Molnar * Update a node after it has been linked into the tree: 4086824900SIngo Molnar */ 4186824900SIngo Molnar static void propagate_callback(struct rb_node *node, struct rb_node *stop) 42e358b4fbSSasha Levin { 43c59e43aaSKirill A. Shutemov struct rb_int_node *i_node; 44e358b4fbSSasha Levin 45c59e43aaSKirill A. Shutemov if (node == stop) 46c59e43aaSKirill A. Shutemov return; 47c59e43aaSKirill A. Shutemov 48c59e43aaSKirill A. Shutemov i_node = rb_int(node); 49e358b4fbSSasha Levin i_node->max_high = i_node->high; 50e358b4fbSSasha Levin 51e358b4fbSSasha Levin if (node->rb_left) 529f112becSSasha Levin i_node->max_high = max(i_node->max_high, rb_int(node->rb_left)->max_high); 53e358b4fbSSasha Levin if (node->rb_right) 549f112becSSasha Levin i_node->max_high = max(i_node->max_high, rb_int(node->rb_right)->max_high); 55e358b4fbSSasha Levin } 56e358b4fbSSasha Levin 5786824900SIngo Molnar /* 5886824900SIngo Molnar * Copy the extra data to a new node: 5986824900SIngo Molnar */ 6086824900SIngo Molnar static void copy_callback(struct rb_node *node_old, struct rb_node *node_new) 6186824900SIngo Molnar { 6286824900SIngo Molnar struct rb_int_node *i_node_old = rb_int(node_old); 6386824900SIngo Molnar struct rb_int_node *i_node_new = rb_int(node_new); 6486824900SIngo Molnar 6586824900SIngo Molnar i_node_new->low = i_node_old->low; 6686824900SIngo Molnar i_node_new->high = i_node_old->high; 6786824900SIngo Molnar 6886824900SIngo Molnar i_node_new->max_high = i_node_old->max_high; 6986824900SIngo Molnar } 7086824900SIngo Molnar 7186824900SIngo Molnar /* 7286824900SIngo Molnar * Update after tree rotation: 7386824900SIngo Molnar */ 7486824900SIngo Molnar static void rotate_callback(struct rb_node *node_old, struct rb_node *node_new) 7586824900SIngo Molnar { 7686824900SIngo Molnar propagate_callback(node_old, NULL); 7786824900SIngo Molnar propagate_callback(node_new, NULL); 7886824900SIngo Molnar } 7986824900SIngo Molnar 8086824900SIngo Molnar /* 8186824900SIngo Molnar * All augmented rbtree callbacks: 8286824900SIngo Molnar */ 8386824900SIngo Molnar struct rb_augment_callbacks callbacks = { 8486824900SIngo Molnar .propagate = propagate_callback, 8586824900SIngo Molnar .copy = copy_callback, 8686824900SIngo Molnar .rotate = rotate_callback, 8786824900SIngo Molnar }; 8886824900SIngo Molnar 89e358b4fbSSasha Levin int rb_int_insert(struct rb_root *root, struct rb_int_node *i_node) 90e358b4fbSSasha Levin { 9186824900SIngo Molnar struct rb_node **node = &root->rb_node, *parent = NULL; 92e358b4fbSSasha Levin 93e358b4fbSSasha Levin while (*node) { 943e64a4a4SMichel Lespinasse struct rb_int_node *cur = rb_int(*node); 95e358b4fbSSasha Levin 96e358b4fbSSasha Levin parent = *node; 973e64a4a4SMichel Lespinasse if (i_node->high <= cur->low) 983e64a4a4SMichel Lespinasse node = &cur->node.rb_left; 993e64a4a4SMichel Lespinasse else if (cur->high <= i_node->low) 1003e64a4a4SMichel Lespinasse node = &cur->node.rb_right; 101e358b4fbSSasha Levin else 102495fbd4eSSasha Levin return -EEXIST; 103e358b4fbSSasha Levin } 104e358b4fbSSasha Levin 105e358b4fbSSasha Levin rb_link_node(&i_node->node, parent, node); 10686824900SIngo Molnar rb_insert_augmented(&i_node->node, root, &callbacks); 107e358b4fbSSasha Levin 108495fbd4eSSasha Levin return 0; 109e358b4fbSSasha Levin } 110e358b4fbSSasha Levin 111e358b4fbSSasha Levin void rb_int_erase(struct rb_root *root, struct rb_int_node *node) 112e358b4fbSSasha Levin { 11386824900SIngo Molnar rb_erase_augmented(&node->node, root, &callbacks); 114e358b4fbSSasha Levin } 115