aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.com>2015-12-20 19:01:21 -0500
committerNeilBrown <neilb@suse.com>2015-12-20 19:10:06 -0500
commit312045eef985b61d74c28047ecd8eca6719d9516 (patch)
tree10e0c0b1ea968e006a35180d2e18bf412da8950b
parent9f7e43278605a0daf4edf7025c52c25e9ace6875 (diff)
md: remove check for MD_RECOVERY_NEEDED in action_store.
md currently doesn't allow a 'sync_action' such as 'reshape' to be set while MD_RECOVERY_NEEDED is set. This s a problem, particularly since commit 738a273806ee as that can cause ->check_shape to call mddev_resume() which sets MD_RECOVERY_NEEDED. So by the time we come to start 'reshape' it is very likely that MD_RECOVERY_NEEDED is still set. Testing for this flag is not really needed and is in any case very racy as it can be set at any moment - asynchronously. Any race between setting a sync_action and setting MD_RECOVERY_NEEDED must already be handled properly in some locked code, probably md_check_recovery(), so remove the test here. The test on MD_RECOVERY_RUNNING is also racy in the 'reshape' case so we should test it again after getting mddev_lock(). As this fixes a race and a regression which can cause 'reshape' to fail, it is suitable for -stable kernels since 4.1 Reported-by: Xiao Ni <xni@redhat.com> Fixes: 738a273806ee ("md/raid5: fix allocation of 'scribble' array.") Cc: stable@vger.kernel.org (v4.1+) Signed-off-by: NeilBrown <neilb@suse.com>
-rw-r--r--drivers/md/md.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index dbedc58d8c00..61aacab424cf 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4326,8 +4326,7 @@ action_store(struct mddev *mddev, const char *page, size_t len)
4326 } 4326 }
4327 mddev_unlock(mddev); 4327 mddev_unlock(mddev);
4328 } 4328 }
4329 } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || 4329 } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
4330 test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
4331 return -EBUSY; 4330 return -EBUSY;
4332 else if (cmd_match(page, "resync")) 4331 else if (cmd_match(page, "resync"))
4333 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); 4332 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -4340,8 +4339,12 @@ action_store(struct mddev *mddev, const char *page, size_t len)
4340 return -EINVAL; 4339 return -EINVAL;
4341 err = mddev_lock(mddev); 4340 err = mddev_lock(mddev);
4342 if (!err) { 4341 if (!err) {
4343 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); 4342 if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
4344 err = mddev->pers->start_reshape(mddev); 4343 err = -EBUSY;
4344 else {
4345 clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
4346 err = mddev->pers->start_reshape(mddev);
4347 }
4345 mddev_unlock(mddev); 4348 mddev_unlock(mddev);
4346 } 4349 }
4347 if (err) 4350 if (err)