From: Itai Handler <itai.handler@gmail.com>
To: mwalle@kernel.org, pratyush@kernel.org
Cc: linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org,
vigneshr@ti.com, richard@nod.at, miquel.raynal@bootlin.com,
takahiro.kuwano@infineon.com,
Itai Handler <itai.handler@gmail.com>
Subject: [PATCH v2 0/3] mtd: spi-nor: fix the unlocked restore on shutdown and remove
Date: Mon, 14 Sep 2026 11:11:46 +0300 [thread overview]
Message-ID: <20260914081149.1916589-1-itai.handler@gmail.com> (raw)
Two threads can talk to the flash at once during reboot/kexec and during
an unbind, because spi_nor_restore() is called without nor->lock while
MTD users are still attached. A busy flash silently ignores the restore
and is left in 4-byte addressing, which is exactly the failure the
restore was added to prevent; a restore landing inside a read corrupts
the rest of that read instead.
I reproduced this under QEMU, using a flash model extended to implement
erase busy time. With an erase outstanding, spi_nor_shutdown() issues
WREN, EX4B and WRDI; the chip refuses all three because it is busy, and
each one still reports success to the caller:
the flash was mid-erase when spi_nor_shutdown() tried to put it back
into 3-byte addressing, and refused 3 of its command(s):
0x06 (four_byte=1), 0xe9 (four_byte=1), 0x04 (four_byte=1)
four_byte=1 is the mode the chip was left in, and so the mode the next
kernel inherits. With the patch, shutdown waits for the erase and the
restore reaches an idle chip. The reproduction is deterministic: the
workload keeps the flash busy continuously, so no timing window is
involved.
Two caveats on that. It runs on a 5.10 vendor tree rather than mainline,
though the path is unchanged - mainline's spi_nor_shutdown() has the
same unlocked spi_nor_restore() call. And what started the investigation
was intermittent hangs after kexec on a Zynq UltraScale+ board, which I
have not tied to this race.
Patch 1 is new in v2 and is a prerequisite rather than part of the fix.
spi_nor_rww_start_exclusive() returns with nor->lock held on both of its
exits, so taking the flash lock in ->shutdown and ->remove, which is
what patches 2 and 3 do, would deadlock an RWW flash on every reboot and
every unbind. Nothing reaches that code today, which is how it survived
since v6.15, so patch 1 also stands on its own.
Patch 2 fixes ->shutdown, which every reboot and kexec goes through, and
is marked for stable. Patch 3 fixes the identical problem in ->remove; I
have deliberately not marked it for stable, since nobody has reported
hitting it and it changes how long an unbind can block. Patch 1 carries
a stable tag too, so that a backport of patch 2 cannot land without it.
Note what patch 2 does not do: the restore still runs with MTD users
attached, so an operation starting after it completes still addresses a
3-byte chip with nor->addr_nbytes == 4. Serialising against operations
already in flight is what stops the restore being issued into a busy
chip; fully closing the window would mean stopping MTD from accepting
operations before ->shutdown, which seemed too big a change to fold in
here. I am happy to look at that separately if you would prefer it.
Patches 2 and 3 are independent of each other; patch 3 can be dropped
without affecting patch 2. Patch 1 has to stay.
Changes in v2:
- New patch 1/3 fixing the lock that spi_nor_rww_start_exclusive()
leaves held on both exits. Without it the rest of the series
deadlocks on an RWW flash, because it adds the first ->shutdown and
->remove callers of the exclusive lock. Found while answering the
automated review of v1.
- Patches 2/3 and 3/3 are unchanged from v1 1/2 and 2/2.
- Link to v1:
https://lore.kernel.org/r/20260910184452.895485-1-itai.handler@gmail.com
Itai Handler (3):
mtd: spi-nor: fix the lock left held by spi_nor_rww_start_exclusive()
mtd: spi-nor: take the flash lock in spi_nor_shutdown()
mtd: spi-nor: take the flash lock in spi_nor_remove()
drivers/mtd/spi-nor/core.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
base-commit: 50d05c7c76c96b90462f24debacca971d2e86713
--
2.34.1
next reply other threads:[~2026-09-14 8:12 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-14 8:11 Itai Handler [this message]
2026-09-14 8:11 ` [PATCH v2 1/3] mtd: spi-nor: fix the lock left held by spi_nor_rww_start_exclusive() Itai Handler
2026-09-14 8:22 ` sashiko-bot
2026-09-14 8:11 ` [PATCH v2 2/3] mtd: spi-nor: take the flash lock in spi_nor_shutdown() Itai Handler
2026-09-14 8:24 ` sashiko-bot
2026-09-14 8:11 ` [PATCH v2 3/3] mtd: spi-nor: take the flash lock in spi_nor_remove() Itai Handler
2026-09-14 8:26 ` sashiko-bot
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=20260914081149.1916589-1-itai.handler@gmail.com \
--to=itai.handler@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=miquel.raynal@bootlin.com \
--cc=mwalle@kernel.org \
--cc=pratyush@kernel.org \
--cc=richard@nod.at \
--cc=takahiro.kuwano@infineon.com \
--cc=vigneshr@ti.com \
/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®