aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2018-02-02 10:02:22 -0500
committerDavid S. Miller <davem@davemloft.net>2018-02-02 19:25:03 -0500
commit058a6c033488494a6b1477b05fe8e1a16e344462 (patch)
tree4a415b70f6fb7356d1c093e9c4cc12e17d3052bb
parent0072f0c40b1fe9a8b2a530b84af0ce66f55cde98 (diff)
cls_u32: add missing RCU annotation.
In a couple of points of the control path, n->ht_down is currently accessed without the required RCU annotation. The accesses are safe, but sparse complaints. Since we already held the rtnl lock, let use rtnl_dereference(). Fixes: a1b7c5fd7fe9 ("net: sched: add cls_u32 offload hooks for netdevs") Fixes: de5df63228fc ("net: sched: cls_u32 changes to knode must appear atomic to readers") Signed-off-by: Paolo Abeni <pabeni@redhat.com> Acked-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sched/cls_u32.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 60c892c36a60..e3c5e390ec23 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -548,6 +548,7 @@ static void u32_remove_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
548static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n, 548static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
549 u32 flags, struct netlink_ext_ack *extack) 549 u32 flags, struct netlink_ext_ack *extack)
550{ 550{
551 struct tc_u_hnode *ht = rtnl_dereference(n->ht_down);
551 struct tcf_block *block = tp->chain->block; 552 struct tcf_block *block = tp->chain->block;
552 struct tc_cls_u32_offload cls_u32 = {}; 553 struct tc_cls_u32_offload cls_u32 = {};
553 bool skip_sw = tc_skip_sw(flags); 554 bool skip_sw = tc_skip_sw(flags);
@@ -567,7 +568,7 @@ static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
567 cls_u32.knode.sel = &n->sel; 568 cls_u32.knode.sel = &n->sel;
568 cls_u32.knode.exts = &n->exts; 569 cls_u32.knode.exts = &n->exts;
569 if (n->ht_down) 570 if (n->ht_down)
570 cls_u32.knode.link_handle = n->ht_down->handle; 571 cls_u32.knode.link_handle = ht->handle;
571 572
572 err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, skip_sw); 573 err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, skip_sw);
573 if (err < 0) { 574 if (err < 0) {
@@ -855,8 +856,9 @@ static void u32_replace_knode(struct tcf_proto *tp, struct tc_u_common *tp_c,
855static struct tc_u_knode *u32_init_knode(struct tcf_proto *tp, 856static struct tc_u_knode *u32_init_knode(struct tcf_proto *tp,
856 struct tc_u_knode *n) 857 struct tc_u_knode *n)
857{ 858{
858 struct tc_u_knode *new; 859 struct tc_u_hnode *ht = rtnl_dereference(n->ht_down);
859 struct tc_u32_sel *s = &n->sel; 860 struct tc_u32_sel *s = &n->sel;
861 struct tc_u_knode *new;
860 862
861 new = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), 863 new = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key),
862 GFP_KERNEL); 864 GFP_KERNEL);
@@ -874,11 +876,11 @@ static struct tc_u_knode *u32_init_knode(struct tcf_proto *tp,
874 new->fshift = n->fshift; 876 new->fshift = n->fshift;
875 new->res = n->res; 877 new->res = n->res;
876 new->flags = n->flags; 878 new->flags = n->flags;
877 RCU_INIT_POINTER(new->ht_down, n->ht_down); 879 RCU_INIT_POINTER(new->ht_down, ht);
878 880
879 /* bump reference count as long as we hold pointer to structure */ 881 /* bump reference count as long as we hold pointer to structure */
880 if (new->ht_down) 882 if (ht)
881 new->ht_down->refcnt++; 883 ht->refcnt++;
882 884
883#ifdef CONFIG_CLS_U32_PERF 885#ifdef CONFIG_CLS_U32_PERF
884 /* Statistics may be incremented by readers during update 886 /* Statistics may be incremented by readers during update