diff options
author | NeilBrown <neilb@suse.de> | 2014-10-28 17:49:50 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2014-11-16 17:17:46 -0500 |
commit | 45eaf45dfa4850df16bc2e8e7903d89021137f40 (patch) | |
tree | 623ac0e21c0f21c851c4dcffe8b317d41aafdb98 | |
parent | 206c5f60a3d902bc4b56dab2de3e88de5eb06108 (diff) |
md: Always set RECOVERY_NEEDED when clearing RECOVERY_FROZEN
md_check_recovery will skip any recovery and also clear
MD_RECOVERY_NEEDED if MD_RECOVERY_FROZEN is set.
So when we clear _FROZEN, we must set _NEEDED and ensure that
md_check_recovery gets run.
Otherwise we could miss out on something that is needed.
In particular, this can make it impossible to remove a
failed device from an array is the 'recovery-needed' processing
didn't happen.
Suitable for stable kernels since 3.13.
Cc: stable@vger.kernel.org (3.13+)
Reported-and-tested-by: Joe Lawrence <joe.lawrence@stratus.com>
Fixes: 30b8feb730f9b9b3c5de02580897da03f59b6b16
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | drivers/md/md.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 4dfa15da9cb8..9233c71138f1 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -5121,6 +5121,7 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) | |||
5121 | printk("md: %s still in use.\n",mdname(mddev)); | 5121 | printk("md: %s still in use.\n",mdname(mddev)); |
5122 | if (did_freeze) { | 5122 | if (did_freeze) { |
5123 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); | 5123 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); |
5124 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
5124 | md_wakeup_thread(mddev->thread); | 5125 | md_wakeup_thread(mddev->thread); |
5125 | } | 5126 | } |
5126 | err = -EBUSY; | 5127 | err = -EBUSY; |
@@ -5135,6 +5136,8 @@ static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) | |||
5135 | mddev->ro = 1; | 5136 | mddev->ro = 1; |
5136 | set_disk_ro(mddev->gendisk, 1); | 5137 | set_disk_ro(mddev->gendisk, 1); |
5137 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); | 5138 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); |
5139 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
5140 | md_wakeup_thread(mddev->thread); | ||
5138 | sysfs_notify_dirent_safe(mddev->sysfs_state); | 5141 | sysfs_notify_dirent_safe(mddev->sysfs_state); |
5139 | err = 0; | 5142 | err = 0; |
5140 | } | 5143 | } |
@@ -5178,6 +5181,7 @@ static int do_md_stop(struct mddev *mddev, int mode, | |||
5178 | mutex_unlock(&mddev->open_mutex); | 5181 | mutex_unlock(&mddev->open_mutex); |
5179 | if (did_freeze) { | 5182 | if (did_freeze) { |
5180 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); | 5183 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); |
5184 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | ||
5181 | md_wakeup_thread(mddev->thread); | 5185 | md_wakeup_thread(mddev->thread); |
5182 | } | 5186 | } |
5183 | return -EBUSY; | 5187 | return -EBUSY; |