@@ -117,15 +117,15 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
117
117
{
118
118
struct net * net = sock_net (skb -> sk );
119
119
struct nlattr * tca [TCA_MAX + 1 ];
120
- spinlock_t * root_lock ;
121
120
struct tcmsg * t ;
122
121
u32 protocol ;
123
122
u32 prio ;
124
123
u32 nprio ;
125
124
u32 parent ;
126
125
struct net_device * dev ;
127
126
struct Qdisc * q ;
128
- struct tcf_proto * * back , * * chain ;
127
+ struct tcf_proto __rcu * * back ;
128
+ struct tcf_proto __rcu * * chain ;
129
129
struct tcf_proto * tp ;
130
130
const struct tcf_proto_ops * tp_ops ;
131
131
const struct Qdisc_class_ops * cops ;
@@ -197,7 +197,9 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
197
197
goto errout ;
198
198
199
199
/* 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 ) {
201
203
if (tp -> prio >= prio ) {
202
204
if (tp -> prio == prio ) {
203
205
if (!nprio ||
@@ -209,8 +211,6 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
209
211
}
210
212
}
211
213
212
- root_lock = qdisc_root_sleeping_lock (q );
213
-
214
214
if (tp == NULL ) {
215
215
/* Proto-tcf does not exist, create new one */
216
216
@@ -259,7 +259,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
259
259
}
260
260
tp -> ops = tp_ops ;
261
261
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 )));
263
264
tp -> q = q ;
264
265
tp -> classify = tp_ops -> classify ;
265
266
tp -> classid = parent ;
@@ -280,9 +281,9 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
280
281
281
282
if (fh == 0 ) {
282
283
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 );
286
287
287
288
tfilter_notify (net , skb , n , tp , fh , RTM_DELTFILTER );
288
289
tcf_destroy (tp );
@@ -322,10 +323,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
322
323
n -> nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE );
323
324
if (err == 0 ) {
324
325
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 );
329
328
}
330
329
tfilter_notify (net , skb , n , tp , fh , RTM_NEWTFILTER );
331
330
} else {
@@ -420,7 +419,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
420
419
int s_t ;
421
420
struct net_device * dev ;
422
421
struct Qdisc * q ;
423
- struct tcf_proto * tp , * * chain ;
422
+ struct tcf_proto * tp , __rcu * * chain ;
424
423
struct tcmsg * tcm = nlmsg_data (cb -> nlh );
425
424
unsigned long cl = 0 ;
426
425
const struct Qdisc_class_ops * cops ;
@@ -454,7 +453,8 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
454
453
455
454
s_t = cb -> args [0 ];
456
455
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 ++ ) {
458
458
if (t < s_t )
459
459
continue ;
460
460
if (TC_H_MAJ (tcm -> tcm_info ) &&
0 commit comments