diff options
author | NeilBrown <neilb@suse.de> | 2011-01-13 17:14:33 -0500 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-01-13 17:14:33 -0500 |
commit | 7ebc0be7fff4146e87b4078f054977b72998abd3 (patch) | |
tree | f5b5b40674ec4e221e77eb1f9e4f36138f75df3c /drivers/md | |
parent | defad61a5b16352d3e22a04d4c930a5b5a7fd1f0 (diff) |
md: Be more careful about clearing flags bit in ->recovery
Setting ->recovery to 0 is generally not a good idea as it could clear
bits that shouldn't be cleared. In particular, MD_RECOVERY_FROZEN
should only be cleared on explicit request from user-space.
So when we need to clear things, just clear the bits that need
clearing.
As there are a few different places which reap a resync process - and
some do an incomplte job - factor out the code for doing the from
md_check_recovery and call that function instead of open coding part
of it.
Signed-off-by: NeilBrown <neilb@suse.de>
Reported-by: Jonathan Brassow <jbrassow@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/md.c | 86 |
1 files changed, 49 insertions, 37 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index f43ff2962b2b..a91dc593f3ca 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3746,6 +3746,8 @@ action_show(mddev_t *mddev, char *page) | |||
3746 | return sprintf(page, "%s\n", type); | 3746 | return sprintf(page, "%s\n", type); |
3747 | } | 3747 | } |
3748 | 3748 | ||
3749 | static void reap_sync_thread(mddev_t *mddev); | ||
3750 | |||
3749 | static ssize_t | 3751 | static ssize_t |
3750 | action_store(mddev_t *mddev, const char *page, size_t len) | 3752 | action_store(mddev_t *mddev, const char *page, size_t len) |
3751 | { | 3753 | { |
@@ -3760,9 +3762,7 @@ action_store(mddev_t *mddev, const char *page, size_t len) | |||
3760 | if (cmd_match(page, "idle") || cmd_match(page, "frozen")) { | 3762 | if (cmd_match(page, "idle") || cmd_match(page, "frozen")) { |
3761 | if (mddev->sync_thread) { | 3763 | if (mddev->sync_thread) { |
3762 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | 3764 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
3763 | md_unregister_thread(mddev->sync_thread); | 3765 | reap_sync_thread(mddev); |
3764 | mddev->sync_thread = NULL; | ||
3765 | mddev->recovery = 0; | ||
3766 | } | 3766 | } |
3767 | } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || | 3767 | } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || |
3768 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) | 3768 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) |
@@ -4709,8 +4709,7 @@ static void __md_stop_writes(mddev_t *mddev) | |||
4709 | if (mddev->sync_thread) { | 4709 | if (mddev->sync_thread) { |
4710 | set_bit(MD_RECOVERY_FROZEN, &mddev->recovery); | 4710 | set_bit(MD_RECOVERY_FROZEN, &mddev->recovery); |
4711 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | 4711 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
4712 | md_unregister_thread(mddev->sync_thread); | 4712 | reap_sync_thread(mddev); |
4713 | mddev->sync_thread = NULL; | ||
4714 | } | 4713 | } |
4715 | 4714 | ||
4716 | del_timer_sync(&mddev->safemode_timer); | 4715 | del_timer_sync(&mddev->safemode_timer); |
@@ -7044,6 +7043,45 @@ static int remove_and_add_spares(mddev_t *mddev) | |||
7044 | } | 7043 | } |
7045 | return spares; | 7044 | return spares; |
7046 | } | 7045 | } |
7046 | |||
7047 | static void reap_sync_thread(mddev_t *mddev) | ||
7048 | { | ||
7049 | mdk_rdev_t *rdev; | ||
7050 | |||
7051 | /* resync has finished, collect result */ | ||
7052 | md_unregister_thread(mddev->sync_thread); | ||
7053 | mddev->sync_thread = NULL; | ||
7054 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && | ||
7055 | !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { | ||
7056 | /* success...*/ | ||
7057 | /* activate any spares */ | ||
7058 | if (mddev->pers->spare_active(mddev)) | ||
7059 | sysfs_notify(&mddev->kobj, NULL, | ||
7060 | "degraded"); | ||
7061 | } | ||
7062 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && | ||
7063 | mddev->pers->finish_reshape) | ||
7064 | mddev->pers->finish_reshape(mddev); | ||
7065 | md_update_sb(mddev, 1); | ||
7066 | |||
7067 | /* if array is no-longer degraded, then any saved_raid_disk | ||
7068 | * information must be scrapped | ||
7069 | */ | ||
7070 | if (!mddev->degraded) | ||
7071 | list_for_each_entry(rdev, &mddev->disks, same_set) | ||
7072 | rdev->saved_raid_disk = -1; | ||
7073 | |||
7074 | clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery); | ||
7075 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); | ||
7076 | clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); | ||
7077 | clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); | ||
7078 | clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); | ||
7079 | /* flag recovery needed just to double check */ | ||
7080 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
7081 | sysfs_notify_dirent_safe(mddev->sysfs_action); | ||
7082 | md_new_event(mddev); | ||
7083 | } | ||
7084 | |||
7047 | /* | 7085 | /* |
7048 | * This routine is regularly called by all per-raid-array threads to | 7086 | * This routine is regularly called by all per-raid-array threads to |
7049 | * deal with generic issues like resync and super-block update. | 7087 | * deal with generic issues like resync and super-block update. |
@@ -7068,9 +7106,6 @@ static int remove_and_add_spares(mddev_t *mddev) | |||
7068 | */ | 7106 | */ |
7069 | void md_check_recovery(mddev_t *mddev) | 7107 | void md_check_recovery(mddev_t *mddev) |
7070 | { | 7108 | { |
7071 | mdk_rdev_t *rdev; | ||
7072 | |||
7073 | |||
7074 | if (mddev->bitmap) | 7109 | if (mddev->bitmap) |
7075 | bitmap_daemon_work(mddev); | 7110 | bitmap_daemon_work(mddev); |
7076 | 7111 | ||
@@ -7138,34 +7173,7 @@ void md_check_recovery(mddev_t *mddev) | |||
7138 | goto unlock; | 7173 | goto unlock; |
7139 | } | 7174 | } |
7140 | if (mddev->sync_thread) { | 7175 | if (mddev->sync_thread) { |
7141 | /* resync has finished, collect result */ | 7176 | reap_sync_thread(mddev); |
7142 | md_unregister_thread(mddev->sync_thread); | ||
7143 | mddev->sync_thread = NULL; | ||
7144 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) && | ||
7145 | !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { | ||
7146 | /* success...*/ | ||
7147 | /* activate any spares */ | ||
7148 | if (mddev->pers->spare_active(mddev)) | ||
7149 | sysfs_notify(&mddev->kobj, NULL, | ||
7150 | "degraded"); | ||
7151 | } | ||
7152 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && | ||
7153 | mddev->pers->finish_reshape) | ||
7154 | mddev->pers->finish_reshape(mddev); | ||
7155 | md_update_sb(mddev, 1); | ||
7156 | |||
7157 | /* if array is no-longer degraded, then any saved_raid_disk | ||
7158 | * information must be scrapped | ||
7159 | */ | ||
7160 | if (!mddev->degraded) | ||
7161 | list_for_each_entry(rdev, &mddev->disks, same_set) | ||
7162 | rdev->saved_raid_disk = -1; | ||
7163 | |||
7164 | mddev->recovery = 0; | ||
7165 | /* flag recovery needed just to double check */ | ||
7166 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
7167 | sysfs_notify_dirent_safe(mddev->sysfs_action); | ||
7168 | md_new_event(mddev); | ||
7169 | goto unlock; | 7177 | goto unlock; |
7170 | } | 7178 | } |
7171 | /* Set RUNNING before clearing NEEDED to avoid | 7179 | /* Set RUNNING before clearing NEEDED to avoid |
@@ -7223,7 +7231,11 @@ void md_check_recovery(mddev_t *mddev) | |||
7223 | " thread...\n", | 7231 | " thread...\n", |
7224 | mdname(mddev)); | 7232 | mdname(mddev)); |
7225 | /* leave the spares where they are, it shouldn't hurt */ | 7233 | /* leave the spares where they are, it shouldn't hurt */ |
7226 | mddev->recovery = 0; | 7234 | clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery); |
7235 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); | ||
7236 | clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery); | ||
7237 | clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); | ||
7238 | clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); | ||
7227 | } else | 7239 | } else |
7228 | md_wakeup_thread(mddev->sync_thread); | 7240 | md_wakeup_thread(mddev->sync_thread); |
7229 | sysfs_notify_dirent_safe(mddev->sysfs_action); | 7241 | sysfs_notify_dirent_safe(mddev->sysfs_action); |