aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2011-01-13 17:14:33 -0500
committerNeilBrown <neilb@suse.de>2011-01-13 17:14:33 -0500
commit7ebc0be7fff4146e87b4078f054977b72998abd3 (patch)
treef5b5b40674ec4e221e77eb1f9e4f36138f75df3c /drivers/md
parentdefad61a5b16352d3e22a04d4c930a5b5a7fd1f0 (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.c86
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
3749static void reap_sync_thread(mddev_t *mddev);
3750
3749static ssize_t 3751static ssize_t
3750action_store(mddev_t *mddev, const char *page, size_t len) 3752action_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
7047static 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 */
7069void md_check_recovery(mddev_t *mddev) 7107void 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);