md_submit_bio() strips REQ_NOMERGE from every bio. For P2PDMA bios the flag is what keeps requests single-provider (see __bio_add_page()): merging a P2PDMA bio with one over a different pgmap, or over host memory, maps the merged request with the wrong bus address. Set the flag on P2PDMA bios -- bios built via bio_iov_bvec_set() arrive without it -- and keep stripping it otherwise. Fixes: 02666132403a ("md: propagate BLK_FEAT_PCI_P2PDMA from member devices to RAID device") Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Mykola Marzhan Reviewed-by: Logan Gunthorpe --- drivers/md/md.c | 10 ++++++++-- drivers/md/md.h | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index d1465bcd86c8..3770bdb4d4b2 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -451,8 +451,14 @@ static void md_submit_bio(struct bio *bio) return; } - /* bio could be mergeable after passing to underlayer */ - bio->bi_opf &= ~REQ_NOMERGE; + /* + * A bio md split may merge again below md -- except P2PDMA bios, + * which must stay single-provider (see __bio_add_page()). + */ + if (md_bio_is_p2pdma(bio)) + bio->bi_opf |= REQ_NOMERGE; + else + bio->bi_opf &= ~REQ_NOMERGE; md_handle_request(mddev, bio); } diff --git a/drivers/md/md.h b/drivers/md/md.h index d8daf0f75cbb..73df1a6eccd8 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -22,6 +24,19 @@ #include #define MaxSector (~(sector_t)0) + +/* + * P2P and host pages never mix within a bio, so the first bvec is + * representative. Read bi_io_vec directly: bio_first_bvec_all() + * WARNs on the split clones md handles, and data-less bios have no + * bi_io_vec. Not valid after the bio's iterator is consumed. + */ +static inline bool md_bio_is_p2pdma(struct bio *bio) +{ + return bio_has_data(bio) && bio->bi_io_vec && + is_pci_p2pdma_page(bio->bi_io_vec->bv_page); +} + /* * Number of guaranteed raid bios in case of extreme VM load: */ -- 2.52.0