Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

sched_ext: Use READ_ONCE() for the read side of dsq->nr update

scx_bpf_dsq_nr_queued() reads dsq->nr via READ_ONCE() without holding
any lock, making dsq->nr a lock-free concurrently accessed variable.
However, dsq_mod_nr(), the sole writer of dsq->nr, only uses
WRITE_ONCE() on the write side without the matching READ_ONCE() on the
read side:

WRITE_ONCE(dsq->nr, dsq->nr + delta);
^^^^^^^
plain read -- KCSAN data race

The KCSAN documentation requires that if one accessor uses READ_ONCE()
or WRITE_ONCE() on a variable to annotate lock-free access, all other
accesses must also use the appropriate accessor. A plain read on the
right-hand side of WRITE_ONCE() leaves the pair incomplete and will
trigger KCSAN warnings.

Fix by using READ_ONCE() for the read side of the update:

WRITE_ONCE(dsq->nr, READ_ONCE(dsq->nr) + delta);

This is consistent with scx_bpf_dsq_nr_queued() and makes the
concurrent access annotation complete and KCSAN-clean.

Signed-off-by: zhidao su <suzhidao@xiaomi.com>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

zhidao su and committed by
Tejun Heo
9adfcef3 032e084f

+6 -2
+6 -2
kernel/sched/ext.c
··· 976 976 977 977 static void dsq_mod_nr(struct scx_dispatch_q *dsq, s32 delta) 978 978 { 979 - /* scx_bpf_dsq_nr_queued() reads ->nr without locking, use WRITE_ONCE() */ 980 - WRITE_ONCE(dsq->nr, dsq->nr + delta); 979 + /* 980 + * scx_bpf_dsq_nr_queued() reads ->nr without locking. Use READ_ONCE() 981 + * on the read side and WRITE_ONCE() on the write side to properly 982 + * annotate the concurrent lockless access and avoid KCSAN warnings. 983 + */ 984 + WRITE_ONCE(dsq->nr, READ_ONCE(dsq->nr) + delta); 981 985 } 982 986 983 987 static void refill_task_slice_dfl(struct scx_sched *sch, struct task_struct *p)