From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: zhidao su <soolaugust@gmail.com>, zhidao su <suzhidao@xiaomi.com>,
Tejun Heo <tj@kernel.org>, Sasha Levin <sashal@kernel.org>,
mingo@redhat.com, peterz@infradead.org, juri.lelli@redhat.com,
vincent.guittot@linaro.org, sched-ext@lists.linux.dev,
linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.19-6.12] sched_ext: Use WRITE_ONCE() for the write side of dsq->seq update
Date: Tue, 17 Mar 2026 07:32:43 -0400 [thread overview]
Message-ID: <20260317113249.117771-12-sashal@kernel.org> (raw)
In-Reply-To: <20260317113249.117771-1-sashal@kernel.org>
From: zhidao su <soolaugust@gmail.com>
[ Upstream commit 7a8464555d2e5f038758bb19e72ab4710b79e9cd ]
bpf_iter_scx_dsq_new() reads dsq->seq via READ_ONCE() without holding
any lock, making dsq->seq a lock-free concurrently accessed variable.
However, dispatch_enqueue(), the sole writer of dsq->seq, uses a plain
increment without the matching WRITE_ONCE() on the write side:
dsq->seq++;
^^^^^^^^^^^
plain write -- 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 write leaves
the pair incomplete and will trigger KCSAN warnings.
Fix by using WRITE_ONCE() for the write side of the update:
WRITE_ONCE(dsq->seq, dsq->seq + 1);
This is consistent with bpf_iter_scx_dsq_new() 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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Now I have all the information I need for the analysis.
## Analysis
### 1. Commit Message Analysis
The commit fixes a KCSAN data race annotation issue. `dsq->seq` is read
lock-free via `READ_ONCE()` in `bpf_iter_scx_dsq_new()` (line 6589), but
the write side in `dispatch_enqueue()` uses a plain `dsq->seq++` (line
1100). KCSAN requires that if one side uses
`READ_ONCE()`/`WRITE_ONCE()`, all accessors must also use the
appropriate annotation. The fix is a one-line change from `dsq->seq++`
to `WRITE_ONCE(dsq->seq, dsq->seq + 1)`.
### 2. Code Change Analysis
The change is trivially small and correct:
- **Before**: `dsq->seq++` — plain write, incomplete KCSAN annotation
- **After**: `WRITE_ONCE(dsq->seq, dsq->seq + 1)` — properly annotated
write
The read side at line 6589 already uses `READ_ONCE(kit->dsq->seq)`,
confirming this is a lock-free concurrent access pattern. The write side
holds a lock (dispatch queue lock), but the reader does not, making the
`WRITE_ONCE()`/`READ_ONCE()` pair necessary for correctness under the
KCSAN/C11 memory model.
### 3. Subsystem: sched_ext
**Critical factor**: `sched_ext` was introduced in **v6.12**. The
current stable kernel trees are:
- 6.12.y (contains sched_ext)
- 6.6.y (does NOT contain sched_ext)
- 6.1.y (does NOT contain sched_ext)
- 5.15.y, 5.10.y, etc. (do NOT contain sched_ext)
This means the commit can only apply to **6.12.y** (and later, 6.19.y
once it becomes a stable tree).
### 4. Bug Severity
This is a KCSAN annotation completeness fix. It:
- Fixes a real data race (writer uses plain store while reader uses
`READ_ONCE()`)
- Prevents KCSAN warnings
- The practical impact on most architectures (especially x86) is minimal
since `dsq->seq` is a `u64` and the write is already atomic in
practice on 64-bit platforms
- However, on some architectures (32-bit), a plain write to a 64-bit
value could be torn, potentially causing the reader to see a
partially-updated value
### 5. Risk Assessment
- **One-line change**: Minimal risk
- **Obviously correct**: `WRITE_ONCE()` is the standard annotation for
this pattern
- **No behavioral change**: Same value is written, just with proper
annotation
- **Well-tested pattern**: `WRITE_ONCE(x, x + 1)` is used extensively
throughout the kernel
### 6. Stable Criteria Assessment
- **Fixes a real bug**: Yes — data race (KCSAN violation), and
potentially a real torn-write issue on 32-bit
- **Obviously correct**: Yes — standard `WRITE_ONCE()` pattern
- **Small and contained**: Yes — one line changed
- **No new features**: Correct
- **Tested**: Accepted by maintainer (Tejun Heo)
While this is a legitimate fix, the severity is quite low. It primarily
silences KCSAN warnings and ensures correctness of the annotation pair.
On 64-bit architectures (where sched_ext is primarily used), the plain
store was already effectively atomic. The practical user impact is
minimal.
### Verification
- Verified `sched_ext` was introduced in v6.12 via `git log --diff-
filter=A -- kernel/sched/ext.c` (commit `f0e1a0643a59b`)
- Verified no commits to `kernel/sched/ext.c` exist in `v6.10..v6.11`
range (file didn't exist before 6.12)
- Confirmed `READ_ONCE(kit->dsq->seq)` exists at line 6589 of
`kernel/sched/ext.c` (the reader)
- Confirmed `dsq->seq++` exists at line 1100 (the writer being fixed)
- The write occurs under a lock (dispatch queue lock held in
`dispatch_enqueue`), but the read in `bpf_iter_scx_dsq_new()` is lock-
free
- Verified this is a one-line change with no dependencies
### Decision
This is a valid but low-severity KCSAN data race annotation fix. It's a
one-line change that is obviously correct and fixes a real (if minor)
data race. It only applies to 6.12.y stable since sched_ext doesn't
exist in older trees. The fix is small, surgical, and meets stable
kernel criteria — it prevents KCSAN warnings and ensures proper memory
access semantics for concurrent access to `dsq->seq`.
**YES**
kernel/sched/ext.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
index 0bb8fa927e9e9..413b9f9336fe9 100644
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -1097,7 +1097,7 @@ static void dispatch_enqueue(struct scx_sched *sch, struct scx_dispatch_q *dsq,
}
/* seq records the order tasks are queued, used by BPF DSQ iterator */
- dsq->seq++;
+ WRITE_ONCE(dsq->seq, dsq->seq + 1);
p->scx.dsq_seq = dsq->seq;
dsq_mod_nr(dsq, 1);
--
2.51.0
next prev parent reply other threads:[~2026-03-17 11:33 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-17 11:32 [PATCH AUTOSEL 6.19-6.1] ALSA: hda/realtek: add HP Laptop 14s-dr5xxx mute LED quirk Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.6] spi: intel-pci: Add support for Nova Lake mobile SPI flash Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19] objtool: Use HOSTCFLAGS for HAVE_XXHASH test Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.18] powerpc64/ftrace: fix OOL stub count with clang Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.12] nvmet: move async event work off nvmet-wq Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.12] drm/amdgpu: fix gpu idle power consumption issue for gfx v12 Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19] objtool/klp: Disable unsupported pr_debug() usage Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19] ALSA: usb-audio: Add iface reset and delay quirk for SPACETOUCH USB Audio Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.1] usb: core: new quirk to handle devices with zero configurations Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.12] ALSA: hda/realtek: add quirk for ASUS UM6702RC Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.6] objtool: Handle Clang RSP musical chairs Sasha Levin
2026-03-17 11:32 ` Sasha Levin [this message]
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.1] btrfs: set BTRFS_ROOT_ORPHAN_CLEANUP during subvol create Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.18] ALSA: hda/realtek: Add quirk for Gigabyte Technology to fix headphone Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-6.12] i3c: master: dw-i3c: Fix missing of_node for virtual I2C adapter Sasha Levin
2026-03-17 11:32 ` [PATCH AUTOSEL 6.19-5.10] ALSA: hda/realtek: Add headset jack quirk for Thinkpad X390 Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260317113249.117771-12-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=juri.lelli@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=patches@lists.linux.dev \
--cc=peterz@infradead.org \
--cc=sched-ext@lists.linux.dev \
--cc=soolaugust@gmail.com \
--cc=stable@vger.kernel.org \
--cc=suzhidao@xiaomi.com \
--cc=tj@kernel.org \
--cc=vincent.guittot@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox