From 7fe1e133bf45b0fe70491ed3d4c5b491feff7aa8 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 21 Apr 2006 13:12:44 +0100 Subject: [RBTREE] Add accessor macros for colour and parent fields of rb_node This is in preparation for merging those fields into a single 'unsigned long', because using a whole machine-word for a single bit of colour information is wasteful. Signed-off-by: David Woodhouse --- include/linux/rbtree.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index 4b7cc4fe366d..ffee81ce7b6f 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h @@ -107,6 +107,15 @@ struct rb_node struct rb_node *rb_left; }; +#define rb_parent(r) ((r)->rb_parent) +#define rb_set_parent(r,p) do { (r)->rb_parent = p; } while (0) +#define rb_colour(r) ((r)->rb_colour) +#define rb_is_red(r) ((r)->colour == RB_RED) +#define rb_is_black(r) ((r)->colour == RB_BLACK) +#define rb_set_red(r) do { (r)->colour = RB_RED; } while (0) +#define rb_set_black(r) do { (r)->colour = RB_BLACK; } while (0) +#define rb_set_colour(r,c) do { (r)->colour = (c); } while (0) + struct rb_root { struct rb_node *rb_node; -- cgit v1.2.3-59-g8ed1b From 3db3a445308b3cee9bbbd8baa6d05081c9532da0 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 21 Apr 2006 13:15:17 +0100 Subject: [RBTREE] Change rbtree off-tree marking in I/O schedulers. They were abusing the rb_color field to mark nodes which weren't currently on the tree. Fix that to use the same method as eventpoll did -- setting the parent pointer to point back to itself. And use the appropriate accessor macros for setting and reading the parent. Signed-off-by: David Woodhouse --- block/as-iosched.c | 5 ++--- block/cfq-iosched.c | 8 +------- block/deadline-iosched.c | 5 ++--- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/block/as-iosched.c b/block/as-iosched.c index e25a5d79ab27..ed336ab453ba 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -353,10 +353,9 @@ static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset) /* * rb tree support functions */ -#define RB_NONE (2) #define RB_EMPTY(root) ((root)->rb_node == NULL) -#define ON_RB(node) ((node)->rb_color != RB_NONE) -#define RB_CLEAR(node) ((node)->rb_color = RB_NONE) +#define ON_RB(node) (rb_parent(node) != node) +#define RB_CLEAR(node) (rb_set_parent(node, node)) #define rb_entry_arq(node) rb_entry((node), struct as_rq, rb_node) #define ARQ_RB_ROOT(ad, arq) (&(ad)->sort_list[(arq)->is_sync]) #define rq_rb_key(rq) (rq)->sector diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 2540dfaa3e38..01c416ba8437 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -60,14 +60,9 @@ static DEFINE_RWLOCK(cfq_exit_lock); /* * rb-tree defines */ -#define RB_NONE (2) #define RB_EMPTY(node) ((node)->rb_node == NULL) -#define RB_CLEAR_COLOR(node) (node)->rb_color = RB_NONE #define RB_CLEAR(node) do { \ - (node)->rb_parent = NULL; \ - RB_CLEAR_COLOR((node)); \ - (node)->rb_right = NULL; \ - (node)->rb_left = NULL; \ + memset(node, 0, sizeof(*node)); \ } while (0) #define RB_CLEAR_ROOT(root) ((root)->rb_node = NULL) #define rb_entry_crq(node) rb_entry((node), struct cfq_rq, rb_node) @@ -563,7 +558,6 @@ static inline void cfq_del_crq_rb(struct cfq_rq *crq) cfq_update_next_crq(crq); rb_erase(&crq->rb_node, &cfqq->sort_list); - RB_CLEAR_COLOR(&crq->rb_node); if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list)) cfq_del_cfqq_rr(cfqd, cfqq); diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index 399fa1e60e1f..06962d8402a3 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -165,10 +165,9 @@ deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) /* * rb tree support functions */ -#define RB_NONE (2) #define RB_EMPTY(root) ((root)->rb_node == NULL) -#define ON_RB(node) ((node)->rb_color != RB_NONE) -#define RB_CLEAR(node) ((node)->rb_color = RB_NONE) +#define ON_RB(node) (rb_parent(node) != node) +#define RB_CLEAR(node) (rb_set_parent(node, node)) #define rb_entry_drq(node) rb_entry((node), struct deadline_rq, rb_node) #define DRQ_RB_ROOT(dd, drq) (&(dd)->sort_list[rq_data_dir((drq)->request)]) #define rq_rb_key(rq) (rq)->sector -- cgit v1.2.3-59-g8ed1b From 52b5108ca7490c0609e4dbddd8439bc03d702c99 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 21 Apr 2006 13:15:57 +0100 Subject: [RBTREE] Update ext3 to use rb_parent() accessor macro. Signed-off-by: David Woodhouse --- fs/ext3/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index f37528ed222e..fbb0d4ed07d4 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -284,7 +284,7 @@ static void free_rb_tree_fname(struct rb_root *root) * beginning of the loop and try to free the parent * node. */ - parent = n->rb_parent; + parent = rb_parent(n); fname = rb_entry(n, struct fname, rb_hash); while (fname) { struct fname * old = fname; -- cgit v1.2.3-59-g8ed1b From fed306f2baa170220b0299198a39c6be2a91bf19 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 21 Apr 2006 13:16:49 +0100 Subject: [RBTREE] Update key.c to use rb_parent() accessor macro. Signed-off-by: David Woodhouse --- security/keys/key.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/security/keys/key.c b/security/keys/key.c index b6061fa29da7..3fdc49c6a02c 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -211,12 +211,12 @@ static inline void key_alloc_serial(struct key *key) key->serial = 2; key_serial_next = key->serial + 1; - if (!parent->rb_parent) + if (!rb_parent(parent)) p = &key_serial_tree.rb_node; - else if (parent->rb_parent->rb_left == parent) - p = &parent->rb_parent->rb_left; + else if (rb_parent(parent)->rb_left == parent) + p = &(rb_parent(parent)->rb_left); else - p = &parent->rb_parent->rb_right; + p = &(rb_parent(parent)->rb_right); parent = rb_next(parent); if (!parent) -- cgit v1.2.3-59-g8ed1b From c569882b2e70a0c4eac99acdb39b493549041ba1 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 21 Apr 2006 13:17:24 +0100 Subject: [RBTREE] Update eventpoll.c to use rb_parent() accessor macro. Signed-off-by: David Woodhouse --- fs/eventpoll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 1b4491cdd115..2695337d4d64 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -337,20 +337,20 @@ static inline int ep_cmp_ffd(struct epoll_filefd *p1, /* Special initialization for the rb-tree node to detect linkage */ static inline void ep_rb_initnode(struct rb_node *n) { - n->rb_parent = n; + rb_set_parent(n, n); } /* Removes a node from the rb-tree and marks it for a fast is-linked check */ static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r) { rb_erase(n, r); - n->rb_parent = n; + rb_set_parent(n, n); } /* Fast check to verify that the item is linked to the main rb-tree */ static inline int ep_rb_linked(struct rb_node *n) { - return n->rb_parent != n; + return rb_parent(n) != n; } /* -- cgit v1.2.3-59-g8ed1b From 21f1d5fc592e145574dede8debe9603334d08fde Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 21 Apr 2006 13:17:57 +0100 Subject: [RBTREE] Update JFFS2 to use rb_parent() accessor macro. Signed-off-by: David Woodhouse --- fs/jffs2/nodelist.h | 1 - fs/jffs2/readinode.c | 18 +++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 23a67bb3052f..131b67b6c350 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -299,7 +299,6 @@ static inline struct jffs2_node_frag *frag_last(struct rb_root *root) return rb_entry(node, struct jffs2_node_frag, rb); } -#define rb_parent(rb) ((rb)->rb_parent) #define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb) #define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb) #define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb) diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index f1695642d0f7..6f4a7d846e8c 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -66,7 +66,7 @@ static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) jffs2_free_full_dnode(tn->fn); jffs2_free_tmp_dnode_info(tn); - this = this->rb_parent; + this = rb_parent(this); if (!this) break; @@ -679,12 +679,12 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, jffs2_mark_node_obsolete(c, fn->raw); BUG_ON(rb->rb_left); - if (rb->rb_parent && rb->rb_parent->rb_left == rb) { + if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) { /* We were then left-hand child of our parent. We need * to move our own right-hand child into our place. */ repl_rb = rb->rb_right; if (repl_rb) - repl_rb->rb_parent = rb->rb_parent; + rb_set_parent(repl_rb, rb_parent(rb)); } else repl_rb = NULL; @@ -692,14 +692,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, /* Remove the spent tn from the tree; don't bother rebalancing * but put our right-hand child in our own place. */ - if (tn->rb.rb_parent) { - if (tn->rb.rb_parent->rb_left == &tn->rb) - tn->rb.rb_parent->rb_left = repl_rb; - else if (tn->rb.rb_parent->rb_right == &tn->rb) - tn->rb.rb_parent->rb_right = repl_rb; + if (rb_parent(&tn->rb)) { + if (rb_parent(&tn->rb)->rb_left == &tn->rb) + rb_parent(&tn->rb)->rb_left = repl_rb; + else if (rb_parent(&tn->rb)->rb_right == &tn->rb) + rb_parent(&tn->rb)->rb_right = repl_rb; else BUG(); } else if (tn->rb.rb_right) - tn->rb.rb_right->rb_parent = NULL; + rb_set_parent(tn->rb.rb_right, NULL); jffs2_free_tmp_dnode_info(tn); if (ret) { -- cgit v1.2.3-59-g8ed1b From 1975e59375756da4ff4e6e7d12f67485e813ace0 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 21 Apr 2006 13:30:36 +0100 Subject: [RBTREE] Remove dead code in rb_erase() Observe rb_erase(), when the victim node 'old' has two children so neither of the simple cases at the beginning are taken. Observe that it effectively does an 'rb_next()' operation to find the next (by value) node in the tree. That is; we go to the victim's right-hand child and then follow left-hand pointers all the way down the tree as far as we can until we find the next node 'node'. We end up with 'node' being either the same immediate right-hand child of 'old', or one of its descendants on the far left-hand side. For a start, we _know_ that 'node' has a parent. We can drop that check. We also know that if 'node's parent is 'old', then 'node' is the right-hand child of its parent. And that if 'node's parent is _not_ 'old', then 'node' is the left-hand child of its parent. So instead of checking for 'node->rb_parent == old' in one place and also checking 'node's heritage separately when we're trying to change its link from its parent, we can shuffle things around a bit and do it like this... Signed-off-by: David Woodhouse --- lib/rbtree.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/rbtree.c b/lib/rbtree.c index 14b791ac5089..63473e04f18a 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c @@ -243,18 +243,13 @@ void rb_erase(struct rb_node *node, struct rb_root *root) if (child) child->rb_parent = parent; - if (parent) - { - if (parent->rb_left == node) - parent->rb_left = child; - else - parent->rb_right = child; - } - else - root->rb_node = child; - if (node->rb_parent == old) + if (node->rb_parent == old) { + parent->rb_right = child; parent = node; + } else + parent->rb_left = child; + node->rb_parent = old->rb_parent; node->rb_color = old->rb_color; node->rb_right = old->rb_right; -- cgit v1.2.3-59-g8ed1b From 55a981027fc393c86de2c4e7836c9515088a9a58 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 21 Apr 2006 13:35:51 +0100 Subject: [RBTREE] Merge colour and parent fields of struct rb_node. We only used a single bit for colour information, so having a whole machine word of space allocated for it was a bit wasteful. Instead, store it in the lowest bit of the 'parent' pointer, since that was always going to be aligned anyway. Signed-off-by: David Woodhouse --- include/linux/rbtree.h | 32 +++++---- lib/rbtree.c | 178 +++++++++++++++++++++++++------------------------ 2 files changed, 109 insertions(+), 101 deletions(-) diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index ffee81ce7b6f..748be50329d8 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h @@ -99,28 +99,35 @@ static inline struct page * rb_insert_page_cache(struct inode * inode, struct rb_node { - struct rb_node *rb_parent; - int rb_color; + unsigned long rb_parent_colour; #define RB_RED 0 #define RB_BLACK 1 struct rb_node *rb_right; struct rb_node *rb_left; }; -#define rb_parent(r) ((r)->rb_parent) -#define rb_set_parent(r,p) do { (r)->rb_parent = p; } while (0) -#define rb_colour(r) ((r)->rb_colour) -#define rb_is_red(r) ((r)->colour == RB_RED) -#define rb_is_black(r) ((r)->colour == RB_BLACK) -#define rb_set_red(r) do { (r)->colour = RB_RED; } while (0) -#define rb_set_black(r) do { (r)->colour = RB_BLACK; } while (0) -#define rb_set_colour(r,c) do { (r)->colour = (c); } while (0) - struct rb_root { struct rb_node *rb_node; }; + +#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_colour & ~3)) +#define rb_colour(r) ((r)->rb_parent_colour & 1) +#define rb_is_red(r) (!rb_colour(r)) +#define rb_is_black(r) rb_colour(r) +#define rb_set_red(r) do { (r)->rb_parent_colour &= ~1; } while (0) +#define rb_set_black(r) do { (r)->rb_parent_colour |= 1; } while (0) + +static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) +{ + rb->rb_parent_colour = (rb->rb_parent_colour & 3) | (unsigned long)p; +} +static inline void rb_set_colour(struct rb_node *rb, int colour) +{ + rb->rb_parent_colour = (rb->rb_parent_colour & ~1) | colour; +} + #define RB_ROOT (struct rb_root) { NULL, } #define rb_entry(ptr, type, member) container_of(ptr, type, member) @@ -140,8 +147,7 @@ extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, struct rb_node ** rb_link) { - node->rb_parent = parent; - node->rb_color = RB_RED; + node->rb_parent_colour = (unsigned long )parent; node->rb_left = node->rb_right = NULL; *rb_link = node; diff --git a/lib/rbtree.c b/lib/rbtree.c index 63473e04f18a..4a7173cad149 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c @@ -26,60 +26,66 @@ static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) { struct rb_node *right = node->rb_right; + struct rb_node *parent = rb_parent(node); if ((node->rb_right = right->rb_left)) - right->rb_left->rb_parent = node; + rb_set_parent(right->rb_left, node); right->rb_left = node; - if ((right->rb_parent = node->rb_parent)) + rb_set_parent(right, parent); + + if (parent) { - if (node == node->rb_parent->rb_left) - node->rb_parent->rb_left = right; + if (node == parent->rb_left) + parent->rb_left = right; else - node->rb_parent->rb_right = right; + parent->rb_right = right; } else root->rb_node = right; - node->rb_parent = right; + rb_set_parent(node, right); } static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) { struct rb_node *left = node->rb_left; + struct rb_node *parent = rb_parent(node); if ((node->rb_left = left->rb_right)) - left->rb_right->rb_parent = node; + rb_set_parent(left->rb_right, node); left->rb_right = node; - if ((left->rb_parent = node->rb_parent)) + rb_set_parent(left, parent); + + if (parent) { - if (node == node->rb_parent->rb_right) - node->rb_parent->rb_right = left; + if (node == parent->rb_right) + parent->rb_right = left; else - node->rb_parent->rb_left = left; + parent->rb_left = left; } else root->rb_node = left; - node->rb_parent = left; + rb_set_parent(node, left); } void rb_insert_color(struct rb_node *node, struct rb_root *root) { struct rb_node *parent, *gparent; - while ((parent = node->rb_parent) && parent->rb_color == RB_RED) + while ((parent = rb_parent(node)) && rb_is_red(parent)) { - gparent = parent->rb_parent; + gparent = rb_parent(parent); if (parent == gparent->rb_left) { { register struct rb_node *uncle = gparent->rb_right; - if (uncle && uncle->rb_color == RB_RED) + if (uncle && rb_is_red(uncle)) { - uncle->rb_color = RB_BLACK; - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; + rb_set_black(uncle); + rb_set_black(parent); + rb_set_red(gparent); node = gparent; continue; } @@ -94,17 +100,17 @@ void rb_insert_color(struct rb_node *node, struct rb_root *root) node = tmp; } - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; + rb_set_black(parent); + rb_set_red(gparent); __rb_rotate_right(gparent, root); } else { { register struct rb_node *uncle = gparent->rb_left; - if (uncle && uncle->rb_color == RB_RED) + if (uncle && rb_is_red(uncle)) { - uncle->rb_color = RB_BLACK; - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; + rb_set_black(uncle); + rb_set_black(parent); + rb_set_red(gparent); node = gparent; continue; } @@ -119,13 +125,13 @@ void rb_insert_color(struct rb_node *node, struct rb_root *root) node = tmp; } - parent->rb_color = RB_BLACK; - gparent->rb_color = RB_RED; + rb_set_black(parent); + rb_set_red(gparent); __rb_rotate_left(gparent, root); } } - root->rb_node->rb_color = RB_BLACK; + rb_set_black(root->rb_node); } EXPORT_SYMBOL(rb_insert_color); @@ -134,43 +140,40 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, { struct rb_node *other; - while ((!node || node->rb_color == RB_BLACK) && node != root->rb_node) + while ((!node || rb_is_black(node)) && node != root->rb_node) { if (parent->rb_left == node) { other = parent->rb_right; - if (other->rb_color == RB_RED) + if (rb_is_red(other)) { - other->rb_color = RB_BLACK; - parent->rb_color = RB_RED; + rb_set_black(other); + rb_set_red(parent); __rb_rotate_left(parent, root); other = parent->rb_right; } - if ((!other->rb_left || - other->rb_left->rb_color == RB_BLACK) - && (!other->rb_right || - other->rb_right->rb_color == RB_BLACK)) + if ((!other->rb_left || rb_is_black(other->rb_left)) && + (!other->rb_right || rb_is_black(other->rb_right))) { - other->rb_color = RB_RED; + rb_set_red(other); node = parent; - parent = node->rb_parent; + parent = rb_parent(node); } else { - if (!other->rb_right || - other->rb_right->rb_color == RB_BLACK) + if (!other->rb_right || rb_is_black(other->rb_right)) { - register struct rb_node *o_left; + struct rb_node *o_left; if ((o_left = other->rb_left)) - o_left->rb_color = RB_BLACK; - other->rb_color = RB_RED; + rb_set_black(o_left); + rb_set_red(other); __rb_rotate_right(other, root); other = parent->rb_right; } - other->rb_color = parent->rb_color; - parent->rb_color = RB_BLACK; + rb_set_colour(other, rb_colour(parent)); + rb_set_black(parent); if (other->rb_right) - other->rb_right->rb_color = RB_BLACK; + rb_set_black(other->rb_right); __rb_rotate_left(parent, root); node = root->rb_node; break; @@ -179,38 +182,35 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, else { other = parent->rb_left; - if (other->rb_color == RB_RED) + if (rb_is_red(other)) { - other->rb_color = RB_BLACK; - parent->rb_color = RB_RED; + rb_set_black(other); + rb_set_red(parent); __rb_rotate_right(parent, root); other = parent->rb_left; } - if ((!other->rb_left || - other->rb_left->rb_color == RB_BLACK) - && (!other->rb_right || - other->rb_right->rb_color == RB_BLACK)) + if ((!other->rb_left || rb_is_black(other->rb_left)) && + (!other->rb_right || rb_is_black(other->rb_right))) { - other->rb_color = RB_RED; + rb_set_red(other); node = parent; - parent = node->rb_parent; + parent = rb_parent(node); } else { - if (!other->rb_left || - other->rb_left->rb_color == RB_BLACK) + if (!other->rb_left || rb_is_black(other->rb_left)) { register struct rb_node *o_right; if ((o_right = other->rb_right)) - o_right->rb_color = RB_BLACK; - other->rb_color = RB_RED; + rb_set_black(o_right); + rb_set_red(other); __rb_rotate_left(other, root); other = parent->rb_left; } - other->rb_color = parent->rb_color; - parent->rb_color = RB_BLACK; + rb_set_colour(other, rb_colour(parent)); + rb_set_black(parent); if (other->rb_left) - other->rb_left->rb_color = RB_BLACK; + rb_set_black(other->rb_left); __rb_rotate_right(parent, root); node = root->rb_node; break; @@ -218,7 +218,7 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, } } if (node) - node->rb_color = RB_BLACK; + rb_set_black(node); } void rb_erase(struct rb_node *node, struct rb_root *root) @@ -238,43 +238,41 @@ void rb_erase(struct rb_node *node, struct rb_root *root) while ((left = node->rb_left) != NULL) node = left; child = node->rb_right; - parent = node->rb_parent; - color = node->rb_color; + parent = rb_parent(node); + color = rb_colour(node); if (child) - child->rb_parent = parent; - - if (node->rb_parent == old) { + rb_set_parent(child, parent); + if (parent == old) { parent->rb_right = child; parent = node; - } else + } else parent->rb_left = child; - node->rb_parent = old->rb_parent; - node->rb_color = old->rb_color; + node->rb_parent_colour = old->rb_parent_colour; node->rb_right = old->rb_right; node->rb_left = old->rb_left; - if (old->rb_parent) + if (rb_parent(old)) { - if (old->rb_parent->rb_left == old) - old->rb_parent->rb_left = node; + if (rb_parent(old)->rb_left == old) + rb_parent(old)->rb_left = node; else - old->rb_parent->rb_right = node; + rb_parent(old)->rb_right = node; } else root->rb_node = node; - old->rb_left->rb_parent = node; + rb_set_parent(old->rb_left, node); if (old->rb_right) - old->rb_right->rb_parent = node; + rb_set_parent(old->rb_right, node); goto color; } - parent = node->rb_parent; - color = node->rb_color; + parent = rb_parent(node); + color = rb_colour(node); if (child) - child->rb_parent = parent; + rb_set_parent(child, parent); if (parent) { if (parent->rb_left == node) @@ -322,6 +320,8 @@ EXPORT_SYMBOL(rb_last); struct rb_node *rb_next(struct rb_node *node) { + struct rb_node *parent; + /* If we have a right-hand child, go down and then left as far as we can. */ if (node->rb_right) { @@ -337,15 +337,17 @@ struct rb_node *rb_next(struct rb_node *node) ancestor is a right-hand child of its parent, keep going up. First time it's a left-hand child of its parent, said parent is our 'next' node. */ - while (node->rb_parent && node == node->rb_parent->rb_right) - node = node->rb_parent; + while ((parent = rb_parent(node)) && node == parent->rb_right) + node = parent; - return node->rb_parent; + return parent; } EXPORT_SYMBOL(rb_next); struct rb_node *rb_prev(struct rb_node *node) { + struct rb_node *parent; + /* If we have a left-hand child, go down and then right as far as we can. */ if (node->rb_left) { @@ -357,17 +359,17 @@ struct rb_node *rb_prev(struct rb_node *node) /* No left-hand children. Go up till we find an ancestor which is a right-hand child of its parent */ - while (node->rb_parent && node == node->rb_parent->rb_left) - node = node->rb_parent; + while ((parent = rb_parent(node)) && node == parent->rb_left) + node = parent; - return node->rb_parent; + return parent; } EXPORT_SYMBOL(rb_prev); void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root) { - struct rb_node *parent = victim->rb_parent; + struct rb_node *parent = rb_parent(victim); /* Set the surrounding nodes to point to the replacement */ if (parent) { @@ -379,9 +381,9 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new, root->rb_node = new; } if (victim->rb_left) - victim->rb_left->rb_parent = new; + rb_set_parent(victim->rb_left, new); if (victim->rb_right) - victim->rb_right->rb_parent = new; + rb_set_parent(victim->rb_right, new); /* Copy the pointers/colour from the victim to the replacement */ *new = *victim; -- cgit v1.2.3-59-g8ed1b From e977145aeaad23d443686f2a2d5b32800d1607c5 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 21 Apr 2006 23:15:39 +0100 Subject: [RBTREE] Add explicit alignment to sizeof(long) for struct rb_node. Seems like a strange requirement, but allegedly it was necessary for struct address_space on CRIS, because it otherwise ended up being only byte-aligned. It's harmless enough, and easier to just do it than to prove it isn't necessary... although I really ought to dig out my etrax board and test it some time. Signed-off-by: David Woodhouse --- include/linux/rbtree.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index 748be50329d8..3cc30b0ab828 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h @@ -104,7 +104,8 @@ struct rb_node #define RB_BLACK 1 struct rb_node *rb_right; struct rb_node *rb_left; -}; +} __attribute__((aligned(sizeof(long)))); + /* The alignment might seem pointless, but allegedly CRIS needs it */ struct rb_root { -- cgit v1.2.3-59-g8ed1b From ed198cb49750fd9ec564e9f1df66c10efea605f1 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sat, 22 Apr 2006 02:38:50 +0100 Subject: [RBTREE] Update hrtimers to use rb_parent() accessor macro. Also switch it to use the same method of using off-tree nodes as everyone else now does -- set them to point to themselves. Signed-off-by: David Woodhouse --- include/linux/hrtimer.h | 2 +- kernel/hrtimer.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 306acf1dc6d5..7d2a1b974c5e 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -127,7 +127,7 @@ extern ktime_t hrtimer_get_next_event(void); static inline int hrtimer_active(const struct hrtimer *timer) { - return timer->node.rb_parent != HRTIMER_INACTIVE; + return rb_parent(&timer->node) != &timer->node; } /* Forward a hrtimer so it expires after now: */ diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index d2a7296c8251..04ab27ddfd90 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -393,7 +393,7 @@ static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) if (base->first == &timer->node) base->first = rb_next(&timer->node); rb_erase(&timer->node, &base->active); - timer->node.rb_parent = HRTIMER_INACTIVE; + rb_set_parent(&timer->node, &timer->node); } /* @@ -578,7 +578,7 @@ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, clock_id = CLOCK_MONOTONIC; timer->base = &bases[clock_id]; - timer->node.rb_parent = HRTIMER_INACTIVE; + rb_set_parent(&timer->node, &timer->node); } /** -- cgit v1.2.3-59-g8ed1b From aa783a8f31c79f493bd49ba926b171b79b9839fb Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 1 May 2006 09:41:47 +0100 Subject: Update UML kernel/physmem.c to use rb_parent() accessor macro Signed-off-by: Andrew Morton Signed-off-by: David Woodhouse --- arch/um/kernel/physmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 0500800df1c1..73c741d37af9 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -69,7 +69,7 @@ static void insert_phys_mapping(struct phys_desc *desc) panic("Physical remapping for %p already present", desc->virt); - rb_link_node(&desc->rb, (*n)->rb_parent, n); + rb_link_node(&desc->rb, rb_parent(*n), n); rb_insert_color(&desc->rb, &phys_mappings); } -- cgit v1.2.3-59-g8ed1b From 2f3243aebd8df4d9eecaeca04bbff6c7dbfb2142 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 5 Jun 2006 20:19:05 +0100 Subject: [RBTREE] Switch rb_colour() et al to en_US spelling of 'color' for consistency Since rb_insert_color() is part of the _public_ API, while the others are purely internal, switch to be consistent with that. Signed-off-by: David Woodhouse --- include/linux/rbtree.h | 22 +++++++++++----------- lib/rbtree.c | 10 +++++----- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index 3cc30b0ab828..f37006f21664 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h @@ -99,7 +99,7 @@ static inline struct page * rb_insert_page_cache(struct inode * inode, struct rb_node { - unsigned long rb_parent_colour; + unsigned long rb_parent_color; #define RB_RED 0 #define RB_BLACK 1 struct rb_node *rb_right; @@ -113,20 +113,20 @@ struct rb_root }; -#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_colour & ~3)) -#define rb_colour(r) ((r)->rb_parent_colour & 1) -#define rb_is_red(r) (!rb_colour(r)) -#define rb_is_black(r) rb_colour(r) -#define rb_set_red(r) do { (r)->rb_parent_colour &= ~1; } while (0) -#define rb_set_black(r) do { (r)->rb_parent_colour |= 1; } while (0) +#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) +#define rb_color(r) ((r)->rb_parent_color & 1) +#define rb_is_red(r) (!rb_color(r)) +#define rb_is_black(r) rb_color(r) +#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) +#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) { - rb->rb_parent_colour = (rb->rb_parent_colour & 3) | (unsigned long)p; + rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; } -static inline void rb_set_colour(struct rb_node *rb, int colour) +static inline void rb_set_color(struct rb_node *rb, int color) { - rb->rb_parent_colour = (rb->rb_parent_colour & ~1) | colour; + rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; } #define RB_ROOT (struct rb_root) { NULL, } @@ -148,7 +148,7 @@ extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, static inline void rb_link_node(struct rb_node * node, struct rb_node * parent, struct rb_node ** rb_link) { - node->rb_parent_colour = (unsigned long )parent; + node->rb_parent_color = (unsigned long )parent; node->rb_left = node->rb_right = NULL; *rb_link = node; diff --git a/lib/rbtree.c b/lib/rbtree.c index 4a7173cad149..1e55ba1c2edf 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c @@ -170,7 +170,7 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, __rb_rotate_right(other, root); other = parent->rb_right; } - rb_set_colour(other, rb_colour(parent)); + rb_set_color(other, rb_color(parent)); rb_set_black(parent); if (other->rb_right) rb_set_black(other->rb_right); @@ -207,7 +207,7 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, __rb_rotate_left(other, root); other = parent->rb_left; } - rb_set_colour(other, rb_colour(parent)); + rb_set_color(other, rb_color(parent)); rb_set_black(parent); if (other->rb_left) rb_set_black(other->rb_left); @@ -239,7 +239,7 @@ void rb_erase(struct rb_node *node, struct rb_root *root) node = left; child = node->rb_right; parent = rb_parent(node); - color = rb_colour(node); + color = rb_color(node); if (child) rb_set_parent(child, parent); @@ -249,7 +249,7 @@ void rb_erase(struct rb_node *node, struct rb_root *root) } else parent->rb_left = child; - node->rb_parent_colour = old->rb_parent_colour; + node->rb_parent_color = old->rb_parent_color; node->rb_right = old->rb_right; node->rb_left = old->rb_left; @@ -269,7 +269,7 @@ void rb_erase(struct rb_node *node, struct rb_root *root) } parent = rb_parent(node); - color = rb_colour(node); + color = rb_color(node); if (child) rb_set_parent(child, parent); -- cgit v1.2.3-59-g8ed1b