Skip to content

Commit f9eb8ae

Browse files
edumazetdavem330
authored andcommitted
net_sched: transform qdisc running bit into a seqcount
Instead of using a single bit (__QDISC___STATE_RUNNING) in sch->__state, use a seqcount. This adds lockdep support, but more importantly it will allow us to sample qdisc/class statistics without having to grab qdisc root lock. Signed-off-by: Eric Dumazet <[email protected]> Cc: Cong Wang <[email protected]> Cc: Jamal Hadi Salim <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 64151ae commit f9eb8ae

File tree

10 files changed

+32
-16
lines changed

10 files changed

+32
-16
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4610,6 +4610,7 @@ static int bond_check_params(struct bond_params *params)
46104610
static struct lock_class_key bonding_netdev_xmit_lock_key;
46114611
static struct lock_class_key bonding_netdev_addr_lock_key;
46124612
static struct lock_class_key bonding_tx_busylock_key;
4613+
static struct lock_class_key bonding_qdisc_running_key;
46134614

46144615
static void bond_set_lockdep_class_one(struct net_device *dev,
46154616
struct netdev_queue *txq,
@@ -4625,6 +4626,7 @@ static void bond_set_lockdep_class(struct net_device *dev)
46254626
&bonding_netdev_addr_lock_key);
46264627
netdev_for_each_tx_queue(dev, bond_set_lockdep_class_one, NULL);
46274628
dev->qdisc_tx_busylock = &bonding_tx_busylock_key;
4629+
dev->qdisc_running_key = &bonding_qdisc_running_key;
46284630
}
46294631

46304632
/* Called from registration process */

drivers/net/ppp/ppp_generic.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,9 +1313,12 @@ ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64)
13131313
}
13141314

13151315
static struct lock_class_key ppp_tx_busylock;
1316+
static struct lock_class_key ppp_qdisc_running_key;
1317+
13161318
static int ppp_dev_init(struct net_device *dev)
13171319
{
13181320
dev->qdisc_tx_busylock = &ppp_tx_busylock;
1321+
dev->qdisc_running_key = &ppp_qdisc_running_key;
13191322
return 0;
13201323
}
13211324

