Skip to content

Commit c9a82be

Browse files
w1ldptrkuba-moo
authored andcommitted
net/sched: cls_api: Fix lockup on flushing explicitly created chain
Mingshuai Ren reports: When a new chain is added by using tc, one soft lockup alarm will be generated after delete the prio 0 filter of the chain. To reproduce the problem, perform the following steps: (1) tc qdisc add dev eth0 root handle 1: htb default 1 (2) tc chain add dev eth0 (3) tc filter del dev eth0 chain 0 parent 1: prio 0 (4) tc filter add dev eth0 chain 0 parent 1: Fix the issue by accounting for additional reference to chains that are explicitly created by RTM_NEWCHAIN message as opposed to implicitly by RTM_NEWTFILTER message. Fixes: 726d061 ("net: sched: prevent insertion of new classifiers during chain flush") Reported-by: Mingshuai Ren <renmingshuai@huawei.com> Closes: https://lore.kernel.org/lkml/87legswvi3.fsf@nvidia.com/T/ Signed-off-by: Vlad Buslov <vladbu@nvidia.com> Link: https://lore.kernel.org/r/20230612093426.2867183-1-vladbu@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 24b454b commit c9a82be

1 file changed

Lines changed: 7 additions & 5 deletions

File tree

net/sched/cls_api.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -657,8 +657,8 @@ static void __tcf_chain_put(struct tcf_chain *chain, bool by_act,
657657
{
658658
struct tcf_block *block = chain->block;
659659
const struct tcf_proto_ops *tmplt_ops;
660+
unsigned int refcnt, non_act_refcnt;
660661
bool free_block = false;
661-
unsigned int refcnt;
662662
void *tmplt_priv;
663663

664664
mutex_lock(&block->lock);
@@ -678,13 +678,15 @@ static void __tcf_chain_put(struct tcf_chain *chain, bool by_act,
678678
* save these to temporary variables.
679679
*/
680680
refcnt = --chain->refcnt;
681+
non_act_refcnt = refcnt - chain->action_refcnt;
681682
tmplt_ops = chain->tmplt_ops;
682683
tmplt_priv = chain->tmplt_priv;
683684

684-
/* The last dropped non-action reference will trigger notification. */
685-
if (refcnt - chain->action_refcnt == 0 && !by_act) {
686-
tc_chain_notify_delete(tmplt_ops, tmplt_priv, chain->index,
687-
block, NULL, 0, 0, false);
685+
if (non_act_refcnt == chain->explicitly_created && !by_act) {
686+
if (non_act_refcnt == 0)
687+
tc_chain_notify_delete(tmplt_ops, tmplt_priv,
688+
chain->index, block, NULL, 0, 0,
689+
false);
688690
/* Last reference to chain, no need to lock. */
689691
chain->flushing = false;
690692
}

0 commit comments

Comments
 (0)