aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/pending-3.18/080-11-fib_trie-Push-rcu_read_lock-unlock-to-callers.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/pending-3.18/080-11-fib_trie-Push-rcu_read_lock-unlock-to-callers.patch')
-rw-r--r--target/linux/generic/pending-3.18/080-11-fib_trie-Push-rcu_read_lock-unlock-to-callers.patch403
1 files changed, 0 insertions, 403 deletions
diff --git a/target/linux/generic/pending-3.18/080-11-fib_trie-Push-rcu_read_lock-unlock-to-callers.patch b/target/linux/generic/pending-3.18/080-11-fib_trie-Push-rcu_read_lock-unlock-to-callers.patch
deleted file mode 100644
index 29bec8387d..0000000000
--- a/target/linux/generic/pending-3.18/080-11-fib_trie-Push-rcu_read_lock-unlock-to-callers.patch
+++ /dev/null
@@ -1,403 +0,0 @@
-From: Alexander Duyck <alexander.h.duyck@redhat.com>
-Date: Wed, 31 Dec 2014 10:56:24 -0800
-Subject: [PATCH] fib_trie: Push rcu_read_lock/unlock to callers
-
-This change is to start cleaning up some of the rcu_read_lock/unlock
-handling. I realized while reviewing the code there are several spots that
-I don't believe are being handled correctly or are masking warnings by
-locally calling rcu_read_lock/unlock instead of calling them at the correct
-level.
-
-A common example is a call to fib_get_table followed by fib_table_lookup.
-The rcu_read_lock/unlock ought to wrap both but there are several spots where
-they were not wrapped.
-
-Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/include/net/ip_fib.h
-+++ b/include/net/ip_fib.h
-@@ -222,16 +222,19 @@ static inline struct fib_table *fib_new_
- static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
- struct fib_result *res)
- {
-- struct fib_table *table;
-+ int err = -ENETUNREACH;
-
-- table = fib_get_table(net, RT_TABLE_LOCAL);
-- if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
-- return 0;
--
-- table = fib_get_table(net, RT_TABLE_MAIN);
-- if (!fib_table_lookup(table, flp, res, FIB_LOOKUP_NOREF))
-- return 0;
-- return -ENETUNREACH;
-+ rcu_read_lock();
-+
-+ if (!fib_table_lookup(fib_get_table(net, RT_TABLE_LOCAL), flp, res,
-+ FIB_LOOKUP_NOREF) ||
-+ !fib_table_lookup(fib_get_table(net, RT_TABLE_MAIN), flp, res,
-+ FIB_LOOKUP_NOREF))
-+ err = 0;
-+
-+ rcu_read_unlock();
-+
-+ return err;
- }
-
- #else /* CONFIG_IP_MULTIPLE_TABLES */
-@@ -247,20 +250,25 @@ static inline int fib_lookup(struct net
- struct fib_result *res)
- {
- if (!net->ipv4.fib_has_custom_rules) {
-+ int err = -ENETUNREACH;
-+
-+ rcu_read_lock();
-+
- res->tclassid = 0;
-- if (net->ipv4.fib_local &&
-- !fib_table_lookup(net->ipv4.fib_local, flp, res,
-- FIB_LOOKUP_NOREF))
-- return 0;
-- if (net->ipv4.fib_main &&
-- !fib_table_lookup(net->ipv4.fib_main, flp, res,
-- FIB_LOOKUP_NOREF))
-- return 0;
-- if (net->ipv4.fib_default &&
-- !fib_table_lookup(net->ipv4.fib_default, flp, res,
-- FIB_LOOKUP_NOREF))
-- return 0;
-- return -ENETUNREACH;
-+ if ((net->ipv4.fib_local &&
-+ !fib_table_lookup(net->ipv4.fib_local, flp, res,
-+ FIB_LOOKUP_NOREF)) ||
-+ (net->ipv4.fib_main &&
-+ !fib_table_lookup(net->ipv4.fib_main, flp, res,
-+ FIB_LOOKUP_NOREF)) ||
-+ (net->ipv4.fib_default &&
-+ !fib_table_lookup(net->ipv4.fib_default, flp, res,
-+ FIB_LOOKUP_NOREF)))
-+ err = 0;
-+
-+ rcu_read_unlock();
-+
-+ return err;
- }
- return __fib_lookup(net, flp, res);
- }
---- a/net/ipv4/fib_frontend.c
-+++ b/net/ipv4/fib_frontend.c
-@@ -109,6 +109,7 @@ struct fib_table *fib_new_table(struct n
- return tb;
- }
-
-+/* caller must hold either rtnl or rcu read lock */
- struct fib_table *fib_get_table(struct net *net, u32 id)
- {
- struct fib_table *tb;
-@@ -119,15 +120,11 @@ struct fib_table *fib_get_table(struct n
- id = RT_TABLE_MAIN;
- h = id & (FIB_TABLE_HASHSZ - 1);
-
-- rcu_read_lock();
- head = &net->ipv4.fib_table_hash[h];
- hlist_for_each_entry_rcu(tb, head, tb_hlist) {
-- if (tb->tb_id == id) {
-- rcu_read_unlock();
-+ if (tb->tb_id == id)
- return tb;
-- }
- }
-- rcu_read_unlock();
- return NULL;
- }
- #endif /* CONFIG_IP_MULTIPLE_TABLES */
-@@ -167,16 +164,18 @@ static inline unsigned int __inet_dev_ad
- if (ipv4_is_multicast(addr))
- return RTN_MULTICAST;
-
-+ rcu_read_lock();
-+
- local_table = fib_get_table(net, RT_TABLE_LOCAL);
- if (local_table) {
- ret = RTN_UNICAST;
-- rcu_read_lock();
- if (!fib_table_lookup(local_table, &fl4, &res, FIB_LOOKUP_NOREF)) {
- if (!dev || dev == res.fi->fib_dev)
- ret = res.type;
- }
-- rcu_read_unlock();
- }
-+
-+ rcu_read_unlock();
- return ret;
- }
-
-@@ -923,7 +922,7 @@ no_promotions:
- #undef BRD1_OK
- }
-
--static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
-+static void nl_fib_lookup(struct net *net, struct fib_result_nl *frn)
- {
-
- struct fib_result res;
-@@ -933,6 +932,11 @@ static void nl_fib_lookup(struct fib_res
- .flowi4_tos = frn->fl_tos,
- .flowi4_scope = frn->fl_scope,
- };
-+ struct fib_table *tb;
-+
-+ rcu_read_lock();
-+
-+ tb = fib_get_table(net, frn->tb_id_in);
-
- frn->err = -ENOENT;
- if (tb) {
-@@ -949,6 +953,8 @@ static void nl_fib_lookup(struct fib_res
- }
- local_bh_enable();
- }
-+
-+ rcu_read_unlock();
- }
-
- static void nl_fib_input(struct sk_buff *skb)
-@@ -956,7 +962,6 @@ static void nl_fib_input(struct sk_buff
- struct net *net;
- struct fib_result_nl *frn;
- struct nlmsghdr *nlh;
-- struct fib_table *tb;
- u32 portid;
-
- net = sock_net(skb->sk);
-@@ -972,9 +977,7 @@ static void nl_fib_input(struct sk_buff
- nlh = nlmsg_hdr(skb);
-
- frn = (struct fib_result_nl *) nlmsg_data(nlh);
-- tb = fib_get_table(net, frn->tb_id_in);
--
-- nl_fib_lookup(frn, tb);
-+ nl_fib_lookup(net, frn);
-
- portid = NETLINK_CB(skb).portid; /* netlink portid */
- NETLINK_CB(skb).portid = 0; /* from kernel */
---- a/net/ipv4/fib_rules.c
-+++ b/net/ipv4/fib_rules.c
-@@ -81,27 +81,25 @@ static int fib4_rule_action(struct fib_r
- break;
-
- case FR_ACT_UNREACHABLE:
-- err = -ENETUNREACH;
-- goto errout;
-+ return -ENETUNREACH;
-
- case FR_ACT_PROHIBIT:
-- err = -EACCES;
-- goto errout;
-+ return -EACCES;
-
- case FR_ACT_BLACKHOLE:
- default:
-- err = -EINVAL;
-- goto errout;
-+ return -EINVAL;
- }
-
-+ rcu_read_lock();
-+
- tbl = fib_get_table(rule->fr_net, rule->table);
-- if (!tbl)
-- goto errout;
-+ if (tbl)
-+ err = fib_table_lookup(tbl, &flp->u.ip4,
-+ (struct fib_result *)arg->result,
-+ arg->flags);
-
-- err = fib_table_lookup(tbl, &flp->u.ip4, (struct fib_result *) arg->result, arg->flags);
-- if (err > 0)
-- err = -EAGAIN;
--errout:
-+ rcu_read_unlock();
- return err;
- }
-
---- a/net/ipv4/fib_trie.c
-+++ b/net/ipv4/fib_trie.c
-@@ -1181,72 +1181,6 @@ err:
- return err;
- }
-
--/* should be called with rcu_read_lock */
--static int check_leaf(struct fib_table *tb, struct trie *t, struct tnode *l,
-- t_key key, const struct flowi4 *flp,
-- struct fib_result *res, int fib_flags)
--{
-- struct leaf_info *li;
-- struct hlist_head *hhead = &l->list;
--
-- hlist_for_each_entry_rcu(li, hhead, hlist) {
-- struct fib_alias *fa;
--
-- if (l->key != (key & li->mask_plen))
-- continue;
--
-- list_for_each_entry_rcu(fa, &li->falh, fa_list) {
-- struct fib_info *fi = fa->fa_info;
-- int nhsel, err;
--
-- if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
-- continue;
-- if (fi->fib_dead)
-- continue;
-- if (fa->fa_info->fib_scope < flp->flowi4_scope)
-- continue;
-- fib_alias_accessed(fa);
-- err = fib_props[fa->fa_type].error;
-- if (unlikely(err < 0)) {
--#ifdef CONFIG_IP_FIB_TRIE_STATS
-- this_cpu_inc(t->stats->semantic_match_passed);
--#endif
-- return err;
-- }
-- if (fi->fib_flags & RTNH_F_DEAD)
-- continue;
-- for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
-- const struct fib_nh *nh = &fi->fib_nh[nhsel];
--
-- if (nh->nh_flags & RTNH_F_DEAD)
-- continue;
-- if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif)
-- continue;
--
--#ifdef CONFIG_IP_FIB_TRIE_STATS
-- this_cpu_inc(t->stats->semantic_match_passed);
--#endif
-- res->prefixlen = li->plen;
-- res->nh_sel = nhsel;
-- res->type = fa->fa_type;
-- res->scope = fi->fib_scope;
-- res->fi = fi;
-- res->table = tb;
-- res->fa_head = &li->falh;
-- if (!(fib_flags & FIB_LOOKUP_NOREF))
-- atomic_inc(&fi->fib_clntref);
-- return 0;
-- }
-- }
--
--#ifdef CONFIG_IP_FIB_TRIE_STATS
-- this_cpu_inc(t->stats->semantic_match_miss);
--#endif
-- }
--
-- return 1;
--}
--
- static inline t_key prefix_mismatch(t_key key, struct tnode *n)
- {
- t_key prefix = n->key;
-@@ -1254,6 +1188,7 @@ static inline t_key prefix_mismatch(t_ke
- return (key ^ prefix) & (prefix | -prefix);
- }
-
-+/* should be called with rcu_read_lock */
- int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
- struct fib_result *res, int fib_flags)
- {
-@@ -1263,14 +1198,12 @@ int fib_table_lookup(struct fib_table *t
- #endif
- const t_key key = ntohl(flp->daddr);
- struct tnode *n, *pn;
-+ struct leaf_info *li;
- t_key cindex;
-- int ret = 1;
--
-- rcu_read_lock();
-
- n = rcu_dereference(t->trie);
- if (!n)
-- goto failed;
-+ return -EAGAIN;
-
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- this_cpu_inc(stats->gets);
-@@ -1350,7 +1283,7 @@ backtrace:
-
- pn = node_parent_rcu(pn);
- if (unlikely(!pn))
-- goto failed;
-+ return -EAGAIN;
- #ifdef CONFIG_IP_FIB_TRIE_STATS
- this_cpu_inc(stats->backtrack);
- #endif
-@@ -1368,12 +1301,62 @@ backtrace:
-
- found:
- /* Step 3: Process the leaf, if that fails fall back to backtracing */
-- ret = check_leaf(tb, t, n, key, flp, res, fib_flags);
-- if (unlikely(ret > 0))
-- goto backtrace;
--failed:
-- rcu_read_unlock();
-- return ret;
-+ hlist_for_each_entry_rcu(li, &n->list, hlist) {
-+ struct fib_alias *fa;
-+
-+ if ((key ^ n->key) & li->mask_plen)
-+ continue;
-+
-+ list_for_each_entry_rcu(fa, &li->falh, fa_list) {
-+ struct fib_info *fi = fa->fa_info;
-+ int nhsel, err;
-+
-+ if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
-+ continue;
-+ if (fi->fib_dead)
-+ continue;
-+ if (fa->fa_info->fib_scope < flp->flowi4_scope)
-+ continue;
-+ fib_alias_accessed(fa);
-+ err = fib_props[fa->fa_type].error;
-+ if (unlikely(err < 0)) {
-+#ifdef CONFIG_IP_FIB_TRIE_STATS
-+ this_cpu_inc(stats->semantic_match_passed);
-+#endif
-+ return err;
-+ }
-+ if (fi->fib_flags & RTNH_F_DEAD)
-+ continue;
-+ for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
-+ const struct fib_nh *nh = &fi->fib_nh[nhsel];
-+
-+ if (nh->nh_flags & RTNH_F_DEAD)
-+ continue;
-+ if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif)
-+ continue;
-+
-+ if (!(fib_flags & FIB_LOOKUP_NOREF))
-+ atomic_inc(&fi->fib_clntref);
-+
-+ res->prefixlen = li->plen;
-+ res->nh_sel = nhsel;
-+ res->type = fa->fa_type;
-+ res->scope = fi->fib_scope;
-+ res->fi = fi;
-+ res->table = tb;
-+ res->fa_head = &li->falh;
-+#ifdef CONFIG_IP_FIB_TRIE_STATS
-+ this_cpu_inc(stats->semantic_match_passed);
-+#endif
-+ return err;
-+ }
-+ }
-+
-+#ifdef CONFIG_IP_FIB_TRIE_STATS
-+ this_cpu_inc(stats->semantic_match_miss);
-+#endif
-+ }
-+ goto backtrace;
- }
- EXPORT_SYMBOL_GPL(fib_table_lookup);
-