diff options
author | NeilBrown <neilb@suse.de> | 2013-11-18 20:02:01 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2013-11-18 23:19:17 -0500 |
commit | c91abf5a3546a4ff0838d2905f4d7eae2795f724 (patch) | |
tree | 39b3735cebfa73ff370f2738bd8578a113fe4215 /drivers/md/md.c | |
parent | 29f097c4d968021ee4fad1b033be5825ff78330e (diff) |
md: use MD_RECOVERY_INTR instead of kthread_should_stop in resync thread.
We currently use kthread_should_stop() in various places in the
sync/reshape code to abort early.
However some places set MD_RECOVERY_INTR but don't immediately call
md_reap_sync_thread() (and we will shortly get another one).
When this happens we are relying on md_check_recovery() to reap the
thread and that only happen when it finishes normally.
So MD_RECOVERY_INTR must lead to a normal finish without the
kthread_should_stop() test.
So replace all relevant tests, and be more careful when the thread is
interrupted not to acknowledge that latest step in a reshape as it may
not be fully committed yet.
Also add a test on MD_RECOVERY_INTR in the 'is_mddev_idle' loop
so we don't wait have to wait for the speed to drop before we can abort.
Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 40 |
1 files changed, 14 insertions, 26 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 1ca47b0f4779..a74045df7bab 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -7410,9 +7410,6 @@ void md_do_sync(struct md_thread *thread) | |||
7410 | mddev->curr_resync = 2; | 7410 | mddev->curr_resync = 2; |
7411 | 7411 | ||
7412 | try_again: | 7412 | try_again: |
7413 | if (kthread_should_stop()) | ||
7414 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | ||
7415 | |||
7416 | if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) | 7413 | if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) |
7417 | goto skip; | 7414 | goto skip; |
7418 | for_each_mddev(mddev2, tmp) { | 7415 | for_each_mddev(mddev2, tmp) { |
@@ -7437,7 +7434,7 @@ void md_do_sync(struct md_thread *thread) | |||
7437 | * be caught by 'softlockup' | 7434 | * be caught by 'softlockup' |
7438 | */ | 7435 | */ |
7439 | prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE); | 7436 | prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE); |
7440 | if (!kthread_should_stop() && | 7437 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && |
7441 | mddev2->curr_resync >= mddev->curr_resync) { | 7438 | mddev2->curr_resync >= mddev->curr_resync) { |
7442 | printk(KERN_INFO "md: delaying %s of %s" | 7439 | printk(KERN_INFO "md: delaying %s of %s" |
7443 | " until %s has finished (they" | 7440 | " until %s has finished (they" |
@@ -7513,7 +7510,7 @@ void md_do_sync(struct md_thread *thread) | |||
7513 | last_check = 0; | 7510 | last_check = 0; |
7514 | 7511 | ||
7515 | if (j>2) { | 7512 | if (j>2) { |
7516 | printk(KERN_INFO | 7513 | printk(KERN_INFO |
7517 | "md: resuming %s of %s from checkpoint.\n", | 7514 | "md: resuming %s of %s from checkpoint.\n", |
7518 | desc, mdname(mddev)); | 7515 | desc, mdname(mddev)); |
7519 | mddev->curr_resync = j; | 7516 | mddev->curr_resync = j; |
@@ -7550,7 +7547,8 @@ void md_do_sync(struct md_thread *thread) | |||
7550 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); | 7547 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); |
7551 | } | 7548 | } |
7552 | 7549 | ||
7553 | while (j >= mddev->resync_max && !kthread_should_stop()) { | 7550 | while (j >= mddev->resync_max && |
7551 | !test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { | ||
7554 | /* As this condition is controlled by user-space, | 7552 | /* As this condition is controlled by user-space, |
7555 | * we can block indefinitely, so use '_interruptible' | 7553 | * we can block indefinitely, so use '_interruptible' |
7556 | * to avoid triggering warnings. | 7554 | * to avoid triggering warnings. |
@@ -7558,17 +7556,18 @@ void md_do_sync(struct md_thread *thread) | |||
7558 | flush_signals(current); /* just in case */ | 7556 | flush_signals(current); /* just in case */ |
7559 | wait_event_interruptible(mddev->recovery_wait, | 7557 | wait_event_interruptible(mddev->recovery_wait, |
7560 | mddev->resync_max > j | 7558 | mddev->resync_max > j |
7561 | || kthread_should_stop()); | 7559 | || test_bit(MD_RECOVERY_INTR, |
7560 | &mddev->recovery)); | ||
7562 | } | 7561 | } |
7563 | 7562 | ||
7564 | if (kthread_should_stop()) | 7563 | if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) |
7565 | goto interrupted; | 7564 | break; |
7566 | 7565 | ||
7567 | sectors = mddev->pers->sync_request(mddev, j, &skipped, | 7566 | sectors = mddev->pers->sync_request(mddev, j, &skipped, |
7568 | currspeed < speed_min(mddev)); | 7567 | currspeed < speed_min(mddev)); |
7569 | if (sectors == 0) { | 7568 | if (sectors == 0) { |
7570 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | 7569 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
7571 | goto out; | 7570 | break; |
7572 | } | 7571 | } |
7573 | 7572 | ||
7574 | if (!skipped) { /* actual IO requested */ | 7573 | if (!skipped) { /* actual IO requested */ |
@@ -7605,10 +7604,8 @@ void md_do_sync(struct md_thread *thread) | |||
7605 | last_mark = next; | 7604 | last_mark = next; |
7606 | } | 7605 | } |
7607 | 7606 | ||
7608 | 7607 | if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) | |
7609 | if (kthread_should_stop()) | 7608 | break; |
7610 | goto interrupted; | ||
7611 | |||
7612 | 7609 | ||
7613 | /* | 7610 | /* |
7614 | * this loop exits only if either when we are slower than | 7611 | * this loop exits only if either when we are slower than |
@@ -7631,11 +7628,12 @@ void md_do_sync(struct md_thread *thread) | |||
7631 | } | 7628 | } |
7632 | } | 7629 | } |
7633 | } | 7630 | } |
7634 | printk(KERN_INFO "md: %s: %s done.\n",mdname(mddev), desc); | 7631 | printk(KERN_INFO "md: %s: %s %s.\n",mdname(mddev), desc, |
7632 | test_bit(MD_RECOVERY_INTR, &mddev->recovery) | ||
7633 | ? "interrupted" : "done"); | ||
7635 | /* | 7634 | /* |
7636 | * this also signals 'finished resyncing' to md_stop | 7635 | * this also signals 'finished resyncing' to md_stop |
7637 | */ | 7636 | */ |
7638 | out: | ||
7639 | blk_finish_plug(&plug); | 7637 | blk_finish_plug(&plug); |
7640 | wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); | 7638 | wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); |
7641 | 7639 | ||
@@ -7689,16 +7687,6 @@ void md_do_sync(struct md_thread *thread) | |||
7689 | set_bit(MD_RECOVERY_DONE, &mddev->recovery); | 7687 | set_bit(MD_RECOVERY_DONE, &mddev->recovery); |
7690 | md_wakeup_thread(mddev->thread); | 7688 | md_wakeup_thread(mddev->thread); |
7691 | return; | 7689 | return; |
7692 | |||
7693 | interrupted: | ||
7694 | /* | ||
7695 | * got a signal, exit. | ||
7696 | */ | ||
7697 | printk(KERN_INFO | ||
7698 | "md: md_do_sync() got signal ... exiting\n"); | ||
7699 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | ||
7700 | goto out; | ||
7701 | |||
7702 | } | 7690 | } |
7703 | EXPORT_SYMBOL_GPL(md_do_sync); | 7691 | EXPORT_SYMBOL_GPL(md_do_sync); |
7704 | 7692 | ||