080-25-fib_trie-Various-clean-ups-for-handling-slen.patch 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. From: Alexander Duyck <alexander.h.duyck@redhat.com>
  2. Date: Thu, 22 Jan 2015 15:51:45 -0800
  3. Subject: [PATCH] fib_trie: Various clean-ups for handling slen
  4. While doing further work on the fib_trie I noted a few items.
  5. First I was using calls that were far more complicated than they needed to
  6. be for determining when to push/pull the suffix length. I have updated the
  7. code to reflect the simplier logic.
  8. The second issue is that I realised we weren't necessarily handling the
  9. case of a leaf_info struct surviving a flush. I have updated the logic so
  10. that now we will call pull_suffix in the event of having a leaf info value
  11. left in the leaf after flushing it.
  12. Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
  13. Signed-off-by: David S. Miller <davem@davemloft.net>
  14. ---
  15. --- a/net/ipv4/fib_trie.c
  16. +++ b/net/ipv4/fib_trie.c
  17. @@ -917,27 +917,20 @@ static void leaf_push_suffix(struct tnod
  18. static void remove_leaf_info(struct tnode *l, struct leaf_info *old)
  19. {
  20. - struct hlist_node *prev;
  21. -
  22. - /* record the location of the pointer to this object */
  23. - prev = rtnl_dereference(hlist_pprev_rcu(&old->hlist));
  24. + /* record the location of the previous list_info entry */
  25. + struct hlist_node **pprev = old->hlist.pprev;
  26. + struct leaf_info *li = hlist_entry(pprev, typeof(*li), hlist.next);
  27. /* remove the leaf info from the list */
  28. hlist_del_rcu(&old->hlist);
  29. - /* if we emptied the list this leaf will be freed and we can sort
  30. - * out parent suffix lengths as a part of trie_rebalance
  31. - */
  32. - if (hlist_empty(&l->list))
  33. + /* only access li if it is pointing at the last valid hlist_node */
  34. + if (hlist_empty(&l->list) || (*pprev))
  35. return;
  36. - /* if we removed the tail then we need to update slen */
  37. - if (!rcu_access_pointer(hlist_next_rcu(prev))) {
  38. - struct leaf_info *li = hlist_entry(prev, typeof(*li), hlist);
  39. -
  40. - l->slen = KEYLENGTH - li->plen;
  41. - leaf_pull_suffix(l);
  42. - }
  43. + /* update the trie with the latest suffix length */
  44. + l->slen = KEYLENGTH - li->plen;
  45. + leaf_pull_suffix(l);
  46. }
  47. static void insert_leaf_info(struct tnode *l, struct leaf_info *new)
  48. @@ -961,7 +954,7 @@ static void insert_leaf_info(struct tnod
  49. }
  50. /* if we added to the tail node then we need to update slen */
  51. - if (!rcu_access_pointer(hlist_next_rcu(&new->hlist))) {
  52. + if (l->slen < (KEYLENGTH - new->plen)) {
  53. l->slen = KEYLENGTH - new->plen;
  54. leaf_push_suffix(l);
  55. }
  56. @@ -1613,6 +1606,7 @@ static int trie_flush_leaf(struct tnode
  57. struct hlist_head *lih = &l->list;
  58. struct hlist_node *tmp;
  59. struct leaf_info *li = NULL;
  60. + unsigned char plen = KEYLENGTH;
  61. hlist_for_each_entry_safe(li, tmp, lih, hlist) {
  62. found += trie_flush_list(&li->falh);
  63. @@ -1620,8 +1614,14 @@ static int trie_flush_leaf(struct tnode
  64. if (list_empty(&li->falh)) {
  65. hlist_del_rcu(&li->hlist);
  66. free_leaf_info(li);
  67. + continue;
  68. }
  69. +
  70. + plen = li->plen;
  71. }
  72. +
  73. + l->slen = KEYLENGTH - plen;
  74. +
  75. return found;
  76. }
  77. @@ -1700,13 +1700,22 @@ int fib_table_flush(struct fib_table *tb
  78. for (l = trie_firstleaf(t); l; l = trie_nextleaf(l)) {
  79. found += trie_flush_leaf(l);
  80. - if (ll && hlist_empty(&ll->list))
  81. - trie_leaf_remove(t, ll);
  82. + if (ll) {
  83. + if (hlist_empty(&ll->list))
  84. + trie_leaf_remove(t, ll);
  85. + else
  86. + leaf_pull_suffix(ll);
  87. + }
  88. +
  89. ll = l;
  90. }
  91. - if (ll && hlist_empty(&ll->list))
  92. - trie_leaf_remove(t, ll);
  93. + if (ll) {
  94. + if (hlist_empty(&ll->list))
  95. + trie_leaf_remove(t, ll);
  96. + else
  97. + leaf_pull_suffix(ll);
  98. + }
  99. pr_debug("trie_flush found=%d\n", found);
  100. return found;