Commit a15b60a2 authored by Neil Brown's avatar Neil Brown Committed by Trond Myklebust

[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.
parent 2a9400e9
...@@ -128,7 +128,8 @@ void multipath_end_request(struct bio *bio) ...@@ -128,7 +128,8 @@ void multipath_end_request(struct bio *bio)
{ {
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
struct multipath_bh * mp_bh = (struct multipath_bh *)(bio->bi_private); struct multipath_bh * mp_bh = (struct multipath_bh *)(bio->bi_private);
multipath_conf_t *conf;
struct block_device *bdev;
if (uptodate) { if (uptodate) {
multipath_end_bh_io(mp_bh, uptodate); multipath_end_bh_io(mp_bh, uptodate);
return; return;
...@@ -136,9 +137,11 @@ void multipath_end_request(struct bio *bio) ...@@ -136,9 +137,11 @@ void multipath_end_request(struct bio *bio)
/* /*
* oops, IO error: * 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", 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); multipath_reschedule_retry(mp_bh);
return; return;
} }
...@@ -174,7 +177,8 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio) ...@@ -174,7 +177,8 @@ static int multipath_make_request (request_queue_t *q, struct bio * bio)
/* /*
* read balancing logic: * 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 = *bio;
mp_bh->bio.bi_bdev = multipath->bdev; mp_bh->bio.bi_bdev = multipath->bdev;
......
...@@ -251,13 +251,21 @@ static void end_request(struct bio *bio) ...@@ -251,13 +251,21 @@ static void end_request(struct bio *bio)
{ {
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); 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: * this branch is our 'one mirror IO has finished' event handler:
*/ */
if (!uptodate) if (!uptodate)
md_error(r1_bio->mddev, bio->bi_bdev); md_error(r1_bio->mddev, conf->mirrors[mirror].bdev);
else else
/* /*
* Set R1BIO_Uptodate in our master bio, so that * Set R1BIO_Uptodate in our master bio, so that
...@@ -270,10 +278,10 @@ static void end_request(struct bio *bio) ...@@ -270,10 +278,10 @@ static void end_request(struct bio *bio)
*/ */
set_bit(R1BIO_Uptodate, &r1_bio->state); 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->cmd == READ) || (r1_bio->cmd == READA)) {
if (!r1_bio->read_bio) if (!r1_bio->read_bio)
BUG(); BUG();
update_head_pos(r1_bio->read_disk, r1_bio);
/* /*
* we have only one bio on the read side * we have only one bio on the read side
*/ */
...@@ -295,14 +303,6 @@ static void end_request(struct bio *bio) ...@@ -295,14 +303,6 @@ static void end_request(struct bio *bio)
/* /*
* WRITE: * 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 * Let's see if all mirrored write operations have finished
* already. * already.
*/ */
...@@ -911,6 +911,7 @@ static void end_sync_read(struct bio *bio) ...@@ -911,6 +911,7 @@ static void end_sync_read(struct bio *bio)
{ {
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
conf_t *conf = mddev_to_conf(r1_bio->mddev);
if (r1_bio->read_bio != bio) if (r1_bio->read_bio != bio)
BUG(); BUG();
...@@ -921,7 +922,8 @@ static void end_sync_read(struct bio *bio) ...@@ -921,7 +922,8 @@ static void end_sync_read(struct bio *bio)
* We don't do much here, just schedule handling by raid1d * We don't do much here, just schedule handling by raid1d
*/ */
if (!uptodate) if (!uptodate)
md_error (r1_bio->mddev, bio->bi_bdev); md_error(r1_bio->mddev,
conf->mirrors[r1_bio->read_disk].bdev);
else else
set_bit(R1BIO_Uptodate, &r1_bio->state); set_bit(R1BIO_Uptodate, &r1_bio->state);
reschedule_retry(r1_bio); reschedule_retry(r1_bio);
...@@ -932,19 +934,20 @@ static void end_sync_write(struct bio *bio) ...@@ -932,19 +934,20 @@ static void end_sync_write(struct bio *bio)
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
mddev_t *mddev = r1_bio->mddev; mddev_t *mddev = r1_bio->mddev;
conf_t *conf = mddev_to_conf(mddev);
int i; int i;
int mirror=0;
if (!uptodate)
md_error(mddev, bio->bi_bdev);
for (i = 0; i < MD_SB_DISKS; i++) for (i = 0; i < MD_SB_DISKS; i++)
if (r1_bio->write_bios[i] == bio) { if (r1_bio->write_bios[i] == bio) {
update_head_pos(i, r1_bio); mirror = i;
break; break;
} }
if (!uptodate)
md_error(mddev, conf->mirrors[mirror].bdev);
update_head_pos(mirror, r1_bio);
if (atomic_dec_and_test(&r1_bio->remaining)) { 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); md_done_sync(mddev, r1_bio->master_bio->bi_size >> 9, uptodate);
resume_device(conf); resume_device(conf);
put_buf(r1_bio); put_buf(r1_bio);
......
...@@ -371,7 +371,7 @@ static void raid5_end_read_request (struct bio * bi) ...@@ -371,7 +371,7 @@ static void raid5_end_read_request (struct bio * bi)
set_bit(R5_UPTODATE, &sh->dev[i].flags); set_bit(R5_UPTODATE, &sh->dev[i].flags);
#endif #endif
} else { } else {
md_error(conf->mddev, bi->bi_bdev); md_error(conf->mddev, conf->disks[i].bdev);
clear_bit(R5_UPTODATE, &sh->dev[i].flags); clear_bit(R5_UPTODATE, &sh->dev[i].flags);
} }
#if 0 #if 0
...@@ -407,7 +407,7 @@ static void raid5_end_write_request (struct bio *bi) ...@@ -407,7 +407,7 @@ static void raid5_end_write_request (struct bio *bi)
spin_lock_irqsave(&conf->device_lock, flags); spin_lock_irqsave(&conf->device_lock, flags);
if (!uptodate) 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); clear_bit(R5_LOCKED, &sh->dev[i].flags);
set_bit(STRIPE_HANDLE, &sh->state); set_bit(STRIPE_HANDLE, &sh->state);
......
...@@ -48,6 +48,7 @@ struct multipath_bh { ...@@ -48,6 +48,7 @@ struct multipath_bh {
mddev_t *mddev; mddev_t *mddev;
struct bio *master_bio; struct bio *master_bio;
struct bio bio; struct bio bio;
int path;
struct multipath_bh *next_mp; /* next for retry */ struct multipath_bh *next_mp; /* next for retry */
}; };
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment