]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/md/raid10.c
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6-omap-h63xx.git] / drivers / md / raid10.c
index f23d52c5df9420280dd252c344c2368fd1ec2d18..ab90a6d1202043f7d332fe5f613be414845f1107 100644 (file)
@@ -132,10 +132,10 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
 
 out_free_pages:
        for ( ; i > 0 ; i--)
-               put_page(bio->bi_io_vec[i-1].bv_page);
+               safe_put_page(bio->bi_io_vec[i-1].bv_page);
        while (j--)
                for (i = 0; i < RESYNC_PAGES ; i++)
-                       put_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
+                       safe_put_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page);
        j = -1;
 out_free_bio:
        while ( ++j < nalloc )
@@ -155,7 +155,7 @@ static void r10buf_pool_free(void *__r10_bio, void *data)
                struct bio *bio = r10bio->devs[j].bio;
                if (bio) {
                        for (i = 0; i < RESYNC_PAGES; i++) {
-                               put_page(bio->bi_io_vec[i].bv_page);
+                               safe_put_page(bio->bi_io_vec[i].bv_page);
                                bio->bi_io_vec[i].bv_page = NULL;
                        }
                        bio_put(bio);
@@ -176,7 +176,7 @@ static void put_all_bios(conf_t *conf, r10bio_t *r10_bio)
        }
 }
 
-static inline void free_r10bio(r10bio_t *r10_bio)
+static void free_r10bio(r10bio_t *r10_bio)
 {
        conf_t *conf = mddev_to_conf(r10_bio->mddev);
 
@@ -190,7 +190,7 @@ static inline void free_r10bio(r10bio_t *r10_bio)
        mempool_free(r10_bio, conf->r10bio_pool);
 }
 
-static inline void put_buf(r10bio_t *r10_bio)
+static void put_buf(r10bio_t *r10_bio)
 {
        conf_t *conf = mddev_to_conf(r10_bio->mddev);
 
@@ -565,6 +565,8 @@ rb_out:
 
        if (disk >= 0 && (rdev=rcu_dereference(conf->mirrors[disk].rdev))!= NULL)
                atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
+       else
+               disk = -1;
        rcu_read_unlock();
 
        return disk;
@@ -712,7 +714,7 @@ static void allow_barrier(conf_t *conf)
 static void freeze_array(conf_t *conf)
 {
        /* stop syncio and normal IO and wait for everything to
-        * go quite.
+        * go quiet.
         * We increment barrier and nr_waiting, and then
         * wait until barrier+nr_pending match nr_queued+2
         */
@@ -1122,9 +1124,13 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
 
        if (test_bit(BIO_UPTODATE, &bio->bi_flags))
                set_bit(R10BIO_Uptodate, &r10_bio->state);
-       else if (!test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
-               md_error(r10_bio->mddev,
-                        conf->mirrors[d].rdev);
+       else {
+               atomic_add(r10_bio->sectors,
+                          &conf->mirrors[d].rdev->corrected_errors);
+               if (!test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
+                       md_error(r10_bio->mddev,
+                                conf->mirrors[d].rdev);
+       }
 
        /* for reconstruct, we always reschedule after a read.
         * for resync, only after all reads
@@ -1421,6 +1427,7 @@ static void raid10d(mddev_t *mddev)
                                } while (!success && sl != r10_bio->read_slot);
 
                                if (success) {
+                                       int start = sl;
                                        /* write it back and re-read */
                                        while (sl != r10_bio->read_slot) {
                                                int d;
@@ -1429,19 +1436,33 @@ static void raid10d(mddev_t *mddev)
                                                sl--;
                                                d = r10_bio->devs[sl].devnum;
                                                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,
                                                                         r10_bio->devs[sl].addr +
                                                                         sect + rdev->data_offset,
-                                                                        s<<9, conf->tmppage, WRITE) == 0 ||
-                                                           sync_page_io(rdev->bdev,
+                                                                        s<<9, conf->tmppage, WRITE) == 0)
+                                                               /* Well, this device is dead */
+                                                               md_error(mddev, rdev);
+                                               }
+                                       }
+                                       sl = start;
+                                       while (sl != r10_bio->read_slot) {
+                                               int d;
+                                               if (sl==0)
+                                                       sl = conf->copies;
+                                               sl--;
+                                               d = r10_bio->devs[sl].devnum;
+                                               rdev = conf->mirrors[d].rdev;
+                                               if (rdev &&
+                                                   test_bit(In_sync, &rdev->flags)) {
+                                                       if (sync_page_io(rdev->bdev,
                                                                         r10_bio->devs[sl].addr +
                                                                         sect + rdev->data_offset,
-                                                                        s<<9, conf->tmppage, READ) == 0) {
+                                                                        s<<9, conf->tmppage, READ) == 0)
                                                                /* Well, this device is dead */
                                                                md_error(mddev, rdev);
-                                                       }
                                                }
                                        }
                                } else {
@@ -2028,7 +2049,7 @@ static int run(mddev_t *mddev)
 out_free_conf:
        if (conf->r10bio_pool)
                mempool_destroy(conf->r10bio_pool);
-       put_page(conf->tmppage);
+       safe_put_page(conf->tmppage);
        kfree(conf->mirrors);
        kfree(conf);
        mddev->private = NULL;
@@ -2103,4 +2124,5 @@ module_init(raid_init);
 module_exit(raid_exit);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-9"); /* RAID10 */
+MODULE_ALIAS("md-raid10");
 MODULE_ALIAS("md-level-10");