Merge remote-tracking branch 'md/for-next'
[karo-tx-linux.git] / drivers / md / raid1.c
index 33e5987..e2169ff 100644 (file)
@@ -90,6 +90,8 @@ static void r1bio_pool_free(void *r1_bio, void *data)
 #define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE)
 #define RESYNC_WINDOW (RESYNC_BLOCK_SIZE * RESYNC_DEPTH)
 #define RESYNC_WINDOW_SECTORS (RESYNC_WINDOW >> 9)
+#define CLUSTER_RESYNC_WINDOW (16 * RESYNC_WINDOW)
+#define CLUSTER_RESYNC_WINDOW_SECTORS (CLUSTER_RESYNC_WINDOW >> 9)
 #define NEXT_NORMALIO_DISTANCE (3 * RESYNC_WINDOW_SECTORS)
 
 static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
@@ -1590,6 +1592,15 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
        if (rdev->raid_disk >= 0)
                first = last = rdev->raid_disk;
 
+       /*
+        * find the disk ... but prefer rdev->saved_raid_disk
+        * if possible.
+        */
+       if (rdev->saved_raid_disk >= 0 &&
+           rdev->saved_raid_disk >= first &&
+           conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
+               first = last = rdev->saved_raid_disk;
+
        for (mirror = first; mirror <= last; mirror++) {
                p = conf->mirrors+mirror;
                if (!p->rdev) {
@@ -2495,6 +2506,11 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
 
                bitmap_close_sync(mddev->bitmap);
                close_sync(conf);
+
+               if (mddev_is_clustered(mddev)) {
+                       conf->cluster_sync_low = 0;
+                       conf->cluster_sync_high = 0;
+               }
                return 0;
        }
 
@@ -2515,7 +2531,12 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
                return sync_blocks;
        }
 
-       bitmap_cond_end_sync(mddev->bitmap, sector_nr);
+       /* we are incrementing sector_nr below. To be safe, we check against
+        * sector_nr + two times RESYNC_SECTORS
+        */
+
+       bitmap_cond_end_sync(mddev->bitmap, sector_nr,
+               mddev_is_clustered(mddev) && (sector_nr + 2 * RESYNC_SECTORS > conf->cluster_sync_high));
        r1_bio = mempool_alloc(conf->r1buf_pool, GFP_NOIO);
 
        raise_barrier(conf, sector_nr);
@@ -2706,6 +2727,16 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipp
  bio_full:
        r1_bio->sectors = nr_sectors;
 
+       if (mddev_is_clustered(mddev) &&
+                       conf->cluster_sync_high < sector_nr + nr_sectors) {
+               conf->cluster_sync_low = mddev->curr_resync_completed;
+               conf->cluster_sync_high = conf->cluster_sync_low + CLUSTER_RESYNC_WINDOW_SECTORS;
+               /* Send resync message */
+               md_cluster_ops->resync_info_update(mddev,
+                               conf->cluster_sync_low,
+                               conf->cluster_sync_high);
+       }
+
        /* For a user-requested sync, we read all readable devices and do a
         * compare
         */
@@ -3020,9 +3051,11 @@ static int raid1_reshape(struct mddev *mddev)
                return -EINVAL;
        }
 
-       err = md_allow_write(mddev);
-       if (err)
-               return err;
+       if (!mddev_is_clustered(mddev)) {
+               err = md_allow_write(mddev);
+               if (err)
+                       return err;
+       }
 
        raid_disks = mddev->raid_disks + mddev->delta_disks;