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