fib_trie: Various clean-ups for handling slen
While doing further work on the fib_trie I noted a few items. First I was using calls that were far more complicated than they needed to be for determining when to push/pull the suffix length. I have updated the code to reflect the simplier logic. The second issue is that I realised we weren't necessarily handling the case of a leaf_info struct surviving a flush. I have updated the logic so that now we will call pull_suffix in the event of having a leaf info value left in the leaf after flushing it. Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
02525368f4
commit
64c6272351
|
@ -917,27 +917,20 @@ static void leaf_push_suffix(struct tnode *l)
|
||||||
|
|
||||||
static void remove_leaf_info(struct tnode *l, struct leaf_info *old)
|
static void remove_leaf_info(struct tnode *l, struct leaf_info *old)
|
||||||
{
|
{
|
||||||
struct hlist_node *prev;
|
/* record the location of the previous list_info entry */
|
||||||
|
struct hlist_node **pprev = old->hlist.pprev;
|
||||||
/* record the location of the pointer to this object */
|
struct leaf_info *li = hlist_entry(pprev, typeof(*li), hlist.next);
|
||||||
prev = rtnl_dereference(hlist_pprev_rcu(&old->hlist));
|
|
||||||
|
|
||||||
/* remove the leaf info from the list */
|
/* remove the leaf info from the list */
|
||||||
hlist_del_rcu(&old->hlist);
|
hlist_del_rcu(&old->hlist);
|
||||||
|
|
||||||
/* if we emptied the list this leaf will be freed and we can sort
|
/* only access li if it is pointing at the last valid hlist_node */
|
||||||
* out parent suffix lengths as a part of trie_rebalance
|
if (hlist_empty(&l->list) || (*pprev))
|
||||||
*/
|
|
||||||
if (hlist_empty(&l->list))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* if we removed the tail then we need to update slen */
|
/* update the trie with the latest suffix length */
|
||||||
if (!rcu_access_pointer(hlist_next_rcu(prev))) {
|
l->slen = KEYLENGTH - li->plen;
|
||||||
struct leaf_info *li = hlist_entry(prev, typeof(*li), hlist);
|
leaf_pull_suffix(l);
|
||||||
|
|
||||||
l->slen = KEYLENGTH - li->plen;
|
|
||||||
leaf_pull_suffix(l);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void insert_leaf_info(struct tnode *l, struct leaf_info *new)
|
static void insert_leaf_info(struct tnode *l, struct leaf_info *new)
|
||||||
|
@ -961,7 +954,7 @@ static void insert_leaf_info(struct tnode *l, struct leaf_info *new)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if we added to the tail node then we need to update slen */
|
/* if we added to the tail node then we need to update slen */
|
||||||
if (!rcu_access_pointer(hlist_next_rcu(&new->hlist))) {
|
if (l->slen < (KEYLENGTH - new->plen)) {
|
||||||
l->slen = KEYLENGTH - new->plen;
|
l->slen = KEYLENGTH - new->plen;
|
||||||
leaf_push_suffix(l);
|
leaf_push_suffix(l);
|
||||||
}
|
}
|
||||||
|
@ -1613,6 +1606,7 @@ static int trie_flush_leaf(struct tnode *l)
|
||||||
struct hlist_head *lih = &l->list;
|
struct hlist_head *lih = &l->list;
|
||||||
struct hlist_node *tmp;
|
struct hlist_node *tmp;
|
||||||
struct leaf_info *li = NULL;
|
struct leaf_info *li = NULL;
|
||||||
|
unsigned char plen = KEYLENGTH;
|
||||||
|
|
||||||
hlist_for_each_entry_safe(li, tmp, lih, hlist) {
|
hlist_for_each_entry_safe(li, tmp, lih, hlist) {
|
||||||
found += trie_flush_list(&li->falh);
|
found += trie_flush_list(&li->falh);
|
||||||
|
@ -1620,8 +1614,14 @@ static int trie_flush_leaf(struct tnode *l)
|
||||||
if (list_empty(&li->falh)) {
|
if (list_empty(&li->falh)) {
|
||||||
hlist_del_rcu(&li->hlist);
|
hlist_del_rcu(&li->hlist);
|
||||||
free_leaf_info(li);
|
free_leaf_info(li);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plen = li->plen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
l->slen = KEYLENGTH - plen;
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1700,13 +1700,22 @@ int fib_table_flush(struct fib_table *tb)
|
||||||
for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
|
for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
|
||||||
found += trie_flush_leaf(l);
|
found += trie_flush_leaf(l);
|
||||||
|
|
||||||
if (ll && hlist_empty(&ll->list))
|
if (ll) {
|
||||||
trie_leaf_remove(t, ll);
|
if (hlist_empty(&ll->list))
|
||||||
|
trie_leaf_remove(t, ll);
|
||||||
|
else
|
||||||
|
leaf_pull_suffix(ll);
|
||||||
|
}
|
||||||
|
|
||||||
ll = l;
|
ll = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ll && hlist_empty(&ll->list))
|
if (ll) {
|
||||||
trie_leaf_remove(t, ll);
|
if (hlist_empty(&ll->list))
|
||||||
|
trie_leaf_remove(t, ll);
|
||||||
|
else
|
||||||
|
leaf_pull_suffix(ll);
|
||||||
|
}
|
||||||
|
|
||||||
pr_debug("trie_flush found=%d\n", found);
|
pr_debug("trie_flush found=%d\n", found);
|
||||||
return found;
|
return found;
|
||||||
|
|
Loading…
Reference in New Issue