diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 35 |
1 files changed, 23 insertions, 12 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 177d2a7d7cea..fa608a1a5c20 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3241,12 +3241,13 @@ static void md_do_sync(mddev_t *mddev) | |||
3241 | mddev_t *mddev2; | 3241 | mddev_t *mddev2; |
3242 | unsigned int currspeed = 0, | 3242 | unsigned int currspeed = 0, |
3243 | window; | 3243 | window; |
3244 | sector_t max_sectors,j; | 3244 | sector_t max_sectors,j, io_sectors; |
3245 | unsigned long mark[SYNC_MARKS]; | 3245 | unsigned long mark[SYNC_MARKS]; |
3246 | sector_t mark_cnt[SYNC_MARKS]; | 3246 | sector_t mark_cnt[SYNC_MARKS]; |
3247 | int last_mark,m; | 3247 | int last_mark,m; |
3248 | struct list_head *tmp; | 3248 | struct list_head *tmp; |
3249 | sector_t last_check; | 3249 | sector_t last_check; |
3250 | int skipped = 0; | ||
3250 | 3251 | ||
3251 | /* just incase thread restarts... */ | 3252 | /* just incase thread restarts... */ |
3252 | if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) | 3253 | if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) |
@@ -3312,7 +3313,7 @@ static void md_do_sync(mddev_t *mddev) | |||
3312 | 3313 | ||
3313 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) | 3314 | if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) |
3314 | /* resync follows the size requested by the personality, | 3315 | /* resync follows the size requested by the personality, |
3315 | * which default to physical size, but can be virtual size | 3316 | * which defaults to physical size, but can be virtual size |
3316 | */ | 3317 | */ |
3317 | max_sectors = mddev->resync_max_sectors; | 3318 | max_sectors = mddev->resync_max_sectors; |
3318 | else | 3319 | else |
@@ -3331,9 +3332,10 @@ static void md_do_sync(mddev_t *mddev) | |||
3331 | j = mddev->recovery_cp; | 3332 | j = mddev->recovery_cp; |
3332 | else | 3333 | else |
3333 | j = 0; | 3334 | j = 0; |
3335 | io_sectors = 0; | ||
3334 | for (m = 0; m < SYNC_MARKS; m++) { | 3336 | for (m = 0; m < SYNC_MARKS; m++) { |
3335 | mark[m] = jiffies; | 3337 | mark[m] = jiffies; |
3336 | mark_cnt[m] = j; | 3338 | mark_cnt[m] = io_sectors; |
3337 | } | 3339 | } |
3338 | last_mark = 0; | 3340 | last_mark = 0; |
3339 | mddev->resync_mark = mark[last_mark]; | 3341 | mddev->resync_mark = mark[last_mark]; |
@@ -3358,21 +3360,29 @@ static void md_do_sync(mddev_t *mddev) | |||
3358 | } | 3360 | } |
3359 | 3361 | ||
3360 | while (j < max_sectors) { | 3362 | while (j < max_sectors) { |
3361 | int sectors; | 3363 | sector_t sectors; |
3362 | 3364 | ||
3363 | sectors = mddev->pers->sync_request(mddev, j, currspeed < sysctl_speed_limit_min); | 3365 | skipped = 0; |
3364 | if (sectors < 0) { | 3366 | sectors = mddev->pers->sync_request(mddev, j, &skipped, |
3367 | currspeed < sysctl_speed_limit_min); | ||
3368 | if (sectors == 0) { | ||
3365 | set_bit(MD_RECOVERY_ERR, &mddev->recovery); | 3369 | set_bit(MD_RECOVERY_ERR, &mddev->recovery); |
3366 | goto out; | 3370 | goto out; |
3367 | } | 3371 | } |
3368 | atomic_add(sectors, &mddev->recovery_active); | 3372 | |
3373 | if (!skipped) { /* actual IO requested */ | ||
3374 | io_sectors += sectors; | ||
3375 | atomic_add(sectors, &mddev->recovery_active); | ||
3376 | } | ||
3377 | |||
3369 | j += sectors; | 3378 | j += sectors; |
3370 | if (j>1) mddev->curr_resync = j; | 3379 | if (j>1) mddev->curr_resync = j; |
3371 | 3380 | ||
3372 | if (last_check + window > j || j == max_sectors) | 3381 | |
3382 | if (last_check + window > io_sectors || j == max_sectors) | ||
3373 | continue; | 3383 | continue; |
3374 | 3384 | ||
3375 | last_check = j; | 3385 | last_check = io_sectors; |
3376 | 3386 | ||
3377 | if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) || | 3387 | if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) || |
3378 | test_bit(MD_RECOVERY_ERR, &mddev->recovery)) | 3388 | test_bit(MD_RECOVERY_ERR, &mddev->recovery)) |
@@ -3386,7 +3396,7 @@ static void md_do_sync(mddev_t *mddev) | |||
3386 | mddev->resync_mark = mark[next]; | 3396 | mddev->resync_mark = mark[next]; |
3387 | mddev->resync_mark_cnt = mark_cnt[next]; | 3397 | mddev->resync_mark_cnt = mark_cnt[next]; |
3388 | mark[next] = jiffies; | 3398 | mark[next] = jiffies; |
3389 | mark_cnt[next] = j - atomic_read(&mddev->recovery_active); | 3399 | mark_cnt[next] = io_sectors - atomic_read(&mddev->recovery_active); |
3390 | last_mark = next; | 3400 | last_mark = next; |
3391 | } | 3401 | } |
3392 | 3402 | ||
@@ -3413,7 +3423,8 @@ static void md_do_sync(mddev_t *mddev) | |||
3413 | mddev->queue->unplug_fn(mddev->queue); | 3423 | mddev->queue->unplug_fn(mddev->queue); |
3414 | cond_resched(); | 3424 | cond_resched(); |
3415 | 3425 | ||
3416 | currspeed = ((unsigned long)(j-mddev->resync_mark_cnt))/2/((jiffies-mddev->resync_mark)/HZ +1) +1; | 3426 | currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2 |
3427 | /((jiffies-mddev->resync_mark)/HZ +1) +1; | ||
3417 | 3428 | ||
3418 | if (currspeed > sysctl_speed_limit_min) { | 3429 | if (currspeed > sysctl_speed_limit_min) { |
3419 | if ((currspeed > sysctl_speed_limit_max) || | 3430 | if ((currspeed > sysctl_speed_limit_max) || |
@@ -3433,7 +3444,7 @@ static void md_do_sync(mddev_t *mddev) | |||
3433 | wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); | 3444 | wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); |
3434 | 3445 | ||
3435 | /* tell personality that we are finished */ | 3446 | /* tell personality that we are finished */ |
3436 | mddev->pers->sync_request(mddev, max_sectors, 1); | 3447 | mddev->pers->sync_request(mddev, max_sectors, &skipped, 1); |
3437 | 3448 | ||
3438 | if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && | 3449 | if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && |
3439 | mddev->curr_resync > 2 && | 3450 | mddev->curr_resync > 2 && |