drm/drm_crtc: return -EFAULT on copy_to_user errors
[safe/jmp/linux-2.6] / lib / rbtree.c
index 9956b99..15e10b1 100644 (file)
@@ -44,6 +44,11 @@ static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
        else
                root->rb_node = right;
        rb_set_parent(node, right);
+
+       if (root->augment_cb) {
+               root->augment_cb(node);
+               root->augment_cb(right);
+       }
 }
 
 static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
@@ -67,12 +72,20 @@ static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
        else
                root->rb_node = left;
        rb_set_parent(node, left);
+
+       if (root->augment_cb) {
+               root->augment_cb(node);
+               root->augment_cb(left);
+       }
 }
 
 void rb_insert_color(struct rb_node *node, struct rb_root *root)
 {
        struct rb_node *parent, *gparent;
 
+       if (root->augment_cb)
+               root->augment_cb(node);
+
        while ((parent = rb_parent(node)) && rb_is_red(parent))
        {
                gparent = rb_parent(parent);
@@ -163,17 +176,14 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
                        {
                                if (!other->rb_right || rb_is_black(other->rb_right))
                                {
-                                       struct rb_node *o_left;
-                                       if ((o_left = other->rb_left))
-                                               rb_set_black(o_left);
+                                       rb_set_black(other->rb_left);
                                        rb_set_red(other);
                                        __rb_rotate_right(other, root);
                                        other = parent->rb_right;
                                }
                                rb_set_color(other, rb_color(parent));
                                rb_set_black(parent);
-                               if (other->rb_right)
-                                       rb_set_black(other->rb_right);
+                               rb_set_black(other->rb_right);
                                __rb_rotate_left(parent, root);
                                node = root->rb_node;
                                break;
@@ -200,17 +210,14 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
                        {
                                if (!other->rb_left || rb_is_black(other->rb_left))
                                {
-                                       register struct rb_node *o_right;
-                                       if ((o_right = other->rb_right))
-                                               rb_set_black(o_right);
+                                       rb_set_black(other->rb_right);
                                        rb_set_red(other);
                                        __rb_rotate_left(other, root);
                                        other = parent->rb_left;
                                }
                                rb_set_color(other, rb_color(parent));
                                rb_set_black(parent);
-                               if (other->rb_left)
-                                       rb_set_black(other->rb_left);
+                               rb_set_black(other->rb_left);
                                __rb_rotate_right(parent, root);
                                node = root->rb_node;
                                break;
@@ -233,38 +240,61 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
        else
        {
                struct rb_node *old = node, *left;
+               int old_parent_cb = 0;
+               int successor_parent_cb = 0;
 
                node = node->rb_right;
                while ((left = node->rb_left) != NULL)
                        node = left;
+
+               if (rb_parent(old)) {
+                       old_parent_cb = 1;
+                       if (rb_parent(old)->rb_left == old)
+                               rb_parent(old)->rb_left = node;
+                       else
+                               rb_parent(old)->rb_right = node;
+               } else
+                       root->rb_node = node;
+
                child = node->rb_right;
                parent = rb_parent(node);
                color = rb_color(node);
 
-               if (child)
-                       rb_set_parent(child, parent);
                if (parent == old) {
-                       parent->rb_right = child;
                        parent = node;
-               } else
+               } else {
+                       successor_parent_cb = 1;
+                       if (child)
+                               rb_set_parent(child, parent);
+
                        parent->rb_left = child;
 
+                       node->rb_right = old->rb_right;
+                       rb_set_parent(old->rb_right, node);
+               }
+
                node->rb_parent_color = old->rb_parent_color;
-               node->rb_right = old->rb_right;
                node->rb_left = old->rb_left;
+               rb_set_parent(old->rb_left, node);
 
-               if (rb_parent(old))
-               {
-                       if (rb_parent(old)->rb_left == old)
-                               rb_parent(old)->rb_left = node;
-                       else
-                               rb_parent(old)->rb_right = node;
-               } else
-                       root->rb_node = node;
+               if (root->augment_cb) {
+                       /*
+                        * Here, three different nodes can have new children.
+                        * The parent of the successor node that was selected
+                        * to replace the node to be erased.
+                        * The node that is getting erased and is now replaced
+                        * by its successor.
+                        * The parent of the node getting erased-replaced.
+                        */
+                       if (successor_parent_cb)
+                               root->augment_cb(parent);
+
+                       root->augment_cb(node);
+
+                       if (old_parent_cb)
+                               root->augment_cb(rb_parent(old));
+               }
 
-               rb_set_parent(old->rb_left, node);
-               if (old->rb_right)
-                       rb_set_parent(old->rb_right, node);
                goto color;
        }
 
@@ -273,15 +303,19 @@ void rb_erase(struct rb_node *node, struct rb_root *root)
 
        if (child)
                rb_set_parent(child, parent);
-       if (parent)
-       {
+
+       if (parent) {
                if (parent->rb_left == node)
                        parent->rb_left = child;
                else
                        parent->rb_right = child;
-       }
-       else
+
+               if (root->augment_cb)
+                       root->augment_cb(parent);
+
+       } else {
                root->rb_node = child;
+       }
 
  color:
        if (color == RB_BLACK)