]> git.hungrycats.org Git - linux/commitdiff
[PATCH] MD - Pass the correct bdev to md_error
authorNeil Brown <neilb@cse.unsw.edu.au>
Fri, 19 Jul 2002 02:08:13 +0000 (19:08 -0700)
committerTrond Myklebust <trond.myklebust@fys.uio.no>
Fri, 19 Jul 2002 02:08:13 +0000 (19:08 -0700)
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
drivers/md/raid1.c
drivers/md/raid5.c
include/linux/raid/multipath.h

index 7c3c1f4fb60b51b7bb4dacd2fb6c6ab64b15c2dc..7f6dd3ed27aec1e48f9a441b1042ceedd7011bc3 100644 (file)
@@ -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;
index caf5cd626095320acfbeb53e9e71e9673636c4b6..05276fdf73a55553b22dcf2506e22385c66f5ff8 100644 (file)
@@ -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);
index 5d0af20344cccb7647a0d1636c33c53613c25446..44562157133b3360a4cb5d481e3ffd19531ccd53 100644 (file)
@@ -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);
index 886448c201fc01bc7315c7ca8ed23c23a8b67adc..bd245bbcd845009d016c3b32e9ff8d1e326c0b35 100644 (file)
@@ -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