Re: [PATCH v4 4/9] md/raid1: don't use write-behind for P2PDMA bios

[email protected] Wed, 22 Jul 2026 19:11:31 +0000
Newsgroups org.kernel.vger.linux-raid,org.kernel.vger.linux-pci
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] raid1_write_request() can block on resource allocations and serialization when processing a REQ_NOWAIT bio, violating non-blocking guarantees.
--

--- Patch [4]: [PATCH v4 4/9] md/raid1: don't use write-behind for P2PDMA bios ---
commit 1a1224f9f3e6ee3f02e62a2f1a4ff02688f39f0d
Author: Mykola Marzhan <[email protected]>

md/raid1: don't use write-behind for P2PDMA bios

This commit skips write-behind for P2PDMA bios as they are written directly
to all members, including write-mostly ones. A CPU copy via bio_copy_data()
defeats the point of a peer-to-peer transfer.

> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index 997f79c05db7b..7d769b6460ca7 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -1523,6 +1523,7 @@ static bool raid1_write_request(struct mddev *mddev, struct bio *bio,
>  	bool write_behind = false;
>  	bool nowait = bio->bi_opf & REQ_NOWAIT;
>  	bool is_discard = op_is_discard(bio->bi_opf);
> +	bool is_p2pdma = md_bio_is_p2pdma(bio);
>  	sector_t sector = bio->bi_iter.bi_sector;
>  
>  	if (mddev_is_clustered(mddev) &&
[ ... ]
> @@ -1575,9 +1576,12 @@ static bool raid1_write_request(struct mddev *mddev, struct bio *bio,
>  		/*
>  		 * The write-behind io is only attempted on drives marked as
>  		 * write-mostly, which means we could allocate write behind
> -		 * bio later.
> +		 * bio later. P2PDMA bios are excluded: write-behind copies
> +		 * the data with bio_copy_data(), a CPU copy that cannot be
> +		 * assumed safe or fast on P2PDMA (device BAR) pages.
>  		 */
> -		if (!is_discard && rdev && test_bit(WriteMostly, &rdev->flags))
> +		if (!is_discard && !is_p2pdma && rdev &&
> +		    test_bit(WriteMostly, &rdev->flags))
>  			write_behind = true;
>  
>  		r1_bio->bios[i] = NULL;

[Severity: High]
This is a pre-existing issue, but does raid1_write_request() properly support
REQ_NOWAIT semantics without blocking?

Earlier in raid1_write_request(), we allocate r1_bio unconditionally using
GFP_NOIO, which can sleep under memory pressure:

    r1_bio = alloc_r1bio(mddev, bio);

alloc_r1bio() {
    ...
    r1_bio = mempool_alloc(conf->r1bio_pool, GFP_NOIO);
    ...
}

Later down in raid1_write_request(), if CollisionCheck is set, we can
unconditionally put the thread to sleep, ignoring the REQ_NOWAIT context:

    if (test_bit(CollisionCheck, &rdev->flags))
        wait_for_serialization(rdev, r1_bio);

wait_for_serialization() {
    ...
    si = mempool_alloc(mddev->serial_info_pool, GFP_NOIO);
    ...
    wait_for_completion(&si->ready);
}

Could a REQ_NOWAIT write bio submitted to an md raid1 array block under
memory pressure or in-flight I/O overlapping, causing thread starvation in
io_uring workers?

-- 
Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=4