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 | ||
