@@ -117,15 +117,15 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
117117{
118118 struct net * net = sock_net (skb -> sk );
119119 struct nlattr * tca [TCA_MAX + 1 ];
120- spinlock_t * root_lock ;
121120 struct tcmsg * t ;
122121 u32 protocol ;
123122 u32 prio ;
124123 u32 nprio ;
125124 u32 parent ;
126125 struct net_device * dev ;
127126 struct Qdisc * q ;
128- struct tcf_proto * * back , * * chain ;
127+ struct tcf_proto __rcu * * back ;
128+ struct tcf_proto __rcu * * chain ;
129129 struct tcf_proto * tp ;
130130 const struct tcf_proto_ops * tp_ops ;
131131 const struct Qdisc_class_ops * cops ;
@@ -197,7 +197,9 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
197197 goto errout ;
198198
199199 /* Check the chain for existence of proto-tcf with this priority */
200- for (back = chain ; (tp = * back ) != NULL ; back = & tp -> next ) {
200+ for (back = chain ;
201+ (tp = rtnl_dereference (* back )) != NULL ;
202+ back = & tp -> next ) {
201203 if (tp -> prio >= prio ) {
202204 if (tp -> prio == prio ) {
203205 if (!nprio ||
@@ -209,8 +211,6 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
209211 }
210212 }
211213
212- root_lock = qdisc_root_sleeping_lock (q );
213-
214214 if (tp == NULL ) {
215215 /* Proto-tcf does not exist, create new one */
216216
@@ -259,7 +259,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
259259 }
260260 tp -> ops = tp_ops ;
261261 tp -> protocol = protocol ;
262- tp -> prio = nprio ? : TC_H_MAJ (tcf_auto_prio (* back ));
262+ tp -> prio = nprio ? :
263+ TC_H_MAJ (tcf_auto_prio (rtnl_dereference (* back )));
263264 tp -> q = q ;
264265 tp -> classify = tp_ops -> classify ;
265266 tp -> classid = parent ;
@@ -280,9 +281,9 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
280281
281282 if (fh == 0 ) {
282283 if (n -> nlmsg_type == RTM_DELTFILTER && t -> tcm_handle == 0 ) {
283- spin_lock_bh ( root_lock );
284- * back = tp -> next ;
285- spin_unlock_bh ( root_lock );
284+ struct tcf_proto * next = rtnl_dereference ( tp -> next );
285+
286+ RCU_INIT_POINTER ( * back , next );
286287
287288 tfilter_notify (net , skb , n , tp , fh , RTM_DELTFILTER );
288289 tcf_destroy (tp );
@@ -322,10 +323,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
322323 n -> nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE );
323324 if (err == 0 ) {
324325 if (tp_created ) {
325- spin_lock_bh (root_lock );
326- tp -> next = * back ;
327- * back = tp ;
328- spin_unlock_bh (root_lock );
326+ RCU_INIT_POINTER (tp -> next , rtnl_dereference (* back ));
327+ rcu_assign_pointer (* back , tp );
329328 }
330329 tfilter_notify (net , skb , n , tp , fh , RTM_NEWTFILTER );
331330 } else {
@@ -420,7 +419,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
420419 int s_t ;
421420 struct net_device * dev ;
422421 struct Qdisc * q ;
423- struct tcf_proto * tp , * * chain ;
422+ struct tcf_proto * tp , __rcu * * chain ;
424423 struct tcmsg * tcm = nlmsg_data (cb -> nlh );
425424 unsigned long cl = 0 ;
426425 const struct Qdisc_class_ops * cops ;
@@ -454,7 +453,8 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
454453
455454 s_t = cb -> args [0 ];
456455
457- for (tp = * chain , t = 0 ; tp ; tp = tp -> next , t ++ ) {
456+ for (tp = rtnl_dereference (* chain ), t = 0 ;
457+ tp ; tp = rtnl_dereference (tp -> next ), t ++ ) {
458458 if (t < s_t )
459459 continue ;
460460 if (TC_H_MAJ (tcm -> tcm_info ) &&
0 commit comments