]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
md: Allow re-add to work on array without bitmaps
authorNeil Brown <neilb@suse.de>
Wed, 22 Aug 2007 22:56:48 +0000 (00:56 +0200)
committerAdrian Bunk <bunk@stusta.de>
Wed, 22 Aug 2007 22:56:48 +0000 (00:56 +0200)
When an array has a bitmap, a device can be removed and re-added and only
blocks changes since the removal (as recorded in the bitmap) will be resynced.

It should be possible to do a similar thing to arrays without bitmaps.  i.e.
if a device is removed and re-added and *no* changes have been made in the
interim, then the add should not require a resync.

This patch allows that option.  This means that when assembling an array one
device at a time (e.g.  during device discovery) the array can be enabled
read-only as soon as enough devices are available, but extra devices can still
be added without causing a resync.

Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Adrian Bunk <bunk@kernel.org>
drivers/md/md.c
drivers/md/raid1.c

index 22ca22c343c64fd68c108030403f9cefa752d741..e0b81b607184ff0e8d1edf8f9b5e9debe69d0ac1 100644 (file)
@@ -722,6 +722,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 {
        mdp_disk_t *desc;
        mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page);
+       __u64 ev1 = md_event(sb);
 
        rdev->raid_disk = -1;
        rdev->flags = 0;
@@ -738,7 +739,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                mddev->layout = sb->layout;
                mddev->raid_disks = sb->raid_disks;
                mddev->size = sb->size;
-               mddev->events = md_event(sb);
+               mddev->events = ev1;
                mddev->bitmap_offset = 0;
                mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
 
@@ -773,7 +774,6 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 
        } else if (mddev->pers == NULL) {
                /* Insist on good event counter while assembling */
-               __u64 ev1 = md_event(sb);
                ++ev1;
                if (ev1 < mddev->events) 
                        return -EINVAL;
@@ -781,11 +781,13 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                /* if adding to array with a bitmap, then we can accept an
                 * older device ... but not too old.
                 */
-               __u64 ev1 = md_event(sb);
                if (ev1 < mddev->bitmap->events_cleared)
                        return 0;
-       } else /* just a hot-add of a new device, leave raid_disk at -1 */
-               return 0;
+       } else {
+               if (ev1 < mddev->events)
+                       /* just a hot-add of a new device, leave raid_disk at -1 */
+                       return 0;
+       }
 
        if (mddev->level != LEVEL_MULTIPATH) {
                desc = sb->disks + rdev->desc_nr;
@@ -1067,6 +1069,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
 static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 {
        struct mdp_superblock_1 *sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
+       __u64 ev1 = le64_to_cpu(sb->events);
 
        rdev->raid_disk = -1;
        rdev->flags = 0;
@@ -1082,7 +1085,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                mddev->layout = le32_to_cpu(sb->layout);
                mddev->raid_disks = le32_to_cpu(sb->raid_disks);
                mddev->size = le64_to_cpu(sb->size)/2;
-               mddev->events = le64_to_cpu(sb->events);
+               mddev->events = ev1;
                mddev->bitmap_offset = 0;
                mddev->default_bitmap_offset = 1024 >> 9;
                
@@ -1103,7 +1106,6 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                }
        } else if (mddev->pers == NULL) {
                /* Insist of good event counter while assembling */
-               __u64 ev1 = le64_to_cpu(sb->events);
                ++ev1;
                if (ev1 < mddev->events)
                        return -EINVAL;
@@ -1111,12 +1113,13 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                /* If adding to array with a bitmap, then we can accept an
                 * older device, but not too old.
                 */
-               __u64 ev1 = le64_to_cpu(sb->events);
                if (ev1 < mddev->bitmap->events_cleared)
                        return 0;
-       } else /* just a hot-add of a new device, leave raid_disk at -1 */
-               return 0;
-
+       } else {
+               if (ev1 < mddev->events)
+                       /* just a hot-add of a new device, leave raid_disk at -1 */
+                       return 0;
+       }
        if (mddev->level != LEVEL_MULTIPATH) {
                int role;
                rdev->desc_nr = le32_to_cpu(sb->dev_number);
index 0a01a0cbd88a2ca510806b13f98ef965ffc6a244..b8889200718b8507bb79f6352d3ca2432eded260 100644 (file)
@@ -1630,6 +1630,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 */