OSDN Git Service

raid1: prevent freeze_array/wait_all_barriers deadlock
authorNate Dailey <nate.dailey@stratus.com>
Tue, 17 Oct 2017 12:17:03 +0000 (08:17 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 30 Nov 2017 08:40:52 +0000 (08:40 +0000)
commitd92105f93aeb2c80f6840bed9af71d3f97321916
treeff37eaf33d92ff5b81331115b371c3568c793334
parent77a38e88ccbc9e6451333f742b18d0fe5176c5cd
raid1: prevent freeze_array/wait_all_barriers deadlock

commit f6eca2d43ed694ab8124dd24c88277f7eca93b7d upstream.

If freeze_array is attempted in the middle of close_sync/
wait_all_barriers, deadlock can occur.

freeze_array will wait for nr_pending and nr_queued to line up.
wait_all_barriers increments nr_pending for each barrier bucket, one
at a time, but doesn't actually issue IO that could be counted in
nr_queued. So freeze_array is blocked until wait_all_barriers
completes and allow_all_barriers runs. At the same time, when
_wait_barrier sees array_frozen == 1, it stops and waits for
freeze_array to complete.

Prevent the deadlock by making close_sync call _wait_barrier and
_allow_barrier for one bucket at a time, instead of deferring the
_allow_barrier calls until after all _wait_barriers are complete.

Signed-off-by: Nate Dailey <nate.dailey@stratus.com>
Fix: fd76863e37fe(RAID1: a new I/O barrier implementation to remove resync window)
Reviewed-by: Coly Li <colyli@suse.de>
Signed-off-by: Shaohua Li <shli@fb.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/md/raid1.c