mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 14:41:22 -05:00
net/sched: sch_qfq: Avoid triggering might_sleep in atomic context in qfq_delete_class
might_sleep could be trigger in the atomic context in qfq_delete_class.
qfq_destroy_class was moved into atomic context locked
by sch_tree_lock to avoid a race condition bug on
qfq_aggregate. However, might_sleep could be triggered by
qfq_destroy_class, which introduced sleeping in atomic context (path:
qfq_destroy_class->qdisc_put->__qdisc_destroy->lockdep_unregister_key
->might_sleep).
Considering the race is on the qfq_aggregate objects, keeping
qfq_rm_from_agg in the lock but moving the left part out can solve
this issue.
Fixes: 5e28d5a3f7 ("net/sched: sch_qfq: Fix race condition on qfq_aggregate")
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Link: https://patch.msgid.link/4a04e0cc-a64b-44e7-9213-2880ed641d77@sabinyo.mountain
Reviewed-by: Cong Wang <xiyou.wangcong@gmail.com>
Reviewed-by: Dan Carpenter <dan.carpenter@linaro.org>
Link: https://patch.msgid.link/20250717230128.159766-1-xmei5@asu.edu
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@@ -536,9 +536,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
|
||||
|
||||
static void qfq_destroy_class(struct Qdisc *sch, struct qfq_class *cl)
|
||||
{
|
||||
struct qfq_sched *q = qdisc_priv(sch);
|
||||
|
||||
qfq_rm_from_agg(q, cl);
|
||||
gen_kill_estimator(&cl->rate_est);
|
||||
qdisc_put(cl->qdisc);
|
||||
kfree(cl);
|
||||
@@ -559,10 +556,11 @@ static int qfq_delete_class(struct Qdisc *sch, unsigned long arg,
|
||||
|
||||
qdisc_purge_queue(cl->qdisc);
|
||||
qdisc_class_hash_remove(&q->clhash, &cl->common);
|
||||
qfq_destroy_class(sch, cl);
|
||||
qfq_rm_from_agg(q, cl);
|
||||
|
||||
sch_tree_unlock(sch);
|
||||
|
||||
qfq_destroy_class(sch, cl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1503,6 +1501,7 @@ static void qfq_destroy_qdisc(struct Qdisc *sch)
|
||||
for (i = 0; i < q->clhash.hashsize; i++) {
|
||||
hlist_for_each_entry_safe(cl, next, &q->clhash.hash[i],
|
||||
common.hnode) {
|
||||
qfq_rm_from_agg(q, cl);
|
||||
qfq_destroy_class(sch, cl);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user