From a15b60a21c12a15519d55b772a41d7710e200b49 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Thu, 18 Jul 2002 19:08:13 -0700 Subject: [PATCH] [PATCH] MD - Pass the correct bdev to md_error Pass the correct bdev to md_error After a call to generic_make_request, bio->bi_bdev can have changed (e.g. by a re-mapped like raid0). So we cannot trust it for reporting the source of an error. This patch takes care to find the correct bdev. --- drivers/md/multipath.c | 12 +++++++---- drivers/md/raid1.c | 39 ++++++++++++++++++---------------- drivers/md/raid5.c | 4 ++-- include/linux/raid/multipath.h | 1 + 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 7c3c1f4fb60b..7f6dd3ed27ae 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -128,7 +128,8 @@ void multipath_end_request(struct bio *bio) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct multipath_bh * mp_bh = (struct multipath_bh *)(bio->bi_private); - + multipath_conf_t *conf; + struct block_device *bdev; if (uptodate) { multipath_end_bh_io(mp_bh, uptodate); return; @@ -136,9 +137,11 @@ void multipath_end_request(struct bio *bio) /* * oops, IO error: */ - md_error (mp_bh->mddev, bio->bi_bdev); + conf = mddev_to_conf(mp_bh->mddev); + bdev = conf->multipaths[mp_bh->path].bdev; + md_error (mp_bh->mddev, bdev); printk(KERN_ERR "multipath: %s: rescheduling sector %lu\n", - bdev_partition_name(bio->bi_bdev), bio->bi_sector); + bdev_partition_name(bdev), bio->bi_sector); multipath_reschedule_retry(mp_bh); return; } @@ -174,7 +177,8 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio) /* * read balancing logic: */ - multipath = conf->multipaths + multipath_read_balance(conf); + mp_bh->path = multipath_read_balance(conf); + multipath = conf->multipaths + mp_bh->path; mp_bh->bio = *bio; mp_bh->bio.bi_bdev = multipath->bdev; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index caf5cd626095..05276fdf73a5 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -251,13 +251,21 @@ static void end_request(struct bio *bio) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); - int i; - + int mirror; + conf_t *conf = mddev_to_conf(r1_bio->mddev); + + if (r1_bio->cmd == READ || r1_bio->cmd == READA) + mirror = r1_bio->read_disk; + else { + for (mirror = 0; mirror < MD_SB_DISKS; mirror++) + if (r1_bio->write_bios[mirror] == bio) + break; + } /* * this branch is our 'one mirror IO has finished' event handler: */ if (!uptodate) - md_error(r1_bio->mddev, bio->bi_bdev); + md_error(r1_bio->mddev, conf->mirrors[mirror].bdev); else /* * Set R1BIO_Uptodate in our master bio, so that @@ -270,10 +278,10 @@ static void end_request(struct bio *bio) */ set_bit(R1BIO_Uptodate, &r1_bio->state); + update_head_pos(mirror, r1_bio); if ((r1_bio->cmd == READ) || (r1_bio->cmd == READA)) { if (!r1_bio->read_bio) BUG(); - update_head_pos(r1_bio->read_disk, r1_bio); /* * we have only one bio on the read side */ @@ -295,14 +303,6 @@ static void end_request(struct bio *bio) /* * WRITE: * - * First, find the disk this bio belongs to. - */ - for (i = 0; i < MD_SB_DISKS; i++) - if (r1_bio->write_bios[i] == bio) { - update_head_pos(i, r1_bio); - break; - } - /* * Let's see if all mirrored write operations have finished * already. */ @@ -911,6 +911,7 @@ static void end_sync_read(struct bio *bio) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); + conf_t *conf = mddev_to_conf(r1_bio->mddev); if (r1_bio->read_bio != bio) BUG(); @@ -921,7 +922,8 @@ static void end_sync_read(struct bio *bio) * We don't do much here, just schedule handling by raid1d */ if (!uptodate) - md_error (r1_bio->mddev, bio->bi_bdev); + md_error(r1_bio->mddev, + conf->mirrors[r1_bio->read_disk].bdev); else set_bit(R1BIO_Uptodate, &r1_bio->state); reschedule_retry(r1_bio); @@ -932,19 +934,20 @@ static void end_sync_write(struct bio *bio) int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); mddev_t *mddev = r1_bio->mddev; + conf_t *conf = mddev_to_conf(mddev); int i; - - if (!uptodate) - md_error(mddev, bio->bi_bdev); + int mirror=0; for (i = 0; i < MD_SB_DISKS; i++) if (r1_bio->write_bios[i] == bio) { - update_head_pos(i, r1_bio); + mirror = i; break; } + if (!uptodate) + md_error(mddev, conf->mirrors[mirror].bdev); + update_head_pos(mirror, r1_bio); if (atomic_dec_and_test(&r1_bio->remaining)) { - conf_t *conf = mddev_to_conf(mddev); md_done_sync(mddev, r1_bio->master_bio->bi_size >> 9, uptodate); resume_device(conf); put_buf(r1_bio); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 5d0af20344cc..44562157133b 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -371,7 +371,7 @@ static void raid5_end_read_request (struct bio * bi) set_bit(R5_UPTODATE, &sh->dev[i].flags); #endif } else { - md_error(conf->mddev, bi->bi_bdev); + md_error(conf->mddev, conf->disks[i].bdev); clear_bit(R5_UPTODATE, &sh->dev[i].flags); } #if 0 @@ -407,7 +407,7 @@ static void raid5_end_write_request (struct bio *bi) spin_lock_irqsave(&conf->device_lock, flags); if (!uptodate) - md_error(conf->mddev, bi->bi_bdev); + md_error(conf->mddev, conf->disks[i].bdev); clear_bit(R5_LOCKED, &sh->dev[i].flags); set_bit(STRIPE_HANDLE, &sh->state); diff --git a/include/linux/raid/multipath.h b/include/linux/raid/multipath.h index 886448c201fc..bd245bbcd845 100644 --- a/include/linux/raid/multipath.h +++ b/include/linux/raid/multipath.h @@ -48,6 +48,7 @@ struct multipath_bh { mddev_t *mddev; struct bio *master_bio; struct bio bio; + int path; struct multipath_bh *next_mp; /* next for retry */ }; #endif -- 2.39.5