Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[sfrench/cifs-2.6.git] / drivers / md / raid1.c
index 9b374c91db66caf8755d36df304a37f7e0bca482..cead918578a7dc6e8ebbe212eb46aec9fdd82c22 100644 (file)
@@ -315,10 +315,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
                if (r1_bio->bios[mirror] == bio)
                        break;
 
-       if (error == -ENOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) {
+       if (error == -EOPNOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) {
                set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags);
                set_bit(R1BIO_BarrierRetry, &r1_bio->state);
                r1_bio->mddev->barriers_work = 0;
+               /* Don't rdev_dec_pending in this branch - keep it for the retry */
        } else {
                /*
                 * this branch is our 'one mirror IO has finished' event handler:
@@ -365,6 +366,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
                                }
                        }
                }
+               rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
        }
        /*
         *
@@ -372,30 +374,26 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
         * already.
         */
        if (atomic_dec_and_test(&r1_bio->remaining)) {
-               if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) {
+               if (test_bit(R1BIO_BarrierRetry, &r1_bio->state))
                        reschedule_retry(r1_bio);
-                       /* Don't dec_pending yet, we want to hold
-                        * the reference over the retry
-                        */
-                       goto out;
-               }
-               if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
-                       /* free extra copy of the data pages */
-                       int i = bio->bi_vcnt;
-                       while (i--)
-                               safe_put_page(bio->bi_io_vec[i].bv_page);
+               else {
+                       /* it really is the end of this request */
+                       if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
+                               /* free extra copy of the data pages */
+                               int i = bio->bi_vcnt;
+                               while (i--)
+                                       safe_put_page(bio->bi_io_vec[i].bv_page);
+                       }
+                       /* clear the bitmap if all writes complete successfully */
+                       bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
+                                       r1_bio->sectors,
+                                       !test_bit(R1BIO_Degraded, &r1_bio->state),
+                                       behind);
+                       md_write_end(r1_bio->mddev);
+                       raid_end_bio_io(r1_bio);
                }
-               /* clear the bitmap if all writes complete successfully */
-               bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
-                               r1_bio->sectors,
-                               !test_bit(R1BIO_Degraded, &r1_bio->state),
-                               behind);
-               md_write_end(r1_bio->mddev);
-               raid_end_bio_io(r1_bio);
        }
 
-       rdev_dec_pending(conf->mirrors[mirror].rdev, conf->mddev);
- out:
        if (to_put)
                bio_put(to_put);
 
@@ -753,18 +751,24 @@ static int make_request(request_queue_t *q, struct bio * bio)
        const int rw = bio_data_dir(bio);
        int do_barriers;
 
-       if (unlikely(!mddev->barriers_work && bio_barrier(bio))) {
-               bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
-               return 0;
-       }
-
        /*
         * Register the new request and wait if the reconstruction
         * thread has put up a bar for new requests.
         * Continue immediately if no resync is active currently.
+        * We test barriers_work *after* md_write_start as md_write_start
+        * may cause the first superblock write, and that will check out
+        * if barriers work.
         */
+
        md_write_start(mddev, bio); /* wait on superblock update early */
 
+       if (unlikely(!mddev->barriers_work && bio_barrier(bio))) {
+               if (rw == WRITE)
+                       md_write_end(mddev);
+               bio_endio(bio, bio->bi_size, -EOPNOTSUPP);
+               return 0;
+       }
+
        wait_barrier(conf);
 
        disk_stat_inc(mddev->gendisk, ios[rw]);
@@ -1404,10 +1408,11 @@ static void raid1d(mddev_t *mddev)
                        unplug = 1;
                } else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) {
                        /* some requests in the r1bio were BIO_RW_BARRIER
-                        * requests which failed with -ENOTSUPP.  Hohumm..
+                        * requests which failed with -EOPNOTSUPP.  Hohumm..
                         * Better resubmit without the barrier.
                         * We know which devices to resubmit for, because
                         * all others have had their bios[] entry cleared.
+                        * We already have a nr_pending reference on these rdevs.
                         */
                        int i;
                        clear_bit(R1BIO_BarrierRetry, &r1_bio->state);
@@ -1558,8 +1563,7 @@ static int init_resync(conf_t *conf)
        int buffs;
 
        buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE;
-       if (conf->r1buf_pool)
-               BUG();
+       BUG_ON(conf->r1buf_pool);
        conf->r1buf_pool = mempool_create(buffs, r1buf_pool_alloc, r1buf_pool_free,
                                          conf->poolinfo);
        if (!conf->r1buf_pool)
@@ -1621,6 +1625,12 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
        /* before building a request, check if we can skip these blocks..
         * This call the bitmap_start_sync doesn't actually record anything
         */
+       if (mddev->bitmap == NULL &&
+           mddev->recovery_cp == MaxSector &&
+           conf->fullsync == 0) {
+               *skipped = 1;
+               return max_sector - sector_nr;
+       }
        if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
            !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
                /* We can skip this block, and probably several more */
@@ -1732,8 +1742,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                            !conf->fullsync &&
                            !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
                                break;
-                       if (sync_blocks < (PAGE_SIZE>>9))
-                               BUG();
+                       BUG_ON(sync_blocks < (PAGE_SIZE>>9));
                        if (len > (sync_blocks<<9))
                                len = sync_blocks<<9;
                }
@@ -1885,7 +1894,8 @@ static int run(mddev_t *mddev)
 
                disk = conf->mirrors + i;
 
-               if (!disk->rdev) {
+               if (!disk->rdev ||
+                   !test_bit(In_sync, &disk->rdev->flags)) {
                        disk->head_position = 0;
                        mddev->degraded++;
                }