Skip to content

Commit be08d46

Browse files
edumazetgregkh
authored andcommitted
net/sched: sch_choke: annotate data-races in choke_dump_stats()
[ Upstream commit d3aeb88 ] choke_dump_stats() only runs with RTNL held. It reads fields that can be changed in qdisc fast path. Add READ_ONCE()/WRITE_ONCE() annotations. Fixes: edb09eb ("net: sched: do not acquire qdisc spinlock in qdisc/class stats dump") Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Jamal Hadi Salim <jhs@mojatatu.com> Link: https://patch.msgid.link/20260423062839.2524324-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 8dafd32 commit be08d46

1 file changed

Lines changed: 16 additions & 10 deletions

File tree

net/sched/sch_choke.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ static int choke_enqueue(struct sk_buff *skb, struct Qdisc *sch,
229229

230230
/* Draw a packet at random from queue and compare flow */
231231
if (choke_match_random(q, skb, &idx)) {
232-
q->stats.matched++;
232+
WRITE_ONCE(q->stats.matched, q->stats.matched + 1);
233233
choke_drop_by_idx(sch, idx, to_free);
234234
goto congestion_drop;
235235
}
@@ -241,23 +241,27 @@ static int choke_enqueue(struct sk_buff *skb, struct Qdisc *sch,
241241
qdisc_qstats_overlimit(sch);
242242
if (use_harddrop(q) || !use_ecn(q) ||
243243
!INET_ECN_set_ce(skb)) {
244-
q->stats.forced_drop++;
244+
WRITE_ONCE(q->stats.forced_drop,
245+
q->stats.forced_drop + 1);
245246
goto congestion_drop;
246247
}
247248

248-
q->stats.forced_mark++;
249+
WRITE_ONCE(q->stats.forced_mark,
250+
q->stats.forced_mark + 1);
249251
} else if (++q->vars.qcount) {
250252
if (red_mark_probability(p, &q->vars, q->vars.qavg)) {
251253
q->vars.qcount = 0;
252254
q->vars.qR = red_random(p);
253255

254256
qdisc_qstats_overlimit(sch);
255257
if (!use_ecn(q) || !INET_ECN_set_ce(skb)) {
256-
q->stats.prob_drop++;
258+
WRITE_ONCE(q->stats.prob_drop,
259+
q->stats.prob_drop + 1);
257260
goto congestion_drop;
258261
}
259262

260-
q->stats.prob_mark++;
263+
WRITE_ONCE(q->stats.prob_mark,
264+
q->stats.prob_mark + 1);
261265
}
262266
} else
263267
q->vars.qR = red_random(p);
@@ -272,7 +276,7 @@ static int choke_enqueue(struct sk_buff *skb, struct Qdisc *sch,
272276
return NET_XMIT_SUCCESS;
273277
}
274278

275-
q->stats.pdrop++;
279+
WRITE_ONCE(q->stats.pdrop, q->stats.pdrop + 1);
276280
return qdisc_drop(skb, sch, to_free);
277281

278282
congestion_drop:
@@ -461,10 +465,12 @@ static int choke_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
461465
{
462466
struct choke_sched_data *q = qdisc_priv(sch);
463467
struct tc_choke_xstats st = {
464-
.early = q->stats.prob_drop + q->stats.forced_drop,
465-
.marked = q->stats.prob_mark + q->stats.forced_mark,
466-
.pdrop = q->stats.pdrop,
467-
.matched = q->stats.matched,
468+
.early = READ_ONCE(q->stats.prob_drop) +
469+
READ_ONCE(q->stats.forced_drop),
470+
.marked = READ_ONCE(q->stats.prob_mark) +
471+
READ_ONCE(q->stats.forced_mark),
472+
.pdrop = READ_ONCE(q->stats.pdrop),
473+
.matched = READ_ONCE(q->stats.matched),
468474
};
469475

470476
return gnet_stats_copy_app(d, &st, sizeof(st));

0 commit comments

Comments
 (0)