@ -117,7 +117,6 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
{
struct net * net = sock_net ( skb - > sk ) ;
struct nlattr * tca [ TCA_MAX + 1 ] ;
spinlock_t * root_lock ;
struct tcmsg * t ;
u32 protocol ;
u32 prio ;
@ -125,7 +124,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n)
u32 parent ;
struct net_device * dev ;
struct Qdisc * q ;
struct tcf_proto * * back , * * chain ;
struct tcf_proto __rcu * * back ;
struct tcf_proto __rcu * * chain ;
struct tcf_proto * tp ;
const struct tcf_proto_ops * tp_ops ;
const struct Qdisc_class_ops * cops ;
@ -197,7 +197,9 @@ replay:
goto errout ;
/* Check the chain for existence of proto-tcf with this priority */
for ( back = chain ; ( tp = * back ) ! = NULL ; back = & tp - > next ) {
for ( back = chain ;
( tp = rtnl_dereference ( * back ) ) ! = NULL ;
back = & tp - > next ) {
if ( tp - > prio > = prio ) {
if ( tp - > prio = = prio ) {
if ( ! nprio | |
@ -209,8 +211,6 @@ replay:
}
}
root_lock = qdisc_root_sleeping_lock ( q ) ;
if ( tp = = NULL ) {
/* Proto-tcf does not exist, create new one */
@ -259,7 +259,8 @@ replay:
}
tp - > ops = tp_ops ;
tp - > protocol = protocol ;
tp - > prio = nprio ? : TC_H_MAJ ( tcf_auto_prio ( * back ) ) ;
tp - > prio = nprio ? :
TC_H_MAJ ( tcf_auto_prio ( rtnl_dereference ( * back ) ) ) ;
tp - > q = q ;
tp - > classify = tp_ops - > classify ;
tp - > classid = parent ;
@ -280,9 +281,9 @@ replay:
if ( fh = = 0 ) {
if ( n - > nlmsg_type = = RTM_DELTFILTER & & t - > tcm_handle = = 0 ) {
spin_lock_bh ( root_lock ) ;
* back = tp - > next ;
spin_unlock_bh ( root_lock ) ;
struct tcf_proto * next = rtnl_dereference ( tp - > next ) ;
RCU_INIT_POINTER ( * back , next ) ;
tfilter_notify ( net , skb , n , tp , fh , RTM_DELTFILTER ) ;
tcf_destroy ( tp ) ;
@ -322,10 +323,8 @@ replay:
n - > nlmsg_flags & NLM_F_CREATE ? TCA_ACT_NOREPLACE : TCA_ACT_REPLACE ) ;
if ( err = = 0 ) {
if ( tp_created ) {
spin_lock_bh ( root_lock ) ;
tp - > next = * back ;
* back = tp ;
spin_unlock_bh ( root_lock ) ;
RCU_INIT_POINTER ( tp - > next , rtnl_dereference ( * back ) ) ;
rcu_assign_pointer ( * back , tp ) ;
}
tfilter_notify ( net , skb , n , tp , fh , RTM_NEWTFILTER ) ;
} else {
@ -420,7 +419,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
int s_t ;
struct net_device * dev ;
struct Qdisc * q ;
struct tcf_proto * tp , * * chain ;
struct tcf_proto * tp , __rcu * * chain ;
struct tcmsg * tcm = nlmsg_data ( cb - > nlh ) ;
unsigned long cl = 0 ;
const struct Qdisc_class_ops * cops ;
@ -454,7 +453,8 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
s_t = cb - > args [ 0 ] ;
for ( tp = * chain , t = 0 ; tp ; tp = tp - > next , t + + ) {
for ( tp = rtnl_dereference ( * chain ) , t = 0 ;
tp ; tp = rtnl_dereference ( tp - > next ) , t + + ) {
if ( t < s_t )
continue ;
if ( TC_H_MAJ ( tcm - > tcm_info ) & &