diff options
author | Alexei Starovoitov <ast@plumgrid.com> | 2015-08-25 23:06:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-26 14:01:44 -0400 |
commit | ed7aa879ce1a0ff6468c5a6d3eb4e31169b95c4a (patch) | |
tree | f219143241249dbe1e1fd49ec9d420363ebd8cbe /net/sched | |
parent | faa54be4c78da6aa2148c539659867afdecd3e8d (diff) |
net_sched: convert tcindex to call tcf_exts_destroy from rcu callback
Adjust destroy path of cls_tcindex to call tcf_exts_destroy() after
rcu grace period.
Signed-off-by: Alexei Starovoitov <ast@plumgrid.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/cls_tcindex.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index a557dbaf5afe..944c8ff45055 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
@@ -27,6 +27,7 @@ | |||
27 | struct tcindex_filter_result { | 27 | struct tcindex_filter_result { |
28 | struct tcf_exts exts; | 28 | struct tcf_exts exts; |
29 | struct tcf_result res; | 29 | struct tcf_result res; |
30 | struct rcu_head rcu; | ||
30 | }; | 31 | }; |
31 | 32 | ||
32 | struct tcindex_filter { | 33 | struct tcindex_filter { |
@@ -133,8 +134,23 @@ static int tcindex_init(struct tcf_proto *tp) | |||
133 | return 0; | 134 | return 0; |
134 | } | 135 | } |
135 | 136 | ||
136 | static int | 137 | static void tcindex_destroy_rexts(struct rcu_head *head) |
137 | tcindex_delete(struct tcf_proto *tp, unsigned long arg) | 138 | { |
139 | struct tcindex_filter_result *r; | ||
140 | |||
141 | r = container_of(head, struct tcindex_filter_result, rcu); | ||
142 | tcf_exts_destroy(&r->exts); | ||
143 | } | ||
144 | |||
145 | static void tcindex_destroy_fexts(struct rcu_head *head) | ||
146 | { | ||
147 | struct tcindex_filter *f = container_of(head, struct tcindex_filter, rcu); | ||
148 | |||
149 | tcf_exts_destroy(&f->result.exts); | ||
150 | kfree(f); | ||
151 | } | ||
152 | |||
153 | static int tcindex_delete(struct tcf_proto *tp, unsigned long arg) | ||
138 | { | 154 | { |
139 | struct tcindex_data *p = rtnl_dereference(tp->root); | 155 | struct tcindex_data *p = rtnl_dereference(tp->root); |
140 | struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg; | 156 | struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg; |
@@ -162,9 +178,14 @@ found: | |||
162 | rcu_assign_pointer(*walk, rtnl_dereference(f->next)); | 178 | rcu_assign_pointer(*walk, rtnl_dereference(f->next)); |
163 | } | 179 | } |
164 | tcf_unbind_filter(tp, &r->res); | 180 | tcf_unbind_filter(tp, &r->res); |
165 | tcf_exts_destroy(&r->exts); | 181 | /* all classifiers are required to call tcf_exts_destroy() after rcu |
182 | * grace period, since converted-to-rcu actions are relying on that | ||
183 | * in cleanup() callback | ||
184 | */ | ||
166 | if (f) | 185 | if (f) |
167 | kfree_rcu(f, rcu); | 186 | call_rcu(&f->rcu, tcindex_destroy_fexts); |
187 | else | ||
188 | call_rcu(&r->rcu, tcindex_destroy_rexts); | ||
168 | return 0; | 189 | return 0; |
169 | } | 190 | } |
170 | 191 | ||