diff options
author | James <> | 2015-11-04 11:49:21 +0000 |
---|---|---|
committer | James <> | 2015-11-04 11:49:21 +0000 |
commit | 716ca530e1c4515d8683c9d5be3d56b301758b66 (patch) | |
tree | 700eb5bcc1a462a5f21dcec15ce7c97ecfefa772 /target/linux/generic/patches-3.18/080-25-fib_trie-Various-clean-ups-for-handling-slen.patch | |
download | trunk-47381-716ca530e1c4515d8683c9d5be3d56b301758b66.tar.gz trunk-47381-716ca530e1c4515d8683c9d5be3d56b301758b66.tar.bz2 trunk-47381-716ca530e1c4515d8683c9d5be3d56b301758b66.zip |
Diffstat (limited to 'target/linux/generic/patches-3.18/080-25-fib_trie-Various-clean-ups-for-handling-slen.patch')
-rw-r--r-- | target/linux/generic/patches-3.18/080-25-fib_trie-Various-clean-ups-for-handling-slen.patch | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/target/linux/generic/patches-3.18/080-25-fib_trie-Various-clean-ups-for-handling-slen.patch b/target/linux/generic/patches-3.18/080-25-fib_trie-Various-clean-ups-for-handling-slen.patch new file mode 100644 index 0000000..c7739d0 --- /dev/null +++ b/target/linux/generic/patches-3.18/080-25-fib_trie-Various-clean-ups-for-handling-slen.patch @@ -0,0 +1,116 @@ +From: Alexander Duyck <alexander.h.duyck@redhat.com> +Date: Thu, 22 Jan 2015 15:51:45 -0800 +Subject: [PATCH] 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> +--- + +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -917,27 +917,20 @@ static void leaf_push_suffix(struct tnod + + static void remove_leaf_info(struct tnode *l, struct leaf_info *old) + { +- struct hlist_node *prev; +- +- /* record the location of the pointer to this object */ +- prev = rtnl_dereference(hlist_pprev_rcu(&old->hlist)); ++ /* record the location of the previous list_info entry */ ++ struct hlist_node **pprev = old->hlist.pprev; ++ struct leaf_info *li = hlist_entry(pprev, typeof(*li), hlist.next); + + /* remove the leaf info from the list */ + hlist_del_rcu(&old->hlist); + +- /* if we emptied the list this leaf will be freed and we can sort +- * out parent suffix lengths as a part of trie_rebalance +- */ +- if (hlist_empty(&l->list)) ++ /* only access li if it is pointing at the last valid hlist_node */ ++ if (hlist_empty(&l->list) || (*pprev)) + return; + +- /* if we removed the tail then we need to update slen */ +- if (!rcu_access_pointer(hlist_next_rcu(prev))) { +- struct leaf_info *li = hlist_entry(prev, typeof(*li), hlist); +- +- l->slen = KEYLENGTH - li->plen; +- leaf_pull_suffix(l); +- } ++ /* update the trie with the latest suffix length */ ++ l->slen = KEYLENGTH - li->plen; ++ leaf_pull_suffix(l); + } + + static void insert_leaf_info(struct tnode *l, struct leaf_info *new) +@@ -961,7 +954,7 @@ static void insert_leaf_info(struct tnod + } + + /* 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; + leaf_push_suffix(l); + } +@@ -1613,6 +1606,7 @@ static int trie_flush_leaf(struct tnode + struct hlist_head *lih = &l->list; + struct hlist_node *tmp; + struct leaf_info *li = NULL; ++ unsigned char plen = KEYLENGTH; + + hlist_for_each_entry_safe(li, tmp, lih, hlist) { + found += trie_flush_list(&li->falh); +@@ -1620,8 +1614,14 @@ static int trie_flush_leaf(struct tnode + if (list_empty(&li->falh)) { + hlist_del_rcu(&li->hlist); + free_leaf_info(li); ++ continue; + } ++ ++ plen = li->plen; + } ++ ++ l->slen = KEYLENGTH - plen; ++ + return found; + } + +@@ -1700,13 +1700,22 @@ int fib_table_flush(struct fib_table *tb + for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) { + found += trie_flush_leaf(l); + +- if (ll && hlist_empty(&ll->list)) +- trie_leaf_remove(t, ll); ++ if (ll) { ++ if (hlist_empty(&ll->list)) ++ trie_leaf_remove(t, ll); ++ else ++ leaf_pull_suffix(ll); ++ } ++ + ll = l; + } + +- if (ll && hlist_empty(&ll->list)) +- trie_leaf_remove(t, ll); ++ if (ll) { ++ if (hlist_empty(&ll->list)) ++ trie_leaf_remove(t, ll); ++ else ++ leaf_pull_suffix(ll); ++ } + + pr_debug("trie_flush found=%d\n", found); + return found; |