Skip to content

Commit 70f5096

Browse files
congwangdavem330
authored andcommitted
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 <[email protected]> Tested-by: Václav Zindulka <[email protected]> Cc: Jamal Hadi Salim <[email protected]> Cc: Jiri Pirko <[email protected]> Signed-off-by: Cong Wang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f5a7833 commit 70f5096

File tree

1 file changed

+23
-14
lines changed

1 file changed

+23
-14
lines changed

net/sched/sch_generic.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,28 @@ void dev_activate(struct net_device *dev)
11281128
}
11291129
EXPORT_SYMBOL(dev_activate);
11301130

1131+
static void qdisc_deactivate(struct Qdisc *qdisc)
1132+
{
1133+
bool nolock = qdisc->flags & TCQ_F_NOLOCK;
1134+
1135+
if (qdisc->flags & TCQ_F_BUILTIN)
1136+
return;
1137+
if (test_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state))
1138+
return;
1139+
1140+
if (nolock)
1141+
spin_lock_bh(&qdisc->seqlock);
1142+
spin_lock_bh(qdisc_lock(qdisc));
1143+
1144+
set_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state);
1145+
1146+
qdisc_reset(qdisc);
1147+
1148+
spin_unlock_bh(qdisc_lock(qdisc));
1149+
if (nolock)
1150+
spin_unlock_bh(&qdisc->seqlock);
1151+
}
1152+
11311153
static void dev_deactivate_queue(struct net_device *dev,
11321154
struct netdev_queue *dev_queue,
11331155
void *_qdisc_default)
@@ -1137,21 +1159,8 @@ static void dev_deactivate_queue(struct net_device *dev,
11371159

11381160
qdisc = rtnl_dereference(dev_queue->qdisc);
11391161
if (qdisc) {
1140-
bool nolock = qdisc->flags & TCQ_F_NOLOCK;
1141-
1142-
if (nolock)
1143-
spin_lock_bh(&qdisc->seqlock);
1144-
spin_lock_bh(qdisc_lock(qdisc));
1145-
1146-
if (!(qdisc->flags & TCQ_F_BUILTIN))
1147-
set_bit(__QDISC_STATE_DEACTIVATED, &qdisc->state);
1148-
1162+
qdisc_deactivate(qdisc);
11491163
rcu_assign_pointer(dev_queue->qdisc, qdisc_default);
1150-
qdisc_reset(qdisc);
1151-
1152-
spin_unlock_bh(qdisc_lock(qdisc));
1153-
if (nolock)
1154-
spin_unlock_bh(&qdisc->seqlock);
11551164
}
11561165
}
11571166

0 commit comments

Comments
 (0)