]> git.baikalelectronics.ru Git - kernel.git/commit
md: always clear ->safemode when md_check_recovery gets the mddev lock.
authorNeilBrown <neilb@suse.com>
Tue, 8 Aug 2017 06:56:36 +0000 (16:56 +1000)
committerShaohua Li <shli@fb.com>
Tue, 8 Aug 2017 14:42:35 +0000 (07:42 -0700)
commitea93d1a80ccbf3fb2ab79b6e9354472031497d19
tree3474674380ae8c826eb5f19d36da994464535345
parent8b74f4f4576ba4882ca9e92e5c3794c2476fd0af
md: always clear ->safemode when md_check_recovery gets the mddev lock.

If ->safemode == 1, md_check_recovery() will try to get the mddev lock
and perform various other checks.
If mddev->in_sync is zero, it will call set_in_sync, and clear
->safemode.  However if mddev->in_sync is not zero, ->safemode will not
be cleared.

When md_check_recovery() drops the mddev lock, the thread is woken
up again.  Normally it would just check if there was anything else to
do, find nothing, and go to sleep.  However as ->safemode was not
cleared, it will take the mddev lock again, then wake itself up
when unlocking.

This results in an infinite loop, repeatedly calling
md_check_recovery(), which RCU or the soft-lockup detector
will eventually complain about.

Prior to commit b91e58edf442 ("MD: use per-cpu counter for
writes_pending"), safemode would only be set to one when the
writes_pending counter reached zero, and would be cleared again
when writes_pending is incremented.  Since that patch, safemode
is set more freely, but is not reliably cleared.

So in md_check_recovery() clear ->safemode before checking ->in_sync.

Fixes: b91e58edf442 ("MD: use per-cpu counter for writes_pending")
Cc: stable@vger.kernel.org (4.12+)
Reported-by: Dominik Brodowski <linux@dominikbrodowski.net>
Reported-by: David R <david@unsolicited.net>
Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Shaohua Li <shli@fb.com>
drivers/md/md.c