diff options
| author | Cong Wang <xiyou.wangcong@gmail.com> | 2025-04-03 14:10:26 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2025-05-09 09:44:04 +0200 |
| commit | 36269156033fe6262af0872f6ca539b8afb403c3 (patch) | |
| tree | 25fc4312c0dd50bbc5073ecf2719011481f4c32d /net | |
| parent | 9030a91235ae4845ec71902c3e0cecfc9ed1f2df (diff) | |
| download | linux-36269156033fe6262af0872f6ca539b8afb403c3.tar.gz linux-36269156033fe6262af0872f6ca539b8afb403c3.tar.bz2 linux-36269156033fe6262af0872f6ca539b8afb403c3.zip | |
sch_qfq: make qfq_qlen_notify() idempotent
commit 55f9eca4bfe30a15d8656f915922e8c98b7f0728 upstream.
qfq_qlen_notify() always deletes its class from its active list
with list_del_init() _and_ calls qfq_deactivate_agg() when the whole list
becomes empty.
To make it idempotent, just skip everything when it is not in the active
list.
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>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250403211033.166059-5-xiyou.wangcong@gmail.com
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
| -rw-r--r-- | net/sched/sch_qfq.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index c7d4ee8cedff..5e557b960bde 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -352,7 +352,7 @@ static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl) struct qfq_aggregate *agg = cl->agg; - list_del(&cl->alist); /* remove from RR queue of the aggregate */ + list_del_init(&cl->alist); /* remove from RR queue of the aggregate */ if (list_empty(&agg->active)) /* agg is now inactive */ qfq_deactivate_agg(q, agg); } @@ -482,6 +482,7 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, gnet_stats_basic_sync_init(&cl->bstats); cl->common.classid = classid; cl->deficit = lmax; + INIT_LIST_HEAD(&cl->alist); cl->qdisc = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, classid, NULL); @@ -990,7 +991,7 @@ static struct sk_buff *agg_dequeue(struct qfq_aggregate *agg, cl->deficit -= (int) len; if (cl->qdisc->q.qlen == 0) /* no more packets, remove from list */ - list_del(&cl->alist); + list_del_init(&cl->alist); else if (cl->deficit < qdisc_pkt_len(cl->qdisc->ops->peek(cl->qdisc))) { cl->deficit += agg->lmax; list_move_tail(&cl->alist, &agg->active); @@ -1421,6 +1422,8 @@ static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg) struct qfq_sched *q = qdisc_priv(sch); struct qfq_class *cl = (struct qfq_class *)arg; + if (list_empty(&cl->alist)) + return; qfq_deactivate_class(q, cl); } |
