diff options
-rw-r--r-- | net/ipv4/fib_trie.c | 68 |
1 files changed, 36 insertions, 32 deletions
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 9ca786a6fd3c..f28f9f5f240c 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -93,15 +93,8 @@ typedef unsigned int t_key; | |||
93 | #define T_TNODE 0 | 93 | #define T_TNODE 0 |
94 | #define T_LEAF 1 | 94 | #define T_LEAF 1 |
95 | #define NODE_TYPE_MASK 0x1UL | 95 | #define NODE_TYPE_MASK 0x1UL |
96 | #define NODE_PARENT(node) \ | ||
97 | ((struct tnode *)rcu_dereference(((node)->parent & ~NODE_TYPE_MASK))) | ||
98 | |||
99 | #define NODE_TYPE(node) ((node)->parent & NODE_TYPE_MASK) | 96 | #define NODE_TYPE(node) ((node)->parent & NODE_TYPE_MASK) |
100 | 97 | ||
101 | #define NODE_SET_PARENT(node, ptr) \ | ||
102 | rcu_assign_pointer((node)->parent, \ | ||
103 | ((unsigned long)(ptr)) | NODE_TYPE(node)) | ||
104 | |||
105 | #define IS_TNODE(n) (!(n->parent & T_LEAF)) | 98 | #define IS_TNODE(n) (!(n->parent & T_LEAF)) |
106 | #define IS_LEAF(n) (n->parent & T_LEAF) | 99 | #define IS_LEAF(n) (n->parent & T_LEAF) |
107 | 100 | ||
@@ -174,6 +167,19 @@ static void tnode_free(struct tnode *tn); | |||
174 | static struct kmem_cache *fn_alias_kmem __read_mostly; | 167 | static struct kmem_cache *fn_alias_kmem __read_mostly; |
175 | static struct trie *trie_local = NULL, *trie_main = NULL; | 168 | static struct trie *trie_local = NULL, *trie_main = NULL; |
176 | 169 | ||
170 | static inline struct tnode *node_parent(struct node *node) | ||
171 | { | ||
172 | struct tnode *ret; | ||
173 | |||
174 | ret = (struct tnode *)(node->parent & ~NODE_TYPE_MASK); | ||
175 | return rcu_dereference(ret); | ||
176 | } | ||
177 | |||
178 | static inline void node_set_parent(struct node *node, struct tnode *ptr) | ||
179 | { | ||
180 | rcu_assign_pointer(node->parent, | ||
181 | (unsigned long)ptr | NODE_TYPE(node)); | ||
182 | } | ||
177 | 183 | ||
178 | /* rcu_read_lock needs to be hold by caller from readside */ | 184 | /* rcu_read_lock needs to be hold by caller from readside */ |
179 | 185 | ||
@@ -446,7 +452,7 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int w | |||
446 | tn->full_children++; | 452 | tn->full_children++; |
447 | 453 | ||
448 | if (n) | 454 | if (n) |
449 | NODE_SET_PARENT(n, tn); | 455 | node_set_parent(n, tn); |
450 | 456 | ||
451 | rcu_assign_pointer(tn->child[i], n); | 457 | rcu_assign_pointer(tn->child[i], n); |
452 | } | 458 | } |
@@ -481,7 +487,7 @@ static struct node *resize(struct trie *t, struct tnode *tn) | |||
481 | continue; | 487 | continue; |
482 | 488 | ||
483 | /* compress one level */ | 489 | /* compress one level */ |
484 | NODE_SET_PARENT(n, NULL); | 490 | node_set_parent(n, NULL); |
485 | tnode_free(tn); | 491 | tnode_free(tn); |
486 | return n; | 492 | return n; |
487 | } | 493 | } |
@@ -636,7 +642,7 @@ static struct node *resize(struct trie *t, struct tnode *tn) | |||
636 | 642 | ||
637 | /* compress one level */ | 643 | /* compress one level */ |
638 | 644 | ||
639 | NODE_SET_PARENT(n, NULL); | 645 | node_set_parent(n, NULL); |
640 | tnode_free(tn); | 646 | tnode_free(tn); |
641 | return n; | 647 | return n; |
642 | } | 648 | } |
@@ -961,24 +967,21 @@ fib_find_node(struct trie *t, u32 key) | |||
961 | static struct node *trie_rebalance(struct trie *t, struct tnode *tn) | 967 | static struct node *trie_rebalance(struct trie *t, struct tnode *tn) |
962 | { | 968 | { |
963 | int wasfull; | 969 | int wasfull; |
964 | t_key cindex, key; | 970 | t_key cindex, key = tn->key; |
965 | struct tnode *tp = NULL; | 971 | struct tnode *tp; |
966 | |||
967 | key = tn->key; | ||
968 | 972 | ||
969 | while (tn != NULL && NODE_PARENT(tn) != NULL) { | 973 | while (tn != NULL && (tp = node_parent((struct node *)tn)) != NULL) { |
970 | |||
971 | tp = NODE_PARENT(tn); | ||
972 | cindex = tkey_extract_bits(key, tp->pos, tp->bits); | 974 | cindex = tkey_extract_bits(key, tp->pos, tp->bits); |
973 | wasfull = tnode_full(tp, tnode_get_child(tp, cindex)); | 975 | wasfull = tnode_full(tp, tnode_get_child(tp, cindex)); |
974 | tn = (struct tnode *) resize (t, (struct tnode *)tn); | 976 | tn = (struct tnode *) resize (t, (struct tnode *)tn); |
975 | tnode_put_child_reorg((struct tnode *)tp, cindex,(struct node*)tn, wasfull); | 977 | tnode_put_child_reorg((struct tnode *)tp, cindex,(struct node*)tn, wasfull); |
976 | 978 | ||
977 | if (!NODE_PARENT(tn)) | 979 | tp = node_parent((struct node *) tn); |
980 | if (!tp) | ||
978 | break; | 981 | break; |
979 | 982 | tn = tp; | |
980 | tn = NODE_PARENT(tn); | ||
981 | } | 983 | } |
984 | |||
982 | /* Handle last (top) tnode */ | 985 | /* Handle last (top) tnode */ |
983 | if (IS_TNODE(tn)) | 986 | if (IS_TNODE(tn)) |
984 | tn = (struct tnode*) resize(t, (struct tnode *)tn); | 987 | tn = (struct tnode*) resize(t, (struct tnode *)tn); |
@@ -1031,7 +1034,7 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen) | |||
1031 | pos = tn->pos + tn->bits; | 1034 | pos = tn->pos + tn->bits; |
1032 | n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits)); | 1035 | n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits)); |
1033 | 1036 | ||
1034 | BUG_ON(n && NODE_PARENT(n) != tn); | 1037 | BUG_ON(n && node_parent(n) != tn); |
1035 | } else | 1038 | } else |
1036 | break; | 1039 | break; |
1037 | } | 1040 | } |
@@ -1083,7 +1086,7 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen) | |||
1083 | if (t->trie && n == NULL) { | 1086 | if (t->trie && n == NULL) { |
1084 | /* Case 2: n is NULL, and will just insert a new leaf */ | 1087 | /* Case 2: n is NULL, and will just insert a new leaf */ |
1085 | 1088 | ||
1086 | NODE_SET_PARENT(l, tp); | 1089 | node_set_parent((struct node *)l, tp); |
1087 | 1090 | ||
1088 | cindex = tkey_extract_bits(key, tp->pos, tp->bits); | 1091 | cindex = tkey_extract_bits(key, tp->pos, tp->bits); |
1089 | put_child(t, (struct tnode *)tp, cindex, (struct node *)l); | 1092 | put_child(t, (struct tnode *)tp, cindex, (struct node *)l); |
@@ -1114,7 +1117,7 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen) | |||
1114 | goto err; | 1117 | goto err; |
1115 | } | 1118 | } |
1116 | 1119 | ||
1117 | NODE_SET_PARENT(tn, tp); | 1120 | node_set_parent((struct node *)tn, tp); |
1118 | 1121 | ||
1119 | missbit = tkey_extract_bits(key, newpos, 1); | 1122 | missbit = tkey_extract_bits(key, newpos, 1); |
1120 | put_child(t, tn, missbit, (struct node *)l); | 1123 | put_child(t, tn, missbit, (struct node *)l); |
@@ -1495,12 +1498,13 @@ backtrace: | |||
1495 | if (chopped_off <= pn->bits) { | 1498 | if (chopped_off <= pn->bits) { |
1496 | cindex &= ~(1 << (chopped_off-1)); | 1499 | cindex &= ~(1 << (chopped_off-1)); |
1497 | } else { | 1500 | } else { |
1498 | if (NODE_PARENT(pn) == NULL) | 1501 | struct tnode *parent = node_parent((struct node *) pn); |
1502 | if (!parent) | ||
1499 | goto failed; | 1503 | goto failed; |
1500 | 1504 | ||
1501 | /* Get Child's index */ | 1505 | /* Get Child's index */ |
1502 | cindex = tkey_extract_bits(pn->key, NODE_PARENT(pn)->pos, NODE_PARENT(pn)->bits); | 1506 | cindex = tkey_extract_bits(pn->key, parent->pos, parent->bits); |
1503 | pn = NODE_PARENT(pn); | 1507 | pn = parent; |
1504 | chopped_off = 0; | 1508 | chopped_off = 0; |
1505 | 1509 | ||
1506 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 1510 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
@@ -1536,7 +1540,7 @@ static int trie_leaf_remove(struct trie *t, t_key key) | |||
1536 | check_tnode(tn); | 1540 | check_tnode(tn); |
1537 | n = tnode_get_child(tn ,tkey_extract_bits(key, tn->pos, tn->bits)); | 1541 | n = tnode_get_child(tn ,tkey_extract_bits(key, tn->pos, tn->bits)); |
1538 | 1542 | ||
1539 | BUG_ON(n && NODE_PARENT(n) != tn); | 1543 | BUG_ON(n && node_parent(n) != tn); |
1540 | } | 1544 | } |
1541 | l = (struct leaf *) n; | 1545 | l = (struct leaf *) n; |
1542 | 1546 | ||
@@ -1551,7 +1555,7 @@ static int trie_leaf_remove(struct trie *t, t_key key) | |||
1551 | t->revision++; | 1555 | t->revision++; |
1552 | t->size--; | 1556 | t->size--; |
1553 | 1557 | ||
1554 | tp = NODE_PARENT(n); | 1558 | tp = node_parent(n); |
1555 | tnode_free((struct tnode *) n); | 1559 | tnode_free((struct tnode *) n); |
1556 | 1560 | ||
1557 | if (tp) { | 1561 | if (tp) { |
@@ -1703,7 +1707,7 @@ static struct leaf *nextleaf(struct trie *t, struct leaf *thisleaf) | |||
1703 | 1707 | ||
1704 | p = (struct tnode*) trie; /* Start */ | 1708 | p = (struct tnode*) trie; /* Start */ |
1705 | } else | 1709 | } else |
1706 | p = (struct tnode *) NODE_PARENT(c); | 1710 | p = node_parent(c); |
1707 | 1711 | ||
1708 | while (p) { | 1712 | while (p) { |
1709 | int pos, last; | 1713 | int pos, last; |
@@ -1740,7 +1744,7 @@ static struct leaf *nextleaf(struct trie *t, struct leaf *thisleaf) | |||
1740 | up: | 1744 | up: |
1741 | /* No more children go up one step */ | 1745 | /* No more children go up one step */ |
1742 | c = (struct node *) p; | 1746 | c = (struct node *) p; |
1743 | p = (struct tnode *) NODE_PARENT(p); | 1747 | p = node_parent(c); |
1744 | } | 1748 | } |
1745 | return NULL; /* Ready. Root of trie */ | 1749 | return NULL; /* Ready. Root of trie */ |
1746 | } | 1750 | } |
@@ -2043,7 +2047,7 @@ rescan: | |||
2043 | } | 2047 | } |
2044 | 2048 | ||
2045 | /* Current node exhausted, pop back up */ | 2049 | /* Current node exhausted, pop back up */ |
2046 | p = NODE_PARENT(tn); | 2050 | p = node_parent((struct node *)tn); |
2047 | if (p) { | 2051 | if (p) { |
2048 | cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1; | 2052 | cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1; |
2049 | tn = p; | 2053 | tn = p; |
@@ -2317,7 +2321,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v) | |||
2317 | if (v == SEQ_START_TOKEN) | 2321 | if (v == SEQ_START_TOKEN) |
2318 | return 0; | 2322 | return 0; |
2319 | 2323 | ||
2320 | if (!NODE_PARENT(n)) { | 2324 | if (!node_parent(n)) { |
2321 | if (iter->trie == trie_local) | 2325 | if (iter->trie == trie_local) |
2322 | seq_puts(seq, "<local>:\n"); | 2326 | seq_puts(seq, "<local>:\n"); |
2323 | else | 2327 | else |