mirror of
https://github.com/torvalds/linux
synced 2024-09-21 03:28:37 +00:00
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>
This commit is contained in:
parent
defad61a5b
commit
7ebc0be7ff
|
@ -3746,6 +3746,8 @@ action_show(mddev_t *mddev, char *page)
|
||||||
return sprintf(page, "%s\n", type);
|
return sprintf(page, "%s\n", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reap_sync_thread(mddev_t *mddev);
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
action_store(mddev_t *mddev, const char *page, size_t len)
|
action_store(mddev_t *mddev, const char *page, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -3760,9 +3762,7 @@ action_store(mddev_t *mddev, const char *page, size_t len)
|
||||||
if (cmd_match(page, "idle") || cmd_match(page, "frozen")) {
|
if (cmd_match(page, "idle") || cmd_match(page, "frozen")) {
|
||||||
if (mddev->sync_thread) {
|
if (mddev->sync_thread) {
|
||||||
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
||||||
md_unregister_thread(mddev->sync_thread);
|
reap_sync_thread(mddev);
|
||||||
mddev->sync_thread = NULL;
|
|
||||||
mddev->recovery = 0;
|
|
||||||
}
|
}
|
||||||
} else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
|
} else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
|
||||||
test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
|
test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
|
||||||
|
@ -4709,8 +4709,7 @@ static void __md_stop_writes(mddev_t *mddev)
|
||||||
if (mddev->sync_thread) {
|
if (mddev->sync_thread) {
|
||||||
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
|
||||||
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
||||||
md_unregister_thread(mddev->sync_thread);
|
reap_sync_thread(mddev);
|
||||||
mddev->sync_thread = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
del_timer_sync(&mddev->safemode_timer);
|
del_timer_sync(&mddev->safemode_timer);
|
||||||
|
@ -7044,6 +7043,45 @@ static int remove_and_add_spares(mddev_t *mddev)
|
||||||
}
|
}
|
||||||
return spares;
|
return spares;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reap_sync_thread(mddev_t *mddev)
|
||||||
|
{
|
||||||
|
mdk_rdev_t *rdev;
|
||||||
|
|
||||||
|
/* resync has finished, collect result */
|
||||||
|
md_unregister_thread(mddev->sync_thread);
|
||||||
|
mddev->sync_thread = NULL;
|
||||||
|
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
|
||||||
|
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
|
||||||
|
/* success...*/
|
||||||
|
/* activate any spares */
|
||||||
|
if (mddev->pers->spare_active(mddev))
|
||||||
|
sysfs_notify(&mddev->kobj, NULL,
|
||||||
|
"degraded");
|
||||||
|
}
|
||||||
|
if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
|
||||||
|
mddev->pers->finish_reshape)
|
||||||
|
mddev->pers->finish_reshape(mddev);
|
||||||
|
md_update_sb(mddev, 1);
|
||||||
|
|
||||||
|
/* if array is no-longer degraded, then any saved_raid_disk
|
||||||
|
* information must be scrapped
|
||||||
|
*/
|
||||||
|
if (!mddev->degraded)
|
||||||
|
list_for_each_entry(rdev, &mddev->disks, same_set)
|
||||||
|
rdev->saved_raid_disk = -1;
|
||||||
|
|
||||||
|
clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
|
||||||
|
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
|
||||||
|
clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
|
||||||
|
clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
|
||||||
|
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
|
||||||
|
/* flag recovery needed just to double check */
|
||||||
|
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
||||||
|
sysfs_notify_dirent_safe(mddev->sysfs_action);
|
||||||
|
md_new_event(mddev);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This routine is regularly called by all per-raid-array threads to
|
* This routine is regularly called by all per-raid-array threads to
|
||||||
* deal with generic issues like resync and super-block update.
|
* deal with generic issues like resync and super-block update.
|
||||||
|
@ -7068,9 +7106,6 @@ static int remove_and_add_spares(mddev_t *mddev)
|
||||||
*/
|
*/
|
||||||
void md_check_recovery(mddev_t *mddev)
|
void md_check_recovery(mddev_t *mddev)
|
||||||
{
|
{
|
||||||
mdk_rdev_t *rdev;
|
|
||||||
|
|
||||||
|
|
||||||
if (mddev->bitmap)
|
if (mddev->bitmap)
|
||||||
bitmap_daemon_work(mddev);
|
bitmap_daemon_work(mddev);
|
||||||
|
|
||||||
|
@ -7138,34 +7173,7 @@ void md_check_recovery(mddev_t *mddev)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
if (mddev->sync_thread) {
|
if (mddev->sync_thread) {
|
||||||
/* resync has finished, collect result */
|
reap_sync_thread(mddev);
|
||||||
md_unregister_thread(mddev->sync_thread);
|
|
||||||
mddev->sync_thread = NULL;
|
|
||||||
if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
|
|
||||||
!test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
|
|
||||||
/* success...*/
|
|
||||||
/* activate any spares */
|
|
||||||
if (mddev->pers->spare_active(mddev))
|
|
||||||
sysfs_notify(&mddev->kobj, NULL,
|
|
||||||
"degraded");
|
|
||||||
}
|
|
||||||
if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
|
|
||||||
mddev->pers->finish_reshape)
|
|
||||||
mddev->pers->finish_reshape(mddev);
|
|
||||||
md_update_sb(mddev, 1);
|
|
||||||
|
|
||||||
/* if array is no-longer degraded, then any saved_raid_disk
|
|
||||||
* information must be scrapped
|
|
||||||
*/
|
|
||||||
if (!mddev->degraded)
|
|
||||||
list_for_each_entry(rdev, &mddev->disks, same_set)
|
|
||||||
rdev->saved_raid_disk = -1;
|
|
||||||
|
|
||||||
mddev->recovery = 0;
|
|
||||||
/* flag recovery needed just to double check */
|
|
||||||
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
|
|
||||||
sysfs_notify_dirent_safe(mddev->sysfs_action);
|
|
||||||
md_new_event(mddev);
|
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
/* Set RUNNING before clearing NEEDED to avoid
|
/* Set RUNNING before clearing NEEDED to avoid
|
||||||
|
@ -7223,7 +7231,11 @@ void md_check_recovery(mddev_t *mddev)
|
||||||
" thread...\n",
|
" thread...\n",
|
||||||
mdname(mddev));
|
mdname(mddev));
|
||||||
/* leave the spares where they are, it shouldn't hurt */
|
/* leave the spares where they are, it shouldn't hurt */
|
||||||
mddev->recovery = 0;
|
clear_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
|
||||||
|
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
|
||||||
|
clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
|
||||||
|
clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
|
||||||
|
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
|
||||||
} else
|
} else
|
||||||
md_wakeup_thread(mddev->sync_thread);
|
md_wakeup_thread(mddev->sync_thread);
|
||||||
sysfs_notify_dirent_safe(mddev->sysfs_action);
|
sysfs_notify_dirent_safe(mddev->sysfs_action);
|
||||||
|
|
Loading…
Reference in a new issue