Skip to content

Commit 96009c7

Browse files
Paolo Abenidavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b9f672a commit 96009c7

File tree

2 files changed

+16
-5
lines changed

2 files changed

+16
-5
lines changed

include/net/sch_generic.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ struct qdisc_rate_table {
3030
enum qdisc_state_t {
3131
__QDISC_STATE_SCHED,
3232
__QDISC_STATE_DEACTIVATED,
33-
__QDISC_STATE_RUNNING,
3433
};
3534

3635
struct qdisc_size_table {
@@ -102,6 +101,7 @@ struct Qdisc {
102101
refcount_t refcnt;
103102

104103
spinlock_t busylock ____cacheline_aligned_in_smp;
104+
spinlock_t seqlock;
105105
};
106106

107107
static inline void qdisc_refcount_inc(struct Qdisc *qdisc)
@@ -111,17 +111,17 @@ static inline void qdisc_refcount_inc(struct Qdisc *qdisc)
111111
refcount_inc(&qdisc->refcnt);
112112
}
113113

114-
static inline bool qdisc_is_running(const struct Qdisc *qdisc)
114+
static inline bool qdisc_is_running(struct Qdisc *qdisc)
115115
{
116116
if (qdisc->flags & TCQ_F_NOLOCK)
117-
return test_bit(__QDISC_STATE_RUNNING, &qdisc->state);
117+
return spin_is_locked(&qdisc->seqlock);
118118
return (raw_read_seqcount(&qdisc->running) & 1) ? true : false;
119119
}
120120

121121
static inline bool qdisc_run_begin(struct Qdisc *qdisc)
122122
{
123123
if (qdisc->flags & TCQ_F_NOLOCK) {
124-
if (test_and_set_bit(__QDISC_STATE_RUNNING, &qdisc->state))
124+
if (!spin_trylock(&qdisc->seqlock))
125125
return false;
126126
} else if (qdisc_is_running(qdisc)) {
127127
return false;
@@ -138,7 +138,7 @@ static inline void qdisc_run_end(struct Qdisc *qdisc)
138138
{
139139
write_seqcount_end(&qdisc->running);
140140
if (qdisc->flags & TCQ_F_NOLOCK)
141-
clear_bit(__QDISC_STATE_RUNNING, &qdisc->state);
141+
spin_unlock(&qdisc->seqlock);
142142
}
143143

144144
static inline bool qdisc_may_bulk(const struct Qdisc *qdisc)

net/sched/sch_generic.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,11 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
858858
lockdep_set_class(&sch->busylock,
859859
dev->qdisc_tx_busylock ?: &qdisc_tx_busylock);
860860

861+
/* seqlock has the same scope of busylock, for NOLOCK qdisc */
862+
spin_lock_init(&sch->seqlock);
863+
lockdep_set_class(&sch->busylock,
864+
dev->qdisc_tx_busylock ?: &qdisc_tx_busylock);
865+
861866
seqcount_init(&sch->running);
862867
lockdep_set_class(&sch->running,
863868
dev->qdisc_running_key ?: &qdisc_running_key);
@@ -1097,6 +1102,10 @@ static void dev_deactivate_queue(struct net_device *dev,
10971102

10981103
qdisc = rtnl_dereference(dev_queue->qdisc);
10991104
if (qdisc) {
1105+
bool nolock = qdisc->flags & TCQ_F_NOLOCK;
1106+
1107+
if (nolock)
1108+
spin_lock_bh(&qdisc->seqlock);
11001109
spin_lock_bh(qdisc_lock(qdisc));
11011110

11021111
if (!(qdisc->flags & TCQ_F_BUILTIN))
@@ -1106,6 +1115,8 @@ static void dev_deactivate_queue(struct net_device *dev,
11061115
qdisc_reset(qdisc);
11071116

11081117
spin_unlock_bh(qdisc_lock(qdisc));
1118+
if (nolock)
1119+
spin_unlock_bh(&qdisc->seqlock);
11091120
}
11101121
}
11111122

0 commit comments

Comments
 (0)