mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 10:04:12 +08:00
net_sched: avoid resetting active qdisc for multiple times
Except for sch_mq and sch_mqprio, each dev queue points to the same root qdisc, so when we reset the dev queues with netdev_for_each_tx_queue() we end up resetting the same instance of the root qdisc for multiple times. Avoid this by checking the __QDISC_STATE_DEACTIVATED bit in each iteration, so for sch_mq/sch_mqprio, we still reset all of them like before, for the rest, we only reset it once. Reported-by: Václav Zindulka <vaclav.zindulka@tlapnet.cz> Tested-by: Václav Zindulka <vaclav.zindulka@tlapnet.cz> Cc: Jamal Hadi Salim <jhs@mojatatu.com> Cc: Jiri Pirko <jiri@resnulli.us> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f5a7833e83
commit
70f5096533
@ -1128,6 +1128,28 @@ void dev_activate(struct net_device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(dev_activate);
|
||||
|
||||
static void qdisc_deactivate(struct Qdisc *qdisc)
|
||||
{
|
||||
bool nolock = qdisc->flags & TCQ_F_NOLOCK;
|
||||
|
||||
if (qdisc->flags & TCQ_F_BUILTIN)
|
||||
return;
|
||||
if (test_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state))
|
||||
return;
|
||||
|
||||
if (nolock)
|
||||
spin_lock_bh(&qdisc->seqlock);
|
||||
spin_lock_bh(qdisc_lock(qdisc));
|
||||
|
||||
set_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state);
|
||||
|
||||
qdisc_reset(qdisc);
|
||||
|
||||
spin_unlock_bh(qdisc_lock(qdisc));
|
||||
if (nolock)
|
||||
spin_unlock_bh(&qdisc->seqlock);
|
||||
}
|
||||
|
||||
static void dev_deactivate_queue(struct net_device *dev,
|
||||
struct netdev_queue *dev_queue,
|
||||
void *_qdisc_default)
|
||||
@ -1137,21 +1159,8 @@ static void dev_deactivate_queue(struct net_device *dev,
|
||||
|
||||
qdisc = rtnl_dereference(dev_queue->qdisc);
|
||||
if (qdisc) {
|
||||
bool nolock = qdisc->flags & TCQ_F_NOLOCK;
|
||||
|
||||
if (nolock)
|
||||
spin_lock_bh(&qdisc->seqlock);
|
||||
spin_lock_bh(qdisc_lock(qdisc));
|
||||
|
||||
if (!(qdisc->flags & TCQ_F_BUILTIN))
|
||||
set_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state);
|
||||
|
||||
qdisc_deactivate(qdisc);
|
||||
rcu_assign_pointer(dev_queue->qdisc, qdisc_default);
|
||||
qdisc_reset(qdisc);
|
||||
|
||||
spin_unlock_bh(qdisc_lock(qdisc));
|
||||
if (nolock)
|
||||
spin_unlock_bh(&qdisc->seqlock);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user