diff options
author | Paolo Abeni <pabeni@redhat.com> | 2018-05-15 16:24:36 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-05-17 12:46:54 -0400 |
commit | 96009c7d500efdd5534e83b2e3eb2c58d4b137ae (patch) | |
tree | 7df2aef0eaf670f4991c731a9c38ba73ac9031d7 /net/sched | |
parent | b9f672af148bf7a08a6031743156faffd58dbc7e (diff) | |
download | linux-96009c7d500efdd5534e83b2e3eb2c58d4b137ae.tar.bz2 |
sched: replace __QDISC_STATE_RUNNING bit with a spin lock
So that we can use lockdep on it.
The newly introduced sequence lock has the same scope of busylock,
so it shares the same lockdep annotation, but it's only used for
NOLOCK qdiscs.
With this changeset we acquire such lock in the control path around
flushing operation (qdisc reset), to allow more NOLOCK qdisc perf
improvement in the next patch.
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/sch_generic.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index ff3ce71aec93..a126f16bc30b 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -858,6 +858,11 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, lockdep_set_class(&sch->busylock, dev->qdisc_tx_busylock ?: &qdisc_tx_busylock); + /* seqlock has the same scope of busylock, for NOLOCK qdisc */ + spin_lock_init(&sch->seqlock); + lockdep_set_class(&sch->busylock, + dev->qdisc_tx_busylock ?: &qdisc_tx_busylock); + seqcount_init(&sch->running); lockdep_set_class(&sch->running, dev->qdisc_running_key ?: &qdisc_running_key); @@ -1097,6 +1102,10 @@ 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)) @@ -1106,6 +1115,8 @@ static void dev_deactivate_queue(struct net_device *dev, qdisc_reset(qdisc); spin_unlock_bh(qdisc_lock(qdisc)); + if (nolock) + spin_unlock_bh(&qdisc->seqlock); } } |