A member that cannot DMA-map peer memory fails the leg bio with BLK_STS_TARGET. The failure is a property of the peer/member pairing -- retrying the same pages against the same member cannot succeed, and there is nothing on the medium to repair -- but the error machinery treats it as a medium error: narrow_write_error() grinds through hundreds of doomed chunk retries per write, WantReplacement burns a spare and evicts the healthy member, fix_read_error()'s host-page probe "succeeds" so mixed host/P2P reads charge the read-error budget until a healthy member is kicked (~1s in testing), and FailFast evicts on the first unroutable I/O. Flag P2PDMA master bios with a new R1BIO_P2PDMA state bit at submission. On a BLK_STS_TARGET leg failure for a flagged bio: retry writes once as a single whole range, recording one bad range if that also fails (TARGET can be a transient device condition, e.g. NVME_SC_NS_NOT_READY, so the retry is not skipped outright); don't set WantReplacement; mark failed read legs IO_BLOCKED without charging the read-error budget; and don't treat the failure as FailFast evidence -- the request never reached the wire -- as commit f7b24c7b41f2 ("md/raid1,raid10: don't fail devices for invalid IO errors") did for BLK_STS_INVAL. 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 --- drivers/md/raid1.c | 54 ++++++++++++++++++++++++++++++++++------------ drivers/md/raid1.h | 2 ++ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 16b7465c233a..6334032c4bb8 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -483,16 +483,22 @@ static void raid1_end_write_request(struct bio *bio) * 'one mirror IO has finished' event handler: */ if (bio->bi_status && !ignore_error) { - set_bit(WriteErrorSeen, &rdev->flags); - if (!test_and_set_bit(WantReplacement, &rdev->flags)) - set_bit(MD_RECOVERY_NEEDED, & - conf->mddev->recovery); + /* Peer/member pairing failure, not member health. */ + bool p2pdma_unmappable = bio->bi_status == BLK_STS_TARGET && + test_bit(R1BIO_P2PDMA, &r1_bio->state); - if (test_bit(FailFast, &rdev->flags) && - (bio->bi_opf & MD_FAILFAST) && - /* We never try FailFast to WriteMostly devices */ - !test_bit(WriteMostly, &rdev->flags)) { - md_error(r1_bio->mddev, rdev); + set_bit(WriteErrorSeen, &rdev->flags); + if (!p2pdma_unmappable) { + if (!test_and_set_bit(WantReplacement, &rdev->flags)) + set_bit(MD_RECOVERY_NEEDED, + &conf->mddev->recovery); + + if (test_bit(FailFast, &rdev->flags) && + (bio->bi_opf & MD_FAILFAST) && + /* We never try FailFast to WriteMostly devices */ + !test_bit(WriteMostly, &rdev->flags)) { + md_error(r1_bio->mddev, rdev); + } } /* @@ -1378,6 +1384,8 @@ static void raid1_read_request(struct mddev *mddev, struct bio *bio, else init_r1bio(r1_bio, mddev, bio); r1_bio->sectors = max_read_sectors; + if (md_bio_is_p2pdma(bio)) + set_bit(R1BIO_P2PDMA, &r1_bio->state); /* * make_request() can abort the operation when read-ahead is being @@ -1557,6 +1565,8 @@ static bool raid1_write_request(struct mddev *mddev, struct bio *bio, r1_bio = alloc_r1bio(mddev, bio); r1_bio->sectors = max_sectors; + if (md_bio_is_p2pdma(bio)) + set_bit(R1BIO_P2PDMA, &r1_bio->state); /* first select target devices under rcu_lock and * inc refcount on their rdev. Record them by setting @@ -2522,7 +2532,7 @@ static void fix_read_error(struct r1conf *conf, struct r1bio *r1_bio) } } -static void narrow_write_error(struct r1bio *r1_bio, int i) +static void narrow_write_error(struct r1bio *r1_bio, int i, bool coarse) { struct mddev *mddev = r1_bio->mddev; struct r1conf *conf = mddev->private; @@ -2536,6 +2546,9 @@ static void narrow_write_error(struct r1bio *r1_bio, int i) * It is conceivable that the bio doesn't exactly align with * blocks. We must handle this somehow. * + * With 'coarse', retry the whole range as one bio: P2PDMA + * mapping failures fail every block identically. + * * We currently own a reference on the rdev. */ @@ -2550,9 +2563,12 @@ static void narrow_write_error(struct r1bio *r1_bio, int i) block_sectors = roundup(1 << rdev->badblocks.shift, lbs); sector = r1_bio->sector; - sectors = ((sector + block_sectors) - & ~(sector_t)(block_sectors - 1)) - - sector; + if (coarse) + sectors = sect_to_write; + else + sectors = ((sector + block_sectors) + & ~(sector_t)(block_sectors - 1)) + - sector; while (sect_to_write) { struct bio *wbio; @@ -2633,8 +2649,12 @@ static void handle_write_finished(struct r1conf *conf, struct r1bio *r1_bio) * narrow down and record precise write * errors. */ + bool coarse = r1_bio->bios[m]->bi_status == + BLK_STS_TARGET && + test_bit(R1BIO_P2PDMA, &r1_bio->state); + fail = true; - narrow_write_error(r1_bio, m); + narrow_write_error(r1_bio, m, coarse); rdev_dec_pending(conf->mirrors[m].rdev, conf->mddev); } @@ -2661,6 +2681,9 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio) { struct md_rdev *rdev = conf->mirrors[r1_bio->read_disk].rdev; struct bio *bio = r1_bio->bios[r1_bio->read_disk]; + /* evaluate before the bio_put() below */ + bool p2pdma_error = bio->bi_status == BLK_STS_TARGET && + test_bit(R1BIO_P2PDMA, &r1_bio->state); struct mddev *mddev = conf->mddev; sector_t sector; @@ -2680,6 +2703,9 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio) */ if (mddev->ro) { r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED; + } else if (p2pdma_error) { + /* Peer can't reach this member: just redirect the read. */ + r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED; } else if (test_bit(FailFast, &rdev->flags)) { md_error(mddev, rdev); } else { diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h index c98d43a7ae99..61b788a99d14 100644 --- a/drivers/md/raid1.h +++ b/drivers/md/raid1.h @@ -184,6 +184,8 @@ enum r1bio_state { R1BIO_MadeGood, R1BIO_WriteError, R1BIO_FailFast, +/* the master bio carries PCI P2PDMA (peer device memory) pages */ + R1BIO_P2PDMA, }; static inline int sector_to_idx(sector_t sector) -- 2.52.0