Merge branch 'mymd/for-next' into mymd/for-linus
[cascardo/linux.git] / drivers / md / raid1.c
index 4e6da44..46168ef 100644 (file)
@@ -319,14 +319,13 @@ static void raid1_end_read_request(struct bio *bio)
 {
        int uptodate = !bio->bi_error;
        struct r1bio *r1_bio = bio->bi_private;
-       int mirror;
        struct r1conf *conf = r1_bio->mddev->private;
+       struct md_rdev *rdev = conf->mirrors[r1_bio->read_disk].rdev;
 
-       mirror = r1_bio->read_disk;
        /*
         * this branch is our 'one mirror IO has finished' event handler:
         */
-       update_head_pos(mirror, r1_bio);
+       update_head_pos(r1_bio->read_disk, r1_bio);
 
        if (uptodate)
                set_bit(R1BIO_Uptodate, &r1_bio->state);
@@ -339,14 +338,14 @@ static void raid1_end_read_request(struct bio *bio)
                spin_lock_irqsave(&conf->device_lock, flags);
                if (r1_bio->mddev->degraded == conf->raid_disks ||
                    (r1_bio->mddev->degraded == conf->raid_disks-1 &&
-                    test_bit(In_sync, &conf->mirrors[mirror].rdev->flags)))
+                    test_bit(In_sync, &rdev->flags)))
                        uptodate = 1;
                spin_unlock_irqrestore(&conf->device_lock, flags);
        }
 
        if (uptodate) {
                raid_end_bio_io(r1_bio);
-               rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
+               rdev_dec_pending(rdev, conf->mddev);
        } else {
                /*
                 * oops, read error:
@@ -356,7 +355,7 @@ static void raid1_end_read_request(struct bio *bio)
                        KERN_ERR "md/raid1:%s: %s: "
                        "rescheduling sector %llu\n",
                        mdname(conf->mddev),
-                       bdevname(conf->mirrors[mirror].rdev->bdev,
+                       bdevname(rdev->bdev,
                                 b),
                        (unsigned long long)r1_bio->sector);
                set_bit(R1BIO_ReadError, &r1_bio->state);
@@ -403,20 +402,18 @@ static void r1_bio_write_done(struct r1bio *r1_bio)
 static void raid1_end_write_request(struct bio *bio)
 {
        struct r1bio *r1_bio = bio->bi_private;
-       int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
+       int behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
        struct r1conf *conf = r1_bio->mddev->private;
        struct bio *to_put = NULL;
-
-       mirror = find_bio_disk(r1_bio, bio);
+       int mirror = find_bio_disk(r1_bio, bio);
+       struct md_rdev *rdev = conf->mirrors[mirror].rdev;
 
        /*
         * 'one mirror IO has finished' event handler:
         */
        if (bio->bi_error) {
-               set_bit(WriteErrorSeen,
-                       &conf->mirrors[mirror].rdev->flags);
-               if (!test_and_set_bit(WantReplacement,
-                                     &conf->mirrors[mirror].rdev->flags))
+               set_bit(WriteErrorSeen, &rdev->flags);
+               if (!test_and_set_bit(WantReplacement, &rdev->flags))
                        set_bit(MD_RECOVERY_NEEDED, &
                                conf->mddev->recovery);
 
@@ -445,13 +442,12 @@ static void raid1_end_write_request(struct bio *bio)
                 * before rdev->recovery_offset, but for simplicity we don't
                 * check this here.
                 */
-               if (test_bit(In_sync, &conf->mirrors[mirror].rdev->flags) &&
-                   !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags))
+               if (test_bit(In_sync, &rdev->flags) &&
+                   !test_bit(Faulty, &rdev->flags))
                        set_bit(R1BIO_Uptodate, &r1_bio->state);
 
                /* Maybe we can clear some bad blocks. */
-               if (is_badblock(conf->mirrors[mirror].rdev,
-                               r1_bio->sector, r1_bio->sectors,
+               if (is_badblock(rdev, r1_bio->sector, r1_bio->sectors,
                                &first_bad, &bad_sectors)) {
                        r1_bio->bios[mirror] = IO_MADE_GOOD;
                        set_bit(R1BIO_MadeGood, &r1_bio->state);
@@ -459,7 +455,7 @@ static void raid1_end_write_request(struct bio *bio)
        }
 
        if (behind) {
-               if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags))
+               if (test_bit(WriteMostly, &rdev->flags))
                        atomic_dec(&r1_bio->behind_remaining);
 
                /*
@@ -483,8 +479,7 @@ static void raid1_end_write_request(struct bio *bio)
                }
        }
        if (r1_bio->bios[mirror] == NULL)
-               rdev_dec_pending(conf->mirrors[mirror].rdev,
-                                conf->mddev);
+               rdev_dec_pending(rdev, conf->mddev);
 
        /*
         * Let's see if all mirrored write operations have finished
@@ -689,13 +684,6 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
                if (!rdev)
                        goto retry;
                atomic_inc(&rdev->nr_pending);
-               if (test_bit(Faulty, &rdev->flags)) {
-                       /* cannot risk returning a device that failed
-                        * before we inc'ed nr_pending
-                        */
-                       rdev_dec_pending(rdev, conf->mddev);
-                       goto retry;
-               }
                sectors = best_good_sectors;
 
                if (conf->mirrors[best_disk].next_seq_sect != this_sector)
@@ -1666,13 +1654,16 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
                        goto abort;
                }
                p->rdev = NULL;
