Skip to content

Commit 52e3eeb

Browse files
Binary-Eatergregkh
authored andcommitted
sch_htb: Avoid grafting on htb_destroy_class_offload when destroying htb
[ Upstream commit a22b738 ] Peek at old qdisc and graft only when deleting a leaf class in the htb, rather than when deleting the htb itself. Do not peek at the qdisc of the netdev queue when destroying the htb. The caller may already have grafted a new qdisc that is not part of the htb structure being destroyed. This fix resolves two use cases. 1. Using tc to destroy the htb. - Netdev was being prematurely activated before the htb was fully destroyed. 2. Using tc to replace the htb with another qdisc (which also leads to the htb being destroyed). - Premature netdev activation like previous case. Newly grafted qdisc was also getting accidentally overwritten when destroying the htb. Fixes: d03b195 ("sch_htb: Hierarchical QoS hardware offload") Signed-off-by: Rahul Rameshbabu <[email protected]> Reviewed-by: Saeed Mahameed <[email protected]> Reviewed-by: Maxim Mikityanskiy <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 8232e5a commit 52e3eeb

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

net/sched/sch_htb.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,22 +1558,25 @@ static int htb_destroy_class_offload(struct Qdisc *sch, struct htb_class *cl,
15581558
struct tc_htb_qopt_offload offload_opt;
15591559
struct netdev_queue *dev_queue;
15601560
struct Qdisc *q = cl->leaf.q;
1561-
struct Qdisc *old = NULL;
1561+
struct Qdisc *old;
15621562
int err;
15631563

15641564
if (cl->level)
15651565
return -EINVAL;
15661566

15671567
WARN_ON(!q);
15681568
dev_queue = htb_offload_get_queue(cl);
1569-
old = htb_graft_helper(dev_queue, NULL);
1570-
if (destroying)
1571-
/* Before HTB is destroyed, the kernel grafts noop_qdisc to
1572-
* all queues.
1569+
/* When destroying, caller qdisc_graft grafts the new qdisc and invokes
1570+
* qdisc_put for the qdisc being destroyed. htb_destroy_class_offload
1571+
* does not need to graft or qdisc_put the qdisc being destroyed.
1572+
*/
1573+
if (!destroying) {
1574+
old = htb_graft_helper(dev_queue, NULL);
1575+
/* Last qdisc grafted should be the same as cl->leaf.q when
1576+
* calling htb_delete.
15731577
*/
1574-
WARN_ON(!(old->flags & TCQ_F_BUILTIN));
1575-
else
15761578
WARN_ON(old != q);
1579+
}
15771580

15781581
if (cl->parent) {
15791582
cl->parent->bstats_bias.bytes += q->bstats.bytes;
@@ -1589,10 +1592,12 @@ static int htb_destroy_class_offload(struct Qdisc *sch, struct htb_class *cl,
15891592
};
15901593
err = htb_offload(qdisc_dev(sch), &offload_opt);
15911594

1592-
if (!err || destroying)
1593-
qdisc_put(old);
1594-
else
1595-
htb_graft_helper(dev_queue, old);
1595+
if (!destroying) {
1596+
if (!err)
1597+
qdisc_put(old);
1598+
else
1599+
htb_graft_helper(dev_queue, old);
1600+
}
15961601

15971602
if (last_child)
15981603
return err;

0 commit comments

Comments
 (0)