Re: [PATCH 3/6] md/raid1: don't use write-behind for P2PDMA bios

[email protected] Sat, 18 Jul 2026 16:58:37 +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:
- [Critical] P2PDMA bios bypass write-behind but fail to serialize against outstanding write-behind I/O, leading to silent data corruption on write-mostly devices.
--

--- Patch [3]: [PATCH 3/6] md/raid1: don't use write-behind for P2PDMA bios ---
commit bbb98e00f3bb1bd5712cfce20170706425ddb589
Author: Mykola Marzhan <[email protected]>

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

alloc_behind_master_bio() copies the bio's data with bio_copy_data(),
a CPU copy. P2PDMA pages are peer device (BAR) memory; generic code
must not assume CPU load/store access to them is safe or fast on
every architecture, and bouncing peer memory through the CPU defeats
the point of a peer-to-peer transfer.

Skip write-behind for P2PDMA bios: they are written directly to all
members, including write-mostly ones.

> diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
> index afe2ca96ad8c2..57f64e8901024 100644
> --- a/drivers/md/raid1.c
> +++ b/drivers/md/raid1.c
> @@ -1575,9 +1575,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 && rdev && test_bit(WriteMostly, &rdev->flags) &&
> +		    !md_bio_is_p2pdma(bio))
>  			write_behind = true;
>  

[Severity: Critical]
This is a pre-existing issue, but by excluding P2PDMA bios from
write-behind, does this expose them to silent data corruption due to
missing serialization checks?

When a normal write to a sector uses write-behind, it can be acknowledged
to the caller once fast devices complete, leaving the write-behind bio
in-flight to the write-mostly device.

If a subsequent P2PDMA write is issued to the same sector, this patch
explicitly disables write-behind for it. Because of this,
r1_bio->behind_master_bio remains NULL, and execution falls into the else
branch further down in raid1_write_request():

drivers/md/raid1.c:raid1_write_request() {
    ...
		if (r1_bio->behind_master_bio) {
			mbio = bio_alloc_clone(rdev->bdev,
					       r1_bio->behind_master_bio,
					       GFP_NOIO, &mddev->bio_set);
			if (test_bit(CollisionCheck, &rdev->flags))
				wait_for_serialization(rdev, r1_bio);
                ...
		} else {
			mbio = bio_alloc_clone(rdev->bdev, bio, GFP_NOIO,
					       &mddev->bio_set);

			if (test_bit(MD_SERIALIZE_POLICY, &mddev->flags))
				wait_for_serialization(rdev, r1_bio);
		}
    ...
}

Because the else branch skips the CollisionCheck test,
wait_for_serialization() is bypassed (unless MD_SERIALIZE_POLICY is globally
set). Can the block layer then reorder these concurrent requests, overwriting
the newer P2PDMA data with the older in-flight write-behind data?

>  		r1_bio->bios[i] = NULL;

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