diff options
Diffstat (limited to 'net/sched/cls_api.c')
| -rw-r--r-- | net/sched/cls_api.c | 20 | 
1 files changed, 13 insertions, 7 deletions
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 9360fc81e8c..d2b6f54a626 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -120,6 +120,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)  {  	struct net *net = sock_net(skb->sk);  	struct nlattr *tca[TCA_MAX + 1]; +	spinlock_t *root_lock;  	struct tcmsg *t;  	u32 protocol;  	u32 prio; @@ -166,7 +167,8 @@ replay:  	/* Find qdisc */  	if (!parent) { -		q = dev->qdisc_sleeping; +		struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, 0); +		q = dev_queue->qdisc_sleeping;  		parent = q->handle;  	} else {  		q = qdisc_lookup(dev, TC_H_MAJ(t->tcm_parent)); @@ -203,6 +205,8 @@ replay:  		}  	} +	root_lock = qdisc_root_lock(q); +  	if (tp == NULL) {  		/* Proto-tcf does not exist, create new one */ @@ -262,10 +266,10 @@ replay:  			goto errout;  		} -		qdisc_lock_tree(dev); +		spin_lock_bh(root_lock);  		tp->next = *back;  		*back = tp; -		qdisc_unlock_tree(dev); +		spin_unlock_bh(root_lock);  	} else if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], tp->ops->kind))  		goto errout; @@ -274,9 +278,9 @@ replay:  	if (fh == 0) {  		if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) { -			qdisc_lock_tree(dev); +			spin_lock_bh(root_lock);  			*back = tp->next; -			qdisc_unlock_tree(dev); +			spin_lock_bh(root_lock);  			tfilter_notify(skb, n, tp, fh, RTM_DELTFILTER);  			tcf_destroy(tp); @@ -334,7 +338,7 @@ static int tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp,  	tcm->tcm_family = AF_UNSPEC;  	tcm->tcm__pad1 = 0;  	tcm->tcm__pad1 = 0; -	tcm->tcm_ifindex = tp->q->dev->ifindex; +	tcm->tcm_ifindex = qdisc_dev(tp->q)->ifindex;  	tcm->tcm_parent = tp->classid;  	tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);  	NLA_PUT_STRING(skb, TCA_KIND, tp->ops->kind); @@ -390,6 +394,7 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n,  static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)  {  	struct net *net = sock_net(skb->sk); +	struct netdev_queue *dev_queue;  	int t;  	int s_t;  	struct net_device *dev; @@ -408,8 +413,9 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)  	if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL)  		return skb->len; +	dev_queue = netdev_get_tx_queue(dev, 0);  	if (!tcm->tcm_parent) -		q = dev->qdisc_sleeping; +		q = dev_queue->qdisc_sleeping;  	else  		q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent));  	if (!q)  |