Skip to content

Commit a90f6dc

Browse files
dcarattikuba-moo
authored andcommitted
net/sched: don't use dynamic lockdep keys with clsact/ingress/noqueue
Currently we are registering one dynamic lockdep key for each allocated qdisc, to avoid false deadlock reports when mirred (or TC eBPF) redirects packets to another device while the root lock is acquired [1]. Since dynamic keys are a limited resource, we can save them at least for qdiscs that are not meant to acquire the root lock in the traffic path, or to carry traffic at all, like: - clsact - ingress - noqueue Don't register dynamic keys for the above schedulers, so that we hit MAX_LOCKDEP_KEYS later in our tests. [1] multipath-tcp/mptcp_net-next#451 Changes in v2: - change ordering of spin_lock_init() vs. lockdep_register_key() (Jakub Kicinski) Signed-off-by: Davide Caratti <dcaratti@redhat.com> Link: https://patch.msgid.link/94448f7fa7c4f52d2ce416a4895ec87d456d7417.1770220576.git.dcaratti@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 7e7fcfb commit a90f6dc

3 files changed

Lines changed: 28 additions & 6 deletions

File tree

include/net/pkt_sched.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,4 +308,28 @@ static inline unsigned int qdisc_peek_len(struct Qdisc *sch)
308308
return len;
309309
}
310310

311+
static inline void qdisc_lock_init(struct Qdisc *sch,
312+
const struct Qdisc_ops *ops)
313+
{
314+
spin_lock_init(&sch->q.lock);
315+
316+
/* Skip dynamic keys if nesting is not possible */
317+
if (ops->static_flags & TCQ_F_INGRESS ||
318+
ops == &noqueue_qdisc_ops)
319+
return;
320+
321+
lockdep_register_key(&sch->root_lock_key);
322+
lockdep_set_class(&sch->q.lock, &sch->root_lock_key);
323+
}
324+
325+
static inline void qdisc_lock_uninit(struct Qdisc *sch,
326+
const struct Qdisc_ops *ops)
327+
{
328+
if (ops->static_flags & TCQ_F_INGRESS ||
329+
ops == &noqueue_qdisc_ops)
330+
return;
331+
332+
lockdep_unregister_key(&sch->root_lock_key);
333+
}
334+
311335
#endif

net/sched/sch_api.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1353,7 +1353,7 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
13531353
ops->destroy(sch);
13541354
qdisc_put_stab(rtnl_dereference(sch->stab));
13551355
err_out3:
1356-
lockdep_unregister_key(&sch->root_lock_key);
1356+
qdisc_lock_uninit(sch, ops);
13571357
netdev_put(dev, &sch->dev_tracker);
13581358
qdisc_free(sch);
13591359
err_out2:

net/sched/sch_generic.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -955,9 +955,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
955955
__skb_queue_head_init(&sch->gso_skb);
956956
__skb_queue_head_init(&sch->skb_bad_txq);
957957
gnet_stats_basic_sync_init(&sch->bstats);
958-
lockdep_register_key(&sch->root_lock_key);
959-
spin_lock_init(&sch->q.lock);
960-
lockdep_set_class(&sch->q.lock, &sch->root_lock_key);
958+
qdisc_lock_init(sch, ops);
961959

962960
if (ops->static_flags & TCQ_F_CPUSTATS) {
963961
sch->cpu_bstats =
@@ -987,7 +985,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
987985

988986
return sch;
989987
errout1:
990-
lockdep_unregister_key(&sch->root_lock_key);
988+
qdisc_lock_uninit(sch, ops);
991989
kfree(sch);
992990
errout:
993991
return ERR_PTR(err);
@@ -1076,7 +1074,7 @@ static void __qdisc_destroy(struct Qdisc *qdisc)
10761074
if (ops->destroy)
10771075
ops->destroy(qdisc);
10781076

1079-
lockdep_unregister_key(&qdisc->root_lock_key);
1077+
qdisc_lock_uninit(qdisc, ops);
10801078
bpf_module_put(ops, ops->owner);
10811079
netdev_put(dev, &qdisc->dev_tracker);
10821080

0 commit comments

Comments
 (0)