]> Pileus Git - ~andy/linux/blobdiff - drivers/md/raid1.c
[PATCH] Kconfig fix (sparc32 drivers/char dependencies)
[~andy/linux] / drivers / md / raid1.c
index 3f5234fe359330237e6998d1a0d49faaf99c7db3..51d9645ed09c5e8ff79aa9e7a6604e94dc274a54 100644 (file)
@@ -561,8 +561,8 @@ static int make_request(request_queue_t *q, struct bio * bio)
         * thread has put up a bar for new requests.
         * Continue immediately if no resync is active currently.
         */
-       if (md_write_start(mddev, bio)==0)
-               return 0;
+       md_write_start(mddev, bio); /* wait on superblock update early */
+
        spin_lock_irq(&conf->resync_lock);
        wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
        conf->nr_pending++;
@@ -893,7 +893,6 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
        if (!uptodate) {
                md_error(r1_bio->mddev,
                         conf->mirrors[r1_bio->read_disk].rdev);
-               set_bit(R1BIO_Degraded, &r1_bio->state);
        } else
                set_bit(R1BIO_Uptodate, &r1_bio->state);
        rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
@@ -918,10 +917,9 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
                        mirror = i;
                        break;
                }
-       if (!uptodate) {
+       if (!uptodate)
                md_error(mddev, conf->mirrors[mirror].rdev);
-               set_bit(R1BIO_Degraded, &r1_bio->state);
-       }
+
        update_head_pos(mirror, r1_bio);
 
        if (atomic_dec_and_test(&r1_bio->remaining)) {
@@ -1109,6 +1107,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
        int i;
        int write_targets = 0;
        int sync_blocks;
+       int still_degraded = 0;
 
        if (!conf->r1buf_pool)
        {
@@ -1126,21 +1125,22 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                 * only be one in raid1 resync.
                 * We can find the current addess in mddev->curr_resync
                 */
-               if (!conf->fullsync) {
-                       if (mddev->curr_resync < max_sector)
-                               bitmap_end_sync(mddev->bitmap,
-                                               mddev->curr_resync,
+               if (mddev->curr_resync < max_sector) /* aborted */
+                       bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
                                                &sync_blocks, 1);
-                       bitmap_close_sync(mddev->bitmap);
-               }
-               if (mddev->curr_resync >= max_sector)
+               else /* completed sync */
                        conf->fullsync = 0;
+
+               bitmap_close_sync(mddev->bitmap);
                close_sync(conf);
                return 0;
        }
 
-       if (!conf->fullsync &&
-           !bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks)) {
+       /* before building a request, check if we can skip these blocks..
+        * This call the bitmap_start_sync doesn't actually record anything
+        */
+       if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+           !conf->fullsync) {
                /* We can skip this block, and probably several more */
                *skipped = 1;
                return sync_blocks;
@@ -1205,24 +1205,23 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                if (i == disk) {
                        bio->bi_rw = READ;
                        bio->bi_end_io = end_sync_read;
-               } else if (conf->mirrors[i].rdev &&
-                          !conf->mirrors[i].rdev->faulty &&
-                          (!conf->mirrors[i].rdev->in_sync ||
-                           sector_nr + RESYNC_SECTORS > mddev->recovery_cp)) {
+               } else if (conf->mirrors[i].rdev == NULL ||
+                          conf->mirrors[i].rdev->faulty) {
+                       still_degraded = 1;
+                       continue;
+               } else if (!conf->mirrors[i].rdev->in_sync ||
+                          sector_nr + RESYNC_SECTORS > mddev->recovery_cp) {
                        bio->bi_rw = WRITE;
                        bio->bi_end_io = end_sync_write;
                        write_targets ++;
                } else
+                       /* no need to read or write here */
                        continue;
                bio->bi_sector = sector_nr + conf->mirrors[i].rdev->data_offset;
                bio->bi_bdev = conf->mirrors[i].rdev->bdev;
                bio->bi_private = r1_bio;
        }
 
-       if (write_targets + 1 < conf->raid_disks)
-               /* array degraded, can't clear bitmap */
-               set_bit(R1BIO_Degraded, &r1_bio->state);
-
        if (write_targets == 0) {
                /* There is nowhere to write, so all non-sync
                 * drives must be failed - so we are finished
@@ -1243,15 +1242,15 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                        len = (max_sector - sector_nr) << 9;
                if (len == 0)
                        break;
-               if (!conf->fullsync) {
-                       if (sync_blocks == 0) {
-                               if (!bitmap_start_sync(mddev->bitmap,
-                                                      sector_nr, &sync_blocks))
-                                       break;
-                               if (sync_blocks < (PAGE_SIZE>>9))
-                                       BUG();
-                               if (len > (sync_blocks<<9)) len = sync_blocks<<9;
-                       }
+               if (sync_blocks == 0) {
+                       if (!bitmap_start_sync(mddev->bitmap, sector_nr,
+                                       &sync_blocks, still_degraded) &&
+                                       !conf->fullsync)
+                               break;
+                       if (sync_blocks < (PAGE_SIZE>>9))
+                               BUG();
+                       if (len > (sync_blocks<<9))
+                               len = sync_blocks<<9;
                }
 
                for (i=0 ; i < conf->raid_disks; i++) {
@@ -1264,7 +1263,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
                                        while (i > 0) {
                                                i--;
                                                bio = r1_bio->bios[i];
-                                               if (bio->bi_end_io==NULL) continue;
+                                               if (bio->bi_end_io==NULL)
+                                                       continue;
                                                /* remove last page from this bio */
                                                bio->bi_vcnt--;
                                                bio->bi_size -= len;
@@ -1427,10 +1427,8 @@ out_free_conf:
        if (conf) {
                if (conf->r1bio_pool)
                        mempool_destroy(conf->r1bio_pool);
-               if (conf->mirrors)
-                       kfree(conf->mirrors);
-               if (conf->poolinfo)
-                       kfree(conf->poolinfo);
+               kfree(conf->mirrors);
+               kfree(conf->poolinfo);
                kfree(conf);
                mddev->private = NULL;
        }
@@ -1447,10 +1445,8 @@ static int stop(mddev_t *mddev)
        blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
        if (conf->r1bio_pool)
                mempool_destroy(conf->r1bio_pool);
-       if (conf->mirrors)
-               kfree(conf->mirrors);
-       if (conf->poolinfo)
-               kfree(conf->poolinfo);
+       kfree(conf->mirrors);
+       kfree(conf->poolinfo);
        kfree(conf);
        mddev->private = NULL;
        return 0;
@@ -1473,6 +1469,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
                set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
        }
        mddev->size = mddev->array_size;
+       mddev->resync_max_sectors = sectors;
        return 0;
 }