drivers/net/team/team.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,6 +1577,7 @@ static const struct team_option team_options[] = {
15771577
static struct lock_class_key team_netdev_xmit_lock_key;
15781578
static struct lock_class_key team_netdev_addr_lock_key;
15791579
static struct lock_class_key team_tx_busylock_key;
1580+
static struct lock_class_key team_qdisc_running_key;
15801581

15811582
static void team_set_lockdep_class_one(struct net_device *dev,
15821583
struct netdev_queue *txq,
@@ -1590,6 +1591,7 @@ static void team_set_lockdep_class(struct net_device *dev)
15901591
lockdep_set_class(&dev->addr_list_lock, &team_netdev_addr_lock_key);
15911592
netdev_for_each_tx_queue(dev, team_set_lockdep_class_one, NULL);
15921593
dev->qdisc_tx_busylock = &team_tx_busylock_key;
1594+
dev->qdisc_running_key = &team_qdisc_running_key;
15931595
}
15941596

15951597
static int team_init(struct net_device *dev)

include/linux/netdevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,7 @@ struct net_device {
18621862
#endif
18631863
struct phy_device *phydev;
18641864
struct lock_class_key *qdisc_tx_busylock;
1865+
struct lock_class_key *qdisc_running_key;
18651866
bool proto_down;
18661867
};
18671868
#define to_net_dev(d) container_of(d, struct net_device, dev)

include/net/sch_generic.h

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,6 @@ enum qdisc_state_t {
2929
__QDISC_STATE_THROTTLED,
3030
};
3131

32-
/*
33-
* following bits are only changed while qdisc lock is held
34-
*/
35-
enum qdisc___state_t {
36-
__QDISC___STATE_RUNNING = 1,
37-
};
38-
3932
struct qdisc_size_table {
4033
struct rcu_head rcu;
4134
struct list_head list;
@@ -93,7 +86,7 @@ struct Qdisc {
9386
unsigned long state;
9487
struct sk_buff_head q;
9588
struct gnet_stats_basic_packed bstats;
96-
unsigned int __state;
89+
seqcount_t running;
9790
struct gnet_stats_queue qstats;
9891
struct rcu_head rcu_head;
9992
int padded;
@@ -104,20 +97,20 @@ struct Qdisc {
10497

10598
static inline bool qdisc_is_running(const struct Qdisc *qdisc)
10699
{
107-
return (qdisc->__state & __QDISC___STATE_RUNNING) ? true : false;
100+
return (raw_read_seqcount(&qdisc->running) & 1) ? true : false;
108101
}
109102

110103
static inline bool qdisc_run_begin(struct Qdisc *qdisc)
111104
{
112105
if (qdisc_is_running(qdisc))
113106
return false;
114-
qdisc->__state |= __QDISC___STATE_RUNNING;
107+
write_seqcount_begin(&qdisc->running);
115108
return true;
116109
}
117110

118111
static inline void qdisc_run_end(struct Qdisc *qdisc)
119112
{
120-
qdisc->__state &= ~__QDISC___STATE_RUNNING;
113+
write_seqcount_end(&qdisc->running);
121114
}
122115

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

net/bluetooth/6lowpan.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
629629

630630
static struct lock_class_key bt_tx_busylock;
631631
static struct lock_class_key bt_netdev_xmit_lock_key;
632+
static struct lock_class_key bt_qdisc_running_key;
632633

633634
static void bt_set_lockdep_class_one(struct net_device *dev,
634635
struct netdev_queue *txq,
@@ -641,6 +642,7 @@ static int bt_dev_init(struct net_device *dev)
641642
{
642643
netdev_for_each_tx_queue(dev, bt_set_lockdep_class_one, NULL);
643644
dev->qdisc_tx_busylock = &bt_tx_busylock;
645+
dev->qdisc_running_key = &bt_qdisc_running_key;
644646

645647
return 0;
646648
}

net/core/dev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3075,7 +3075,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
30753075
/*
30763076
* Heuristic to force contended enqueues to serialize on a
30773077
* separate lock before trying to get qdisc main lock.
3078-
* This permits __QDISC___STATE_RUNNING owner to get the lock more
3078+
* This permits qdisc->running owner to get the lock more
30793079
* often and dequeue packets faster.
30803080
*/
30813081
contended = qdisc_is_running(q);

net/ieee802154/6lowpan/core.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ static struct header_ops lowpan_header_ops = {
6060

6161
static struct lock_class_key lowpan_tx_busylock;
6262
static struct lock_class_key lowpan_netdev_xmit_lock_key;
63+
static struct lock_class_key lowpan_qdisc_running_key;
6364

6465
static void lowpan_set_lockdep_class_one(struct net_device *ldev,
6566
struct netdev_queue *txq,
@@ -73,6 +74,8 @@ static int lowpan_dev_init(struct net_device *ldev)
7374
{
7475
netdev_for_each_tx_queue(ldev, lowpan_set_lockdep_class_one, NULL);
7576
ldev->qdisc_tx_busylock = &lowpan_tx_busylock;
77+
ldev->qdisc_running_key = &lowpan_qdisc_running_key;
78+
7679
return 0;
7780
}
7881

net/l2tp/l2tp_eth.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ static inline struct l2tp_eth_net *l2tp_eth_pernet(struct net *net)
6868
}
6969

7070
static struct lock_class_key l2tp_eth_tx_busylock;
71+
static struct lock_class_key l2tp_qdisc_running_key;
72+
7173
static int l2tp_eth_dev_init(struct net_device *dev)
7274
{
7375
struct l2tp_eth *priv = netdev_priv(dev);
@@ -76,6 +78,8 @@ static int l2tp_eth_dev_init(struct net_device *dev)
7678
eth_hw_addr_random(dev);
7779
eth_broadcast_addr(dev->broadcast);
7880
dev->qdisc_tx_busylock = &l2tp_eth_tx_busylock;
81+
dev->qdisc_running_key = &l2tp_qdisc_running_key;
82+
7983
return 0;
8084
}
8185

net/sched/sch_generic.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate,
110110

111111
/*
112112
* Transmit possibly several skbs, and handle the return status as
113-
* required. Holding the __QDISC___STATE_RUNNING bit guarantees that
113+
* required. Owning running seqcount bit guarantees that
114114
* only one CPU can execute this function.
115115
*
116116
* Returns to the caller:
@@ -137,10 +137,10 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
137137

138138
HARD_TX_UNLOCK(dev, txq);
139139
} else {
140-
spin_lock(root_lock);
140+
spin_lock_nested(root_lock, SINGLE_DEPTH_NESTING);
141141
return qdisc_qlen(q);
142142
}
143-
spin_lock(root_lock);
143+
spin_lock_nested(root_lock, SINGLE_DEPTH_NESTING);
144144

145145
if (dev_xmit_complete(ret)) {
146146
/* Driver sent out skb successfully or skb was consumed */
@@ -163,7 +163,7 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
163163
/*
164164
* NOTE: Called under qdisc_lock(q) with locally disabled BH.
165165
*
166-
* __QDISC___STATE_RUNNING guarantees only one CPU can process
166+
* running seqcount guarantees only one CPU can process
167167
* this qdisc at a time. qdisc_lock(q) serializes queue accesses for
168168
* this queue.
169169
*
@@ -379,6 +379,7 @@ struct Qdisc noop_qdisc = {
379379
.list = LIST_HEAD_INIT(noop_qdisc.list),
380380
.q.lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.q.lock),
381381
.dev_queue = &noop_netdev_queue,
382+
.running = SEQCNT_ZERO(noop_qdisc.running),
382383
.busylock = __SPIN_LOCK_UNLOCKED(noop_qdisc.busylock),
383384
};
384385
EXPORT_SYMBOL(noop_qdisc);
@@ -537,6 +538,7 @@ struct Qdisc_ops pfifo_fast_ops __read_mostly = {
537538
EXPORT_SYMBOL(pfifo_fast_ops);
538539

539540
static struct lock_class_key qdisc_tx_busylock;
541+
static struct lock_class_key qdisc_running_key;
540542

541543
struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
542544
const struct Qdisc_ops *ops)
@@ -570,6 +572,10 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
570572
lockdep_set_class(&sch->busylock,
571573
dev->qdisc_tx_busylock ?: &qdisc_tx_busylock);
572574

575+
seqcount_init(&sch->running);
576+
lockdep_set_class(&sch->running,
577+
dev->qdisc_running_key ?: &qdisc_running_key);
578+
573579
sch->ops = ops;
574580
sch->enqueue = ops->enqueue;
575581
sch->dequeue = ops->dequeue;

0 commit comments

Comments
 (0)