Skip to content

Commit

Permalink
net: sched: Add multi-queue support to sch_tree_lock
Browse files Browse the repository at this point in the history
The existing qdiscs that set TCQ_F_MQROOT don't use sch_tree_lock.
However, hardware-offloaded HTB will start setting this flag while also
using sch_tree_lock.

The current implementation of sch_tree_lock basically locks on
qdisc->dev_queue->qdisc, and it works fine when the tree is attached to
some queue. However, it's not the case for MQROOT qdiscs: such a qdisc
is the root itself, and its dev_queue just points to queue 0, while not
actually being used, because there are real per-queue qdiscs.

This patch changes the logic of sch_tree_lock and sch_tree_unlock to
lock the qdisc itself if it's the MQROOT.

Signed-off-by: Maxim Mikityanskiy <maximmi@mellanox.com>
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Maxim Mikityanskiy authored and Jakub Kicinski committed Jan 23, 2021
1 parent 04a8863 commit ca1e4ab
Showing 1 changed file with 10 additions and 4 deletions.
14 changes: 10 additions & 4 deletions include/net/sch_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -552,14 +552,20 @@ static inline struct net_device *qdisc_dev(const struct Qdisc *qdisc)
return qdisc->dev_queue->dev;
}

static inline void sch_tree_lock(const struct Qdisc *q)
static inline void sch_tree_lock(struct Qdisc *q)
{
spin_lock_bh(qdisc_root_sleeping_lock(q));
if (q->flags & TCQ_F_MQROOT)
spin_lock_bh(qdisc_lock(q));
else
spin_lock_bh(qdisc_root_sleeping_lock(q));
}

static inline void sch_tree_unlock(const struct Qdisc *q)
static inline void sch_tree_unlock(struct Qdisc *q)
{
spin_unlock_bh(qdisc_root_sleeping_lock(q));
if (q->flags & TCQ_F_MQROOT)
spin_unlock_bh(qdisc_lock(q));
else
spin_unlock_bh(qdisc_root_sleeping_lock(q));
}

extern struct Qdisc noop_qdisc;
Expand Down

0 comments on commit ca1e4ab

Please sign in to comment.