summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sched/cls_u32.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index dadd1b344497..b58eccb21f03 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -399,6 +399,7 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n,
399 bool free_pf) 399 bool free_pf)
400{ 400{
401 tcf_exts_destroy(&n->exts); 401 tcf_exts_destroy(&n->exts);
402 tcf_exts_put_net(&n->exts);
402 if (n->ht_down) 403 if (n->ht_down)
403 n->ht_down->refcnt--; 404 n->ht_down->refcnt--;
404#ifdef CONFIG_CLS_U32_PERF 405#ifdef CONFIG_CLS_U32_PERF
@@ -476,6 +477,7 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
476 RCU_INIT_POINTER(*kp, key->next); 477 RCU_INIT_POINTER(*kp, key->next);
477 478
478 tcf_unbind_filter(tp, &key->res); 479 tcf_unbind_filter(tp, &key->res);
480 tcf_exts_get_net(&key->exts);
479 call_rcu(&key->rcu, u32_delete_key_freepf_rcu); 481 call_rcu(&key->rcu, u32_delete_key_freepf_rcu);
480 return 0; 482 return 0;
481 } 483 }
@@ -588,7 +590,10 @@ static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
588 rtnl_dereference(n->next)); 590 rtnl_dereference(n->next));
589 tcf_unbind_filter(tp, &n->res); 591 tcf_unbind_filter(tp, &n->res);
590 u32_remove_hw_knode(tp, n->handle); 592 u32_remove_hw_knode(tp, n->handle);
591 call_rcu(&n->rcu, u32_delete_key_freepf_rcu); 593 if (tcf_exts_get_net(&n->exts))
594 call_rcu(&n->rcu, u32_delete_key_freepf_rcu);
595 else
596 u32_destroy_key(n->tp, n, true);
592 } 597 }
593 } 598 }
594} 599}
@@ -949,6 +954,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
949 954
950 u32_replace_knode(tp, tp_c, new); 955 u32_replace_knode(tp, tp_c, new);
951 tcf_unbind_filter(tp, &n->res); 956 tcf_unbind_filter(tp, &n->res);
957 tcf_exts_get_net(&n->exts);
952 call_rcu(&n->rcu, u32_delete_key_rcu); 958 call_rcu(&n->rcu, u32_delete_key_rcu);
953 return 0; 959 return 0;
954 } 960 }