]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
sch_hfsc: make hfsc_qlen_notify() idempotent
authorCong Wang <xiyou.wangcong@gmail.com>
Thu, 3 Apr 2025 21:10:25 +0000 (14:10 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 28 Aug 2025 14:22:51 +0000 (16:22 +0200)
commit 51eb3b65544c9efd6a1026889ee5fb5aa62da3bb upstream.

hfsc_qlen_notify() is not idempotent either and not friendly
to its callers, like fq_codel_dequeue(). Let's make it idempotent
to ease qdisc_tree_reduce_backlog() callers' life:

1. update_vf() decreases cl->cl_nactive, so we can check whether it is
non-zero before calling it.

2. eltree_remove() always removes RB node cl->el_node, but we can use
   RB_EMPTY_NODE() + RB_CLEAR_NODE() to make it safe.

Reported-by: Gerrard Tai <gerrard.tai@starlabs.sg>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250403211033.166059-4-xiyou.wangcong@gmail.com
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Siddh Raman Pant <siddh.raman.pant@oracle.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/sched/sch_hfsc.c

index 443db2c08a09585150e3929007dff9362890d548..2454bafbbb11fd6c0e86b42988e623d79754061c 100644 (file)
@@ -209,7 +209,10 @@ eltree_insert(struct hfsc_class *cl)
 static inline void
 eltree_remove(struct hfsc_class *cl)
 {
-       rb_erase(&cl->el_node, &cl->sched->eligible);
+       if (!RB_EMPTY_NODE(&cl->el_node)) {
+               rb_erase(&cl->el_node, &cl->sched->eligible);
+               RB_CLEAR_NODE(&cl->el_node);
+       }
 }
 
 static inline void
@@ -1230,7 +1233,8 @@ hfsc_qlen_notify(struct Qdisc *sch, unsigned long arg)
        /* vttree is now handled in update_vf() so that update_vf(cl, 0, 0)
         * needs to be called explicitly to remove a class from vttree.
         */
-       update_vf(cl, 0, 0);
+       if (cl->cl_nactive)
+               update_vf(cl, 0, 0);
        if (cl->cl_flags & HFSC_RSC)
                eltree_remove(cl);
 }