rbtree: Make swap resistant to nodes outside the tree
Signed-off-by: Robert Baldyga <robert.baldyga@intel.com>
This commit is contained in:
parent
694224971c
commit
50c4de0495
@ -12,24 +12,19 @@ void ocf_rb_tree_init(struct ocf_rb_tree *tree, ocf_rb_tree_node_cmp_cb cmp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ocf_rb_tree_update_parent(struct ocf_rb_tree *tree,
|
static void ocf_rb_tree_update_parent(struct ocf_rb_tree *tree,
|
||||||
struct ocf_rb_node *node, struct ocf_rb_node *old_node,
|
struct ocf_rb_node *parent, struct ocf_rb_node *old_node,
|
||||||
struct ocf_rb_node *new_node)
|
struct ocf_rb_node *new_node)
|
||||||
{
|
{
|
||||||
if (!node->parent)
|
if (!parent) {
|
||||||
tree->root = new_node;
|
if (tree->root == old_node)
|
||||||
else if (old_node == node->parent->left)
|
tree->root = new_node;
|
||||||
node->parent->left = new_node;
|
return;
|
||||||
else if (old_node == node->parent->right)
|
}
|
||||||
node->parent->right = new_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ocf_rb_tree_update_children(struct ocf_rb_node *node)
|
if (parent->left == old_node)
|
||||||
{
|
parent->left = new_node;
|
||||||
if (node->left)
|
else if (parent->right == old_node)
|
||||||
node->left->parent = node;
|
parent->right = new_node;
|
||||||
|
|
||||||
if (node->right)
|
|
||||||
node->right->parent = node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ocf_rb_tree_rotate_left(struct ocf_rb_tree *tree,
|
static void ocf_rb_tree_rotate_left(struct ocf_rb_tree *tree,
|
||||||
@ -44,7 +39,7 @@ static void ocf_rb_tree_rotate_left(struct ocf_rb_tree *tree,
|
|||||||
|
|
||||||
right->parent = node->parent;
|
right->parent = node->parent;
|
||||||
|
|
||||||
ocf_rb_tree_update_parent(tree, node, node, right);
|
ocf_rb_tree_update_parent(tree, node->parent, node, right);
|
||||||
|
|
||||||
right->left = node;
|
right->left = node;
|
||||||
node->parent = right;
|
node->parent = right;
|
||||||
@ -62,7 +57,7 @@ static void ocf_rb_tree_rotate_right(struct ocf_rb_tree *tree,
|
|||||||
|
|
||||||
left->parent = node->parent;
|
left->parent = node->parent;
|
||||||
|
|
||||||
ocf_rb_tree_update_parent(tree, node, node, left);
|
ocf_rb_tree_update_parent(tree, node->parent, node, left);
|
||||||
|
|
||||||
left->right = node;
|
left->right = node;
|
||||||
node->parent = left;
|
node->parent = left;
|
||||||
@ -165,34 +160,51 @@ void ocf_rb_tree_insert(struct ocf_rb_tree *tree, struct ocf_rb_node *node)
|
|||||||
ocf_rb_tree_fix_violation(tree, node);
|
ocf_rb_tree_fix_violation(tree, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ocf_rb_copy_node(struct ocf_rb_node *dst, struct ocf_rb_node *src)
|
||||||
|
{
|
||||||
|
dst->red = src->red;
|
||||||
|
dst->left = src->left;
|
||||||
|
dst->right = src->right;
|
||||||
|
dst->parent = src->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ocf_rb_tree_update_children(struct ocf_rb_node *node)
|
||||||
|
{
|
||||||
|
if (node->left)
|
||||||
|
node->left->parent = node;
|
||||||
|
|
||||||
|
if (node->right)
|
||||||
|
node->right->parent = node;
|
||||||
|
}
|
||||||
|
|
||||||
static void ocf_rb_tree_swap(struct ocf_rb_tree *tree,
|
static void ocf_rb_tree_swap(struct ocf_rb_tree *tree,
|
||||||
struct ocf_rb_node *node1, struct ocf_rb_node *node2)
|
struct ocf_rb_node *node1, struct ocf_rb_node *node2)
|
||||||
{
|
{
|
||||||
struct ocf_rb_node tmp;
|
struct ocf_rb_node tmp;
|
||||||
|
|
||||||
if (node1->left == node2)
|
ocf_rb_copy_node(&tmp, node1);
|
||||||
node1->left = node1;
|
ocf_rb_copy_node(node1, node2);
|
||||||
else if (node1->right == node2)
|
ocf_rb_copy_node(node2, &tmp);
|
||||||
node1->right = node1;
|
|
||||||
else if (node1->parent == node2)
|
|
||||||
node1->parent = node1;
|
|
||||||
|
|
||||||
if (node2->left == node1)
|
if (node1->parent == node1)
|
||||||
node2->left = node2;
|
node1->parent = node2;
|
||||||
else if (node2->right == node1)
|
else if (node1->left == node1)
|
||||||
node2->right = node2;
|
node1->left = node2;
|
||||||
else if (node2->parent == node1)
|
else if (node1->right == node1)
|
||||||
node2->parent = node2;
|
node1->right = node2;
|
||||||
|
|
||||||
tmp = *node1;
|
if (node2->parent == node2)
|
||||||
*node1 = *node2;
|
node2->parent = node1;
|
||||||
*node2 = tmp;
|
else if (node2->left == node2)
|
||||||
|
node2->left = node1;
|
||||||
ocf_rb_tree_update_parent(tree, node1, node2, node1);
|
else if (node2->right == node2)
|
||||||
ocf_rb_tree_update_parent(tree, node2, node1, node2);
|
node2->right = node1;
|
||||||
|
|
||||||
ocf_rb_tree_update_children(node1);
|
ocf_rb_tree_update_children(node1);
|
||||||
ocf_rb_tree_update_children(node2);
|
ocf_rb_tree_update_children(node2);
|
||||||
|
|
||||||
|
ocf_rb_tree_update_parent(tree, node2->parent, node1, node2);
|
||||||
|
ocf_rb_tree_update_parent(tree, node1->parent, node2, node1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ocf_rb_node *ocf_rb_tree_successor(struct ocf_rb_node *node)
|
static struct ocf_rb_node *ocf_rb_tree_successor(struct ocf_rb_node *node)
|
||||||
@ -334,7 +346,8 @@ void ocf_rb_tree_remove(struct ocf_rb_tree *tree, struct ocf_rb_node *node)
|
|||||||
else if (sibling)
|
else if (sibling)
|
||||||
sibling->red = true;
|
sibling->red = true;
|
||||||
|
|
||||||
ocf_rb_tree_update_parent(tree, node, node, NULL);
|
ocf_rb_tree_update_parent(tree, node->parent,
|
||||||
|
node, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -346,7 +359,8 @@ void ocf_rb_tree_remove(struct ocf_rb_tree *tree, struct ocf_rb_node *node)
|
|||||||
if (!node->red)
|
if (!node->red)
|
||||||
ocf_rb_tree_fix_double_black(tree, node);
|
ocf_rb_tree_fix_double_black(tree, node);
|
||||||
|
|
||||||
ocf_rb_tree_update_parent(tree, node, node, NULL);
|
ocf_rb_tree_update_parent(tree, node->parent,
|
||||||
|
node, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user