This is a note to let you know that I've just added the patch titled md: fix test in md_write_start() to the 4.12-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: md-fix-test-in-md_write_start.patch and it can be found in the queue-4.12 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From 81fe48e9aa00bdd509bd3c37a76d1132da6b9f09 Mon Sep 17 00:00:00 2001 From: NeilBrown <neilb@xxxxxxxx> Date: Tue, 8 Aug 2017 16:56:36 +1000 Subject: md: fix test in md_write_start() From: NeilBrown <neilb@xxxxxxxx> commit 81fe48e9aa00bdd509bd3c37a76d1132da6b9f09 upstream. md_write_start() needs to clear the in_sync flag is it is set, or if there might be a race with set_in_sync() such that the later will set it very soon. In the later case it is sufficient to take the spinlock to synchronize with set_in_sync(), and then set the flag if needed. The current test is incorrect. It should be: if "flag is set" or "race is possible" "flag is set" is trivially "mddev->in_sync". "race is possible" should be tested by "mddev->sync_checkers". If sync_checkers is 0, then there can be no race. set_in_sync() will wait in percpu_ref_switch_to_atomic_sync() for an RCU grace period, and as md_write_start() holds the rcu_read_lock(), set_in_sync() will be sure ot see the update to writes_pending. If sync_checkers is > 0, there could be race. If md_write_start() happened entirely between if (!mddev->in_sync && percpu_ref_is_zero(&mddev->writes_pending)) { and mddev->in_sync = 1; in set_in_sync(), then it would not see that is_sync had been set, and set_in_sync() would not see that writes_pending had been incremented. This bug means that in_sync is sometimes not set when it should be. Consequently there is a small chance that the array will be marked as "clean" when in fact it is inconsistent. Fixes: 4ad23a976413 ("MD: use per-cpu counter for writes_pending") Signed-off-by: NeilBrown <neilb@xxxxxxxx> Signed-off-by: Shaohua Li <shli@xxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7979,7 +7979,7 @@ bool md_write_start(struct mddev *mddev, if (mddev->safemode == 1) mddev->safemode = 0; /* sync_checkers is always 0 when writes_pending is in per-cpu mode */ - if (mddev->in_sync || !mddev->sync_checkers) { + if (mddev->in_sync || mddev->sync_checkers) { spin_lock(&mddev->lock); if (mddev->in_sync) { mddev->in_sync = 0; Patches currently in stable-queue which might be from neilb@xxxxxxxx are queue-4.12/md-not-clear-safemode-for-external-metadata-array.patch queue-4.12/md-always-clear-safemode-when-md_check_recovery-gets-the-mddev-lock.patch queue-4.12/md-fix-test-in-md_write_start.patch