aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2009-03-30 23:33:13 -0400
committerNeilBrown <neilb@suse.de>2009-03-30 23:33:13 -0400
commit97e4f42d62badb0f9fbc27c013e89bc1336a03bc (patch)
tree04cc809702a6b080c417c4ddf605642bbf7de521 /drivers/md/md.c
parent43b2e5d86d8bdd77386226db0bc961529492c043 (diff)
md: occasionally checkpoint drive recovery to reduce duplicate effort after a crash
Version 1.x metadata has the ability to record the status of a partially completed drive recovery. However we only update that record on a clean shutdown. It would be nice to update it on unclean shutdowns too, particularly when using a bitmap that removes much to the 'sync' effort after an unclean shutdown. One complication with checkpointing recovery is that we only know where we are up to in terms of IO requests started, not which ones have completed. And we need to know what has completed to record how much is recovered. So occasionally pause the recovery until all submitted requests are completed, then update the record of where we are up to. When we have a bitmap, we already do that pause occasionally to keep the bitmap up-to-date. So enhance that code to record the recovery offset and schedule a superblock update. And when there is no bitmap, just pause 16 times during the resync to do a checkpoint. '16' is a fairly arbitrary number. But we don't really have any good way to judge how often is acceptable, and it seems like a reasonable number for now. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index aad0ac54bf90..8ea208847a6d 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1324,10 +1324,15 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
1324 } 1324 }
1325 1325
1326 if (rdev->raid_disk >= 0 && 1326 if (rdev->raid_disk >= 0 &&
1327 !test_bit(In_sync, &rdev->flags) && 1327 !test_bit(In_sync, &rdev->flags)) {
1328 rdev->recovery_offset > 0) { 1328 if (mddev->curr_resync_completed > rdev->recovery_offset)
1329 sb->feature_map |= cpu_to_le32(MD_FEATURE_RECOVERY_OFFSET); 1329 rdev->recovery_offset = mddev->curr_resync_completed;
1330 sb->recovery_offset = cpu_to_le64(rdev->recovery_offset); 1330 if (rdev->recovery_offset > 0) {
1331 sb->feature_map |=
1332 cpu_to_le32(MD_FEATURE_RECOVERY_OFFSET);
1333 sb->recovery_offset =
1334 cpu_to_le64(rdev->recovery_offset);
1335 }
1331 } 1336 }
1332 1337
1333 if (mddev->reshape_position != MaxSector) { 1338 if (mddev->reshape_position != MaxSector) {
@@ -6072,6 +6077,18 @@ void md_do_sync(mddev_t *mddev)
6072 } 6077 }
6073 if (kthread_should_stop()) 6078 if (kthread_should_stop())
6074 goto interrupted; 6079 goto interrupted;
6080
6081 if (mddev->curr_resync > mddev->curr_resync_completed &&
6082 (mddev->curr_resync - mddev->curr_resync_completed)
6083 > (max_sectors >> 4)) {
6084 /* time to update curr_resync_completed */
6085 blk_unplug(mddev->queue);
6086 wait_event(mddev->recovery_wait,
6087 atomic_read(&mddev->recovery_active) == 0);
6088 mddev->curr_resync_completed =
6089 mddev->curr_resync;
6090 set_bit(MD_CHANGE_CLEAN, &mddev->flags);
6091 }
6075 sectors = mddev->pers->sync_request(mddev, j, &skipped, 6092 sectors = mddev->pers->sync_request(mddev, j, &skipped,
6076 currspeed < speed_min(mddev)); 6093 currspeed < speed_min(mddev));
6077 if (sectors == 0) { 6094 if (sectors == 0) {
@@ -6205,6 +6222,8 @@ static int remove_and_add_spares(mddev_t *mddev)
6205 mdk_rdev_t *rdev; 6222 mdk_rdev_t *rdev;
6206 int spares = 0; 6223 int spares = 0;
6207 6224
6225 mddev->curr_resync_completed = 0;
6226
6208 list_for_each_entry(rdev, &mddev->disks, same_set) 6227 list_for_each_entry(rdev, &mddev->disks, same_set)
6209 if (rdev->raid_disk >= 0 && 6228 if (rdev->raid_disk >= 0 &&
6210 !test_bit(Blocked, &rdev->flags) && 6229 !test_bit(Blocked, &rdev->flags) &&