aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2015-05-28 03:53:29 -0400
committerNeilBrown <neilb@suse.de>2015-05-28 04:04:45 -0400
commit56ccc1125bc141cf63927eda7febff4216dea2d3 (patch)
tree3af5cac150be4c0cf4d2e0d46dc9fba1328b8670 /drivers/md
parent626f2092c85ac847bb80b3257eb6a565dec32278 (diff)
md: fix race when unfreezing sync_action
A recent change removed the need for locking around writing to "sync_action" (and various other places), but introduced a subtle race. When e.g. setting 'reshape' on a 'frozen' array, the 'frozen' flag is cleared before 'reshape' is set, so the md thread can get in and start trying recovery - which isn't wanted. So instead of clearing MD_RECOVERY_FROZEN for any command except 'frozen', only clear it when each specific command is parsed. This allows the handling of 'reshape' to clear the bit while a lock is held. Also remove some places where we set MD_RECOVERY_NEEDED, as it is always set on non-error exit of the function. Signed-off-by: NeilBrown <neilb@suse.de> Fixes: 6791875e2e53 ("md: make reconfig_mutex optional for writes to md sysfs files.")
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/md.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index d4f31e195e26..8f10f4ea70ea 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4211,12 +4211,12 @@ action_store(struct mddev *mddev, const char *page, size_t len)
4211 if (!mddev->pers || !mddev->pers->sync_request) 4211 if (!mddev->pers || !mddev->pers->sync_request)
4212 return -EINVAL; 4212 return -EINVAL;
4213 4213
4214 if (cmd_match(page, "frozen"))
4215 set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
4216 else
4217 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
4218 4214
4219 if (cmd_match(page, "idle") || cmd_match(page, "frozen")) { 4215 if (cmd_match(page, "idle") || cmd_match(page, "frozen")) {
4216 if (cmd_match(page, "frozen"))
4217 set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
4218 else
4219 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
4220 flush_workqueue(md_misc_wq); 4220 flush_workqueue(md_misc_wq);
4221 if (mddev->sync_thread) { 4221 if (mddev->sync_thread) {
4222 set_bit(MD_RECOVERY_INTR, &mddev->recovery); 4222 set_bit(MD_RECOVERY_INTR, &mddev->recovery);
@@ -4229,16 +4229,17 @@ action_store(struct mddev *mddev, const char *page, size_t len)
4229 test_bit(MD_RECOVERY_NEEDED, &mddev->recovery)) 4229 test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
4230 return -EBUSY; 4230 return -EBUSY;
4231 else if (cmd_match(page, "resync")) 4231 else if (cmd_match(page, "resync"))
4232 set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); 4232 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
4233 else if (cmd_match(page, "recover")) { 4233 else if (cmd_match(page, "recover")) {
4234 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
4234 set_bit(MD_RECOVERY_RECOVER, &mddev->recovery); 4235 set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
4235 set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
4236 } else if (cmd_match(page, "reshape")) { 4236 } else if (cmd_match(page, "reshape")) {
4237 int err; 4237 int err;
4238 if (mddev->pers->start_reshape == NULL) 4238 if (mddev->pers->start_reshape == NULL)
4239 return -EINVAL; 4239 return -EINVAL;
4240 err = mddev_lock(mddev); 4240 err = mddev_lock(mddev);
4241 if (!err) { 4241 if (!err) {
4242 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
4242 err = mddev->pers->start_reshape(mddev); 4243 err = mddev->pers->start_reshape(mddev);
4243 mddev_unlock(mddev); 4244 mddev_unlock(mddev);
4244 } 4245 }
@@ -4250,6 +4251,7 @@ action_store(struct mddev *mddev, const char *page, size_t len)
4250 set_bit(MD_RECOVERY_CHECK, &mddev->recovery); 4251 set_bit(MD_RECOVERY_CHECK, &mddev->recovery);
4251 else if (!cmd_match(page, "repair")) 4252 else if (!cmd_match(page, "repair"))
4252 return -EINVAL; 4253 return -EINVAL;
4254 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
4253 set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); 4255 set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
4254 set_bit(MD_RECOVERY_SYNC, &mddev->recovery); 4256 set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
4255 } 4257 }