-               synchronize_rcu();
-               if (atomic_read(&rdev->nr_pending)) {
-                       /* lost the race, try later */
-                       err = -EBUSY;
-                       p->rdev = rdev;
-                       goto abort;
-               } else if (conf->mirrors[conf->raid_disks + number].rdev) {
+               if (!test_bit(RemoveSynchronized, &rdev->flags)) {
+                       synchronize_rcu();
+                       if (atomic_read(&rdev->nr_pending)) {
+                               /* lost the race, try later */
+                               err = -EBUSY;
+                               p->rdev = rdev;
+                               goto abort;
+                       }
+               }
+               if (conf->mirrors[conf->raid_disks + number].rdev) {
                        /* We just removed a device that is being replaced.
                         * Move down the replacement.  We drain all IO before
                         * doing this to avoid confusion.
@@ -1719,11 +1710,9 @@ static void end_sync_write(struct bio *bio)
        struct r1bio *r1_bio = bio->bi_private;
        struct mddev *mddev = r1_bio->mddev;
        struct r1conf *conf = mddev->private;
-       int mirror=0;
        sector_t first_bad;
        int bad_sectors;
-
-       mirror = find_bio_disk(r1_bio, bio);
+       struct md_rdev *rdev = conf->mirrors[find_bio_disk(r1_bio, bio)].rdev;
 
        if (!uptodate) {
                sector_t sync_blocks = 0;
@@ -1736,16 +1725,12 @@ static void end_sync_write(struct bio *bio)
                        s += sync_blocks;
                        sectors_to_go -= sync_blocks;
                } while (sectors_to_go > 0);
-               set_bit(WriteErrorSeen,
-                       &conf->mirrors[mirror].rdev->flags);
-               if (!test_and_set_bit(WantReplacement,
-                                     &conf->mirrors[mirror].rdev->flags))
+               set_bit(WriteErrorSeen, &rdev->flags);
+               if (!test_and_set_bit(WantReplacement, &rdev->flags))
                        set_bit(MD_RECOVERY_NEEDED, &
                                mddev->recovery);
                set_bit(R1BIO_WriteError, &r1_bio->state);
-       } else if (is_badblock(conf->mirrors[mirror].rdev,
-                              r1_bio->sector,
-                              r1_bio->sectors,
+       } else if (is_badblock(rdev, r1_bio->sector, r1_bio->sectors,
                               &first_bad, &bad_sectors) &&
                   !is_badblock(conf->mirrors[r1_bio->read_disk].rdev,
                                r1_bio->sector,
@@ -2072,29 +2057,30 @@ static void fix_read_error(struct r1conf *conf, int read_disk,
                        s = PAGE_SIZE >> 9;
 
                do {
-                       /* Note: no rcu protection needed here
-                        * as this is synchronous in the raid1d thread
-                        * which is the thread that might remove
-                        * a device.  If raid1d ever becomes multi-threaded....
-                        */
                        sector_t first_bad;
                        int bad_sectors;
 
-                       rdev = conf->mirrors[d].rdev;
+                       rcu_read_lock();
+                       rdev = rcu_dereference(conf->mirrors[d].rdev);
                        if (rdev &&
                            (test_bit(In_sync, &rdev->flags) ||
                             (!test_bit(Faulty, &rdev->flags) &&
                              rdev->recovery_offset >= sect + s)) &&
                            is_badblock(rdev, sect, s,
-                                       &first_bad, &bad_sectors) == 0 &&
-                           sync_page_io(rdev, sect, s<<9,
+                                       &first_bad, &bad_sectors) == 0) {
+                               atomic_inc(&rdev->nr_pending);
+                               rcu_read_unlock();
+                               if (sync_page_io(rdev, sect, s<<9,
                                         conf->tmppage, REQ_OP_READ, 0, false))
-                               success = 1;
-                       else {
-                               d++;
-                               if (d == conf->raid_disks * 2)
-                                       d = 0;
-                       }
+                                       success = 1;
+                               rdev_dec_pending(rdev, mddev);
+                               if (success)
+                                       break;
+                       } else
+                               rcu_read_unlock();
+                       d++;
+                       if (d == conf->raid_disks * 2)
+                               d = 0;
                } while (!success && d != read_disk);
 
                if (!success) {
@@ -2110,11 +2096,17 @@ static void fix_read_error(struct r1conf *conf, int read_disk,
                        if (d==0)
                                d = conf->raid_disks * 2;
                        d--;
-                       rdev = conf->mirrors[d].rdev;
+                       rcu_read_lock();
+                       rdev = rcu_dereference(conf->mirrors[d].rdev);
                        if (rdev &&
-                           !test_bit(Faulty, &rdev->flags))
+                           !test_bit(Faulty, &rdev->flags)) {
+                               atomic_inc(&rdev->nr_pending);
+                               rcu_read_unlock();
                                r1_sync_page_io(rdev, sect, s,
                                                conf->tmppage, WRITE);
+                               rdev_dec_pending(rdev, mddev);
+                       } else
+                               rcu_read_unlock();
                }
                d = start;
                while (d != read_disk) {
@@ -2122,9 +2114,12 @@ static void fix_read_error(struct r1conf *conf, int read_disk,
                        if (d==0)
                                d = conf->raid_disks * 2;
                        d--;
-                       rdev = conf->mirrors[d].rdev;
+                       rcu_read_lock();
+                       rdev = rcu_dereference(conf->mirrors[d].rdev);
                        if (rdev &&
                            !test_bit(Faulty, &rdev->flags)) {
+                               atomic_inc(&rdev->nr_pending);
+                               rcu_read_unlock();
                                if (r1_sync_page_io(rdev, sect, s,
                                                    conf->tmppage, READ)) {
                                        atomic_add(s, &rdev->corrected_errors);
@@ -2133,10 +2128,12 @@ static void fix_read_error(struct r1conf *conf, int read_disk,
                                               "(%d sectors at %llu on %s)\n",
                                               mdname(mddev), s,
                                               (unsigned long long)(sect +
-                                                  rdev->data_offset),
+                                                                   rdev->data_offset),
                                               bdevname(rdev->bdev, b));
                                }
-                       }
+                               rdev_dec_pending(rdev, mddev);
+                       } else
+                               rcu_read_unlock();
                }
                sectors -= s;
                sect += s;
@@ -2534,6 +2531,13 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
                return sync_blocks;
        }
 
+       /*
+        * If there is non-resync activity waiting for a turn, then let it
+        * though before starting on this new sync request.
+        */
+       if (conf->nr_waiting)
+               schedule_timeout_uninterruptible(1);
+
        /* we are incrementing sector_nr below. To be safe, we check against
         * sector_nr + two times RESYNC_SECTORS
         */