Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
[powerpc.git] / drivers / md / raid1.c
index feea4ee..5d88329 100644 (file)
@@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r1bio_t *r1_bio)
        }
 }
 
-static inline void free_r1bio(r1bio_t *r1_bio)
+static void free_r1bio(r1bio_t *r1_bio)
 {
        conf_t *conf = mddev_to_conf(r1_bio->mddev);
 
@@ -190,7 +190,7 @@ static inline void free_r1bio(r1bio_t *r1_bio)
        mempool_free(r1_bio, conf->r1bio_pool);
 }
 
-static inline void put_buf(r1bio_t *r1_bio)
+static void put_buf(r1bio_t *r1_bio)
 {
        conf_t *conf = mddev_to_conf(r1_bio->mddev);
        int i;
@@ -306,6 +306,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
        r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
        int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
        conf_t *conf = mddev_to_conf(r1_bio->mddev);
+       struct bio *to_put = NULL;
 
        if (bio->bi_size)
                return 1;
@@ -323,6 +324,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
                 * this branch is our 'one mirror IO has finished' event handler:
                 */
                r1_bio->bios[mirror] = NULL;
+               to_put = bio;
                if (!uptodate) {
                        md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
                        /* an I/O failed, we can't clear the bitmap */
@@ -375,7 +377,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
                        /* Don't dec_pending yet, we want to hold
                         * the reference over the retry
                         */
-                       return 0;
+                       goto out;
                }
                if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
                        /* free extra copy of the data pages */
@@ -392,10 +394,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
                raid_end_bio_io(r1_bio);
        }
 
-       if (r1_bio->bios[mirror]==NULL)
-               bio_put(bio);
-
        rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
+ out:
+       if (to_put)
+               bio_put(to_put);
+
        return 0;
 }
 
@@ -527,7 +530,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
                        /* cannot risk returning a device that failed
                         * before we inc'ed nr_pending
                         */
-                       atomic_dec(&rdev->nr_pending);
+                       rdev_dec_pending(rdev, conf->mddev);
                        goto retry;
                }
                conf->next_seq_sect = this_sector + sectors;
@@ -830,7 +833,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
                    !test_bit(Faulty, &rdev->flags)) {
                        atomic_inc(&rdev->nr_pending);
                        if (test_bit(Faulty, &rdev->flags)) {
-                               atomic_dec(&rdev->nr_pending);
+                               rdev_dec_pending(rdev, mddev);
                                r1_bio->bios[i] = NULL;
                        } else
                                r1_bio->bios[i] = bio;
@@ -857,7 +860,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
        atomic_set(&r1_bio->remaining, 0);
        atomic_set(&r1_bio->behind_remaining, 0);
 
-       do_barriers = bio->bi_rw & BIO_RW_BARRIER;
+       do_barriers = bio_barrier(bio);
        if (do_barriers)
                set_bit(R1BIO_Barrier, &r1_bio->state);
 
@@ -1176,6 +1179,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
                        if (r1_bio->bios[primary]->bi_end_io == end_sync_read &&
                            test_bit(BIO_UPTODATE, &r1_bio->bios[primary]->bi_flags)) {
                                r1_bio->bios[primary]->bi_end_io = NULL;
+                               rdev_dec_pending(conf->mirrors[primary].rdev, mddev);
                                break;
                        }
                r1_bio->read_disk = primary;
@@ -1193,9 +1197,10 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
                                                break;
                                if (j >= 0)
                                        mddev->resync_mismatches += r1_bio->sectors;
-                               if (j < 0 || test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
+                               if (j < 0 || test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) {
                                        sbio->bi_end_io = NULL;
-                               else {
+                                       rdev_dec_pending(conf->mirrors[i].rdev, mddev);
+                               } else {
                                        /* fixup the bio for reuse */
                                        sbio->bi_vcnt = vcnt;
                                        sbio->bi_size = r1_bio->sectors << 9;
@@ -1263,6 +1268,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
                                        if (r1_bio->bios[d]->bi_end_io != end_sync_read)
                                                continue;
                                        rdev = conf->mirrors[d].rdev;
+                                       atomic_add(s, &rdev->corrected_errors);
                                        if (sync_page_io(rdev->bdev,
                                                         sect + rdev->data_offset,
                                                         s<<9,
@@ -1461,6 +1467,7 @@ static void raid1d(mddev_t *mddev)
                                                        d = conf->raid_disks;
                                                d--;
                                                rdev = conf->mirrors[d].rdev;
+                                               atomic_add(s, &rdev->corrected_errors);
                                                if (rdev &&
                                                    test_bit(In_sync, &rdev->flags)) {
                                                        if (sync_page_io(rdev->bdev,
@@ -2090,4 +2097,5 @@ module_init(raid_init);
 module_exit(raid_exit);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-3"); /* RAID1 */
+MODULE_ALIAS("md-raid1");
 MODULE_ALIAS("md-level-1");