Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alexei Starovoitov and committed by
David S. Miller
ed7aa879 faa54be4

+25 -4
+25 -4
net/sched/cls_tcindex.c
··· 27 27 struct tcindex_filter_result { 28 28 struct tcf_exts exts; 29 29 struct tcf_result res; 30 + struct rcu_head rcu; 30 31 }; 31 32 32 33 struct tcindex_filter { ··· 134 133 return 0; 135 134 } 136 135 137 - static int 138 - tcindex_delete(struct tcf_proto *tp, unsigned long arg) 136 + static void tcindex_destroy_rexts(struct rcu_head *head) 137 + { 138 + struct tcindex_filter_result *r; 139 + 140 + r = container_of(head, struct tcindex_filter_result, rcu); 141 + tcf_exts_destroy(&r->exts); 142 + } 143 + 144 + static void tcindex_destroy_fexts(struct rcu_head *head) 145 + { 146 + struct tcindex_filter *f = container_of(head, struct tcindex_filter, rcu); 147 + 148 + tcf_exts_destroy(&f->result.exts); 149 + kfree(f); 150 + } 151 + 152 + static int tcindex_delete(struct tcf_proto *tp, unsigned long arg) 139 153 { 140 154 struct tcindex_data *p = rtnl_dereference(tp->root); 141 155 struct tcindex_filter_result *r = (struct tcindex_filter_result *) arg; ··· 178 162 rcu_assign_pointer(*walk, rtnl_dereference(f->next)); 179 163 } 180 164 tcf_unbind_filter(tp, &r->res); 181 - tcf_exts_destroy(&r->exts); 165 + /* all classifiers are required to call tcf_exts_destroy() after rcu 166 + * grace period, since converted-to-rcu actions are relying on that 167 + * in cleanup() callback 168 + */ 182 169 if (f) 183 - kfree_rcu(f, rcu); 170 + call_rcu(&f->rcu, tcindex_destroy_fexts); 171 + else 172 + call_rcu(&r->rcu, tcindex_destroy_rexts); 184 173 return 0; 185 174 } 186 175