diff options
| author | majianpeng <majianpeng@gmail.com> | 2012-10-30 20:59:10 -0400 |
|---|---|---|
| committer | NeilBrown <neilb@suse.de> | 2012-12-13 00:41:40 -0500 |
| commit | 54f89341e8b8da0cdac8a7b873491739de19f098 (patch) | |
| tree | 360f937ada4613db9772ef1a28f9503cb4457169 | |
| parent | 35d78c66969fbbb51046e9f251849cf54e9ed88c (diff) | |
md: Update checkpoint of resync/recovery based on time.
md will current only only checkpoint recovery or resync ever 1/16th
of the device size. As devices get larger this can become a long time
an so a lot of work that might need to be duplicated after a shutdown.
So add a time-based checkpoint. Every 5 minutes limits the amount of
duplicated effort to at most 5 minutes, and has almost zero impact on
performance.
[changelog entry re-written by NeilBrown]
Signed-off-by: Jianpeng Ma <majianpeng@gmail.com>
Signed-off-by: NeilBrown <neilb@suse.de>
| -rw-r--r-- | drivers/md/md.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index f97083476475..6aefa4434819 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -7277,6 +7277,7 @@ EXPORT_SYMBOL_GPL(md_allow_write); | |||
| 7277 | 7277 | ||
| 7278 | #define SYNC_MARKS 10 | 7278 | #define SYNC_MARKS 10 |
| 7279 | #define SYNC_MARK_STEP (3*HZ) | 7279 | #define SYNC_MARK_STEP (3*HZ) |
| 7280 | #define UPDATE_FREQUENCY (5*60*HZ) | ||
| 7280 | void md_do_sync(struct md_thread *thread) | 7281 | void md_do_sync(struct md_thread *thread) |
| 7281 | { | 7282 | { |
| 7282 | struct mddev *mddev = thread->mddev; | 7283 | struct mddev *mddev = thread->mddev; |
| @@ -7285,6 +7286,7 @@ void md_do_sync(struct md_thread *thread) | |||
| 7285 | window; | 7286 | window; |
| 7286 | sector_t max_sectors,j, io_sectors; | 7287 | sector_t max_sectors,j, io_sectors; |
| 7287 | unsigned long mark[SYNC_MARKS]; | 7288 | unsigned long mark[SYNC_MARKS]; |
| 7289 | unsigned long update_time; | ||
| 7288 | sector_t mark_cnt[SYNC_MARKS]; | 7290 | sector_t mark_cnt[SYNC_MARKS]; |
| 7289 | int last_mark,m; | 7291 | int last_mark,m; |
| 7290 | struct list_head *tmp; | 7292 | struct list_head *tmp; |
| @@ -7444,6 +7446,7 @@ void md_do_sync(struct md_thread *thread) | |||
| 7444 | mddev->curr_resync_completed = j; | 7446 | mddev->curr_resync_completed = j; |
| 7445 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); | 7447 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); |
| 7446 | md_new_event(mddev); | 7448 | md_new_event(mddev); |
| 7449 | update_time = jiffies; | ||
| 7447 | 7450 | ||
| 7448 | blk_start_plug(&plug); | 7451 | blk_start_plug(&plug); |
| 7449 | while (j < max_sectors) { | 7452 | while (j < max_sectors) { |
| @@ -7455,6 +7458,7 @@ void md_do_sync(struct md_thread *thread) | |||
| 7455 | ((mddev->curr_resync > mddev->curr_resync_completed && | 7458 | ((mddev->curr_resync > mddev->curr_resync_completed && |
| 7456 | (mddev->curr_resync - mddev->curr_resync_completed) | 7459 | (mddev->curr_resync - mddev->curr_resync_completed) |
| 7457 | > (max_sectors >> 4)) || | 7460 | > (max_sectors >> 4)) || |
| 7461 | time_after_eq(jiffies, update_time + UPDATE_FREQUENCY) || | ||
| 7458 | (j - mddev->curr_resync_completed)*2 | 7462 | (j - mddev->curr_resync_completed)*2 |
| 7459 | >= mddev->resync_max - mddev->curr_resync_completed | 7463 | >= mddev->resync_max - mddev->curr_resync_completed |
| 7460 | )) { | 7464 | )) { |
| @@ -7465,6 +7469,7 @@ void md_do_sync(struct md_thread *thread) | |||
| 7465 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && | 7469 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && |
| 7466 | j > mddev->recovery_cp) | 7470 | j > mddev->recovery_cp) |
| 7467 | mddev->recovery_cp = j; | 7471 | mddev->recovery_cp = j; |
| 7472 | update_time = jiffies; | ||
| 7468 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); | 7473 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); |
| 7469 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); | 7474 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); |
| 7470 | } | 7475 | } |
