Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: sched: tbf: don't call qdisc_put() while holding tree lock

The issue is the same to commit c2999f7fb05b ("net: sched: multiq: don't
call qdisc_put() while holding tree lock"). Qdiscs call qdisc_put() while
holding sch tree spinlock, which results sleeping-while-atomic BUG.

Fixes: c266f64dbfa2 ("net: sched: protect block state with mutex")
Signed-off-by: Zhengchao Shao <shaozhengchao@huawei.com>
Link: https://lore.kernel.org/r/20220826013930.340121-1-shaozhengchao@huawei.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Zhengchao Shao and committed by
Paolo Abeni
b05972f0 cb10b0f9

+3 -1
+3 -1
net/sched/sch_tbf.c
··· 356 356 struct nlattr *tb[TCA_TBF_MAX + 1]; 357 357 struct tc_tbf_qopt *qopt; 358 358 struct Qdisc *child = NULL; 359 + struct Qdisc *old = NULL; 359 360 struct psched_ratecfg rate; 360 361 struct psched_ratecfg peak; 361 362 u64 max_size; ··· 448 447 sch_tree_lock(sch); 449 448 if (child) { 450 449 qdisc_tree_flush_backlog(q->qdisc); 451 - qdisc_put(q->qdisc); 450 + old = q->qdisc; 452 451 q->qdisc = child; 453 452 } 454 453 q->limit = qopt->limit; ··· 468 467 memcpy(&q->peak, &peak, sizeof(struct psched_ratecfg)); 469 468 470 469 sch_tree_unlock(sch); 470 + qdisc_put(old); 471 471 err = 0; 472 472 473 473 tbf_offload_change(sch);