Commit 07d84d10 authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds

[PATCH] md: Allow re-add to work on array without bitmaps

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: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 3285edf1
...@@ -737,6 +737,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -737,6 +737,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
{ {
mdp_disk_t *desc; mdp_disk_t *desc;
mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page); mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page);
__u64 ev1 = md_event(sb);
rdev->raid_disk = -1; rdev->raid_disk = -1;
rdev->flags = 0; rdev->flags = 0;
...@@ -753,7 +754,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -753,7 +754,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->layout = sb->layout; mddev->layout = sb->layout;
mddev->raid_disks = sb->raid_disks; mddev->raid_disks = sb->raid_disks;
mddev->size = sb->size; mddev->size = sb->size;
mddev->events = md_event(sb); mddev->events = ev1;
mddev->bitmap_offset = 0; mddev->bitmap_offset = 0;
mddev->default_bitmap_offset = MD_SB_BYTES >> 9; mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
...@@ -802,7 +803,6 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -802,7 +803,6 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
} else if (mddev->pers == NULL) { } else if (mddev->pers == NULL) {
/* Insist on good event counter while assembling */ /* Insist on good event counter while assembling */
__u64 ev1 = md_event(sb);
++ev1; ++ev1;
if (ev1 < mddev->events) if (ev1 < mddev->events)
return -EINVAL; return -EINVAL;
...@@ -810,11 +810,13 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -810,11 +810,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 /* if adding to array with a bitmap, then we can accept an
* older device ... but not too old. * older device ... but not too old.
*/ */
__u64 ev1 = md_event(sb);
if (ev1 < mddev->bitmap->events_cleared) if (ev1 < mddev->bitmap->events_cleared)
return 0; return 0;
} else /* just a hot-add of a new device, leave raid_disk at -1 */ } else {
if (ev1 < mddev->events)
/* just a hot-add of a new device, leave raid_disk at -1 */
return 0; return 0;
}
if (mddev->level != LEVEL_MULTIPATH) { if (mddev->level != LEVEL_MULTIPATH) {
desc = sb->disks + rdev->desc_nr; desc = sb->disks + rdev->desc_nr;
...@@ -1105,6 +1107,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) ...@@ -1105,6 +1107,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) 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); 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->raid_disk = -1;
rdev->flags = 0; rdev->flags = 0;
...@@ -1120,7 +1123,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -1120,7 +1123,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mddev->layout = le32_to_cpu(sb->layout); mddev->layout = le32_to_cpu(sb->layout);
mddev->raid_disks = le32_to_cpu(sb->raid_disks); mddev->raid_disks = le32_to_cpu(sb->raid_disks);
mddev->size = le64_to_cpu(sb->size)/2; mddev->size = le64_to_cpu(sb->size)/2;
mddev->events = le64_to_cpu(sb->events); mddev->events = ev1;
mddev->bitmap_offset = 0; mddev->bitmap_offset = 0;
mddev->default_bitmap_offset = 1024 >> 9; mddev->default_bitmap_offset = 1024 >> 9;
...@@ -1154,7 +1157,6 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -1154,7 +1157,6 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
} else if (mddev->pers == NULL) { } else if (mddev->pers == NULL) {
/* Insist of good event counter while assembling */ /* Insist of good event counter while assembling */
__u64 ev1 = le64_to_cpu(sb->events);
++ev1; ++ev1;
if (ev1 < mddev->events) if (ev1 < mddev->events)
return -EINVAL; return -EINVAL;
...@@ -1162,12 +1164,13 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -1162,12 +1164,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 /* If adding to array with a bitmap, then we can accept an
* older device, but not too old. * older device, but not too old.
*/ */
__u64 ev1 = le64_to_cpu(sb->events);
if (ev1 < mddev->bitmap->events_cleared) if (ev1 < mddev->bitmap->events_cleared)
return 0; return 0;
} else /* just a hot-add of a new device, leave raid_disk at -1 */ } else {
if (ev1 < mddev->events)
/* just a hot-add of a new device, leave raid_disk at -1 */
return 0; return 0;
}
if (mddev->level != LEVEL_MULTIPATH) { if (mddev->level != LEVEL_MULTIPATH) {
int role; int role;
rdev->desc_nr = le32_to_cpu(sb->dev_number); rdev->desc_nr = le32_to_cpu(sb->dev_number);
......
...@@ -1625,6 +1625,12 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i ...@@ -1625,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.. /* before building a request, check if we can skip these blocks..
* This call the bitmap_start_sync doesn't actually record anything * 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) && if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
!conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
/* We can skip this block, and probably several more */ /* We can skip this block, and probably several more */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment