]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
sch_ets: make est_qlen_notify() idempotent
authorCong Wang <xiyou.wangcong@gmail.com>
Thu, 3 Apr 2025 21:10:27 +0000 (14:10 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2025 10:04:10 +0000 (11:04 +0100)
[ Upstream commit a7a15f39c682ac4268624da2abdb9114bdde96d5 ]

est_qlen_notify() deletes its class from its active list with
list_del() when qlen is 0, therefore, it is not idempotent and
not friendly to its callers, like fq_codel_dequeue().

Let's make it idempotent to ease qdisc_tree_reduce_backlog() callers'
life. Also change other list_del()'s to list_del_init() just to be
extra safe.

Reported-by: Gerrard Tai <gerrard.tai@starlabs.sg>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Link: https://patch.msgid.link/20250403211033.166059-6-xiyou.wangcong@gmail.com
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Stable-dep-of: d92adacdd8c2 ("net_sched: ets: fix a race in ets_qdisc_change()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/sched/sch_ets.c

index 35b8577aef7dc2b46da68a0c3f486de217869d22..55b3362d27106e3328edb14f0678b6e2b55179b3 100644 (file)
@@ -298,7 +298,7 @@ static void ets_class_qlen_notify(struct Qdisc *sch, unsigned long arg)
         * to remove them.
         */
        if (!ets_class_is_strict(q, cl) && sch->q.qlen)
-               list_del(&cl->alist);
+               list_del_init(&cl->alist);
 }
 
 static int ets_class_dump(struct Qdisc *sch, unsigned long arg,
@@ -499,7 +499,7 @@ static struct sk_buff *ets_qdisc_dequeue(struct Qdisc *sch)
                        if (unlikely(!skb))
                                goto out;
                        if (cl->qdisc->q.qlen == 0)
-                               list_del(&cl->alist);
+                               list_del_init(&cl->alist);
                        return ets_qdisc_dequeue_skb(sch, skb);
                }
 
@@ -674,7 +674,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
        }
        for (i = q->nbands; i < oldbands; i++) {
                if (i >= q->nstrict && q->classes[i].qdisc->q.qlen)
-                       list_del(&q->classes[i].alist);
+                       list_del_init(&q->classes[i].alist);
                qdisc_tree_flush_backlog(q->classes[i].qdisc);
        }
        q->nstrict = nstrict;
@@ -723,7 +723,7 @@ static void ets_qdisc_reset(struct Qdisc *sch)
 
        for (band = q->nstrict; band < q->nbands; band++) {
                if (q->classes[band].qdisc->q.qlen)
-                       list_del(&q->classes[band].alist);
+                       list_del_init(&q->classes[band].alist);
        }
        for (band = 0; band < q->nbands; band++)
                qdisc_reset(q->classes[band].qdisc);