From: Jeff Layton <jlayton@kernel.org>
To: Shashank Mohan Jain <jain.sm@gmail.com>,
Andrew Morton <akpm@linux-foundation.org>
Cc: Jan Kara <jack@suse.cz>, NeilBrown <neil@brown.name>,
Thomas Maarseveen <maarseveent@gmail.com>,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 0/2] errseq: fix lost writeback errors in errseq_check_and_advance()
Date: Sun, 27 Sep 2026 17:48:24 +0200 [thread overview]
Message-ID: <0c8ff34adf831b7926468c83a2df8c67062ed3bc.camel@kernel.org> (raw)
In-Reply-To: <20260927051726.71337-1-jain.sm@gmail.com>
On Sun, 2026-09-27 at 10:47 +0530, Shashank Mohan Jain wrote:
> errseq_check_and_advance() advances the caller's cursor to the value it
> tried to store even when its cmpxchg() failed. If errseq_set() stored a
> different errno in the meantime, the cursor holds a value that was
> never in the errseq_t. errseq_set() does not bump the counter while the
> current error is unseen, so recording the first errno again recreates
> exactly that value, and once another subscriber has marked it seen, the
> cursor's next check returns 0. For fsync() (file->f_wb_err) and
> syncfs() (sb->s_wb_err) this means that a writeback error recorded
> after the previous call returned is not reported. The race is rare: it
> needs two different errnos, an error recorded while the check runs, and
> a second subscriber consuming the value. There is no user report; it
> was found with a model checker.
>
> Patch 1 retries with the value found when the cmpxchg() fails, so the
> cursor is only ever advanced to a value that was stored with
> ERRSEQ_SEEN set. Patch 2 adds a KUnit case that races errseq_set()
> against errseq_check_and_advance() on two CPUs.
>
> Two behaviour changes are visible to callers, both intended. When a
> writer wins the race, the call now returns the newer errno (still "the
> latest error", as documented). And when two threads race on the same
> unserialised cursor (syncfs() does not lock f_sb_err), the loser may
> now return 0 where both used to return the error, so each open file
> description gets one report.
>
> Dependencies: patch 1 applies to mainline (fd179f8a05be) on its own and
> carries Cc: stable. Patch 2 extends the errseq KUnit suite from commit
> b52f5c1605f2 ("lib/tests: add KUnit tests for errseq"), which is only
> in mm-nonmm-unstable, so the series is based on mm-nonmm-unstable
> (e8d6475e77a7). Patch 1 could go through mm-hotfixes and patch 2
> through mm-nonmm-unstable.
>
> The bug was found with a TLA+ model of lib/errseq.c checked with TLC.
> The patches were prepared with Claude Code (Anthropic), model Claude
> Opus 5.5 (claude-opus-5-5).
>
> Tested:
> - KUnit on UML x86_64 (kunitconfig with CONFIG_ERRSEQ_KUNIT_TEST=y,
> CONFIG_SMP=y and CONFIG_NR_CPUS=8, run with --kernel_args seccomp=on
> --kernel_args ncpus=4). Without patch 1 the new case loses the error
> in 21,957 to 116,003 of 2,000,000 rounds (1-6% over 8 runs,
> depending on host load), in 44,886 with ncpus=2, and in 30,353 on
> UML i386 with ncpus=4. With patch 1 it loses none (8 runs with 4
> CPUs, 1 with 2 CPUs, 1 on i386). All other errseq cases pass. On a
> single CPU the new case is skipped.
> - A userspace replay of the unmodified lib/errseq.c, with a hook before
> the cmpxchg() standing in for the other CPU, loses the error every
> time.
> - TLC: the current code violates "an error recorded after a check
> returned is reported by the next check"; with patch 1 the property
> holds exhaustively for 2 subscribers x 3 checks and either 1 writer
> x 4 errors (1,364,445 distinct states) or 2 writers x 2 errors
> (141,055,253 distinct states).
> - W=1 builds of lib/errseq.o and lib/tests/errseq_kunit.o for UML
> x86_64 and i386 without warnings, and checkpatch --strict.
>
> Not tested: fsync() or syncfs() on a real failing device, weakly
> ordered hardware (the model is sequentially consistent; the fix adds no
> ordering requirement beyond cmpxchg()), and architectures other than
> UML x86_64 and i386.
>
> Shashank Mohan Jain (2):
> errseq: don't let errseq_check_and_advance() hide later errors
> lib/tests: errseq: add a concurrent check_and_advance test
>
> lib/errseq.c | 29 +++++++----
> lib/tests/errseq_kunit.c | 110 +++++++++++++++++++++++++++++++++++++--
> 2 files changed, 123 insertions(+), 16 deletions(-)
>
>
> base-commit: e8d6475e77a75b7a84e42c9d23e238e002f2758f
Nice catch. I think your analysis and patch look correct to me.
Reviewed-by: Jeff Layton <jlayton@kernel.org>
prev parent reply other threads:[~2026-09-27 15:48 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-27 5:17 Shashank Mohan Jain
2026-09-27 5:17 ` [PATCH 1/2] errseq: don't let errseq_check_and_advance() hide later errors Shashank Mohan Jain
2026-09-27 5:17 ` [PATCH 2/2] lib/tests: errseq: add a concurrent check_and_advance test Shashank Mohan Jain
2026-09-27 15:48 ` Jeff Layton [this message]
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=0c8ff34adf831b7926468c83a2df8c67062ed3bc.camel@kernel.org \
--to=jlayton@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=jack@suse.cz \
--cc=jain.sm@gmail.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maarseveent@gmail.com \
--cc=neil@brown.name \
/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
all inboxes | Powered by JetHome®