Linux RAID subsystem development
 help / color / mirror / Atom feed
* [PATCH] md/raid1: release barrier when REQ_NOWAIT write would block
@ 2026-06-11 13:25 Abd-Alrhman Masalkhi
  2026-06-11 13:41 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Abd-Alrhman Masalkhi @ 2026-06-11 13:25 UTC (permalink / raw)
  To: song, yukuai, magiclinan, xiao
  Cc: linux-raid, linux-kernel, Abd-Alrhman Masalkhi, sashiko-bot

raid1_write_request() calls wait_barrier(), which raises
conf->nr_pending, before calling wait_blocked_rdev(). When
wait_blocked_rdev() fails for a REQ_NOWAIT write, the bio is completed
and the function returns without calling allow_barrier(), leaking the
nr_pending reference taken by wait_barrier().

freeze_array() waits for nr_pending to drop to zero, so a leaked
reference prevents the array from ever being frozen again. Any later
operation that freezes the array then hangs, including resync, reshape,
device removal and array teardown.

Release the barrier on the REQ_NOWAIT failure path.

Fixes: 88ed59c4cc6c ("md/raid1: factor out helper to handle blocked rdev from raid1_write_request()")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260611083514.754922-1-abd.masalkhi@gmail.com?part=1
Signed-off-by: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>
---
 drivers/md/raid1.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 6263a1d45f86..e9086ba1f796 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1522,6 +1522,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
 	int max_sectors;
 	bool write_behind = false;
 	bool is_discard = (bio_op(bio) == REQ_OP_DISCARD);
+	sector_t sector = bio->bi_iter.bi_sector;
 
 	if (mddev_is_clustered(mddev) &&
 	    mddev->cluster_ops->area_resyncing(mddev, WRITE,
@@ -1550,6 +1551,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
 
 	if (!wait_blocked_rdev(mddev, bio)) {
 		bio_wouldblock_error(bio);
+		allow_barrier(conf, sector);
 		return;
 	}
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] md/raid1: release barrier when REQ_NOWAIT write would block
  2026-06-11 13:25 [PATCH] md/raid1: release barrier when REQ_NOWAIT write would block Abd-Alrhman Masalkhi
@ 2026-06-11 13:41 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-06-11 13:41 UTC (permalink / raw)
  To: Abd-Alrhman Masalkhi; +Cc: yukuai, linux-raid

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Missing RCU read lock around `conf->mirrors[i].rdev` access in `wait_blocked_rdev()`.
- [High] Early failure paths in `raid1_write_request()` leak the `mddev->writes_pending` reference.
- [High] Allocating bios and r1bios can sleep even when the `REQ_NOWAIT` flag is set.
--

commit 3db9da0ec804800aa3afb93361ccd18de39ce5f0
Author: Abd-Alrhman Masalkhi <abd.masalkhi@gmail.com>

md/raid1: release barrier when REQ_NOWAIT write would block

raid1_write_request() leaks the barrier reference taken by wait_barrier()
if wait_blocked_rdev() fails for a REQ_NOWAIT write. This patch releases
the barrier on this failure path to prevent array freeze hangs.

Closes: https://sashiko.dev/#/patchset/20260611083514.754922-1-abd.masalkhi@gmail.com?part=1

> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index 5b9368bd9e700..f3cc30932ba2b 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -1512,6 +1512,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
>  	int max_sectors;
>  	bool write_behind = false;
>  	bool is_discard = (bio_op(bio) == REQ_OP_DISCARD);
> +	sector_t sector = bio->bi_iter.bi_sector;
>  
>  	if (mddev_is_clustered(mddev) &&
>  	    mddev->cluster_ops->area_resyncing(mddev, WRITE,
> @@ -1540,6 +1541,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
>  
>  	if (!wait_blocked_rdev(mddev, bio)) {
>  		bio_wouldblock_error(bio);
> +		allow_barrier(conf, sector);

[Severity: High]
This is a pre-existing issue, but does this early return path also leak the
mddev->writes_pending reference?

In raid1_make_request(), md_write_start() unconditionally takes a per-cpu
reference on mddev->writes_pending before calling raid1_write_request().
Normally, this is released via md_write_end() inside close_write().

By directly returning here after bio_wouldblock_error(bio), we never call
md_write_end(). Does this permanently leak the writes_pending counter and
prevent the array from transitioning to a clean state?

It looks like this same leak exists on the clustered area_resyncing and
wait_barrier REQ_NOWAIT failure paths earlier in this function, as well as
the err_handle path if bio_submit_split_bioset() fails.

>  		return;
>  	}

[Severity: Critical]
This is a pre-existing issue, but is it safe to call wait_blocked_rdev()
here without holding the RCU read lock?

Looking at wait_blocked_rdev():

	for (i = 0; i < disks; i++) {
		struct md_rdev *rdev = conf->mirrors[i].rdev;

		if (!rdev)
			continue;

		/* don't write here until the bad block is acknowledged */
		if (test_bit(WriteErrorSeen, &rdev->flags) &&

It accesses the rdev pointer and its fields without rcu_read_lock().
Could a concurrent device removal (via md_ioctl -> raid1_remove_conf)
replace the pointer with NULL and free the rdev structure while we are
dereferencing it here, resulting in a use-after-free?

[Severity: High]
This is also a pre-existing issue, but if we proceed past this point for a
REQ_NOWAIT bio, we call alloc_r1bio() and eventually bio_alloc_clone(),
both of which use GFP_NOIO.

Since memory pool allocations with GFP_NOIO can block when the mempool is
exhausted under memory pressure, could this cause REQ_NOWAIT writes to
sleep, defeating the purpose of the REQ_NOWAIT flag?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260611132500.763528-1-abd.masalkhi@gmail.com?part=1

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-06-11 13:41 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-11 13:25 [PATCH] md/raid1: release barrier when REQ_NOWAIT write would block Abd-Alrhman Masalkhi
2026-06-11 13:41 ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox