md: fix deadlock between mddev_suspend() and md_write_start()
authorNeilBrown <neilb@suse.com>
Mon, 5 Jun 2017 06:49:39 +0000 (16:49 +1000)
committerShaohua Li <shli@fb.com>
Tue, 13 Jun 2017 17:18:01 +0000 (10:18 -0700)
commitcc27b0c78c79680d128dbac79de0d40556d041bb
tree1f32d4acd29d825eecc1aef90d423cdacea8121c
parent63f700aab4c11d46626de3cd051dae56cf7e9056
md: fix deadlock between mddev_suspend() and md_write_start()

If mddev_suspend() races with md_write_start() we can deadlock
with mddev_suspend() waiting for the request that is currently
in md_write_start() to complete the ->make_request() call,
and md_write_start() waiting for the metadata to be updated
to mark the array as 'dirty'.
As metadata updates done by md_check_recovery() only happen then
the mddev_lock() can be claimed, and as mddev_suspend() is often
called with the lock held, these threads wait indefinitely for each
other.

We fix this by having md_write_start() abort if mddev_suspend()
is happening, and ->make_request() aborts if md_write_start()
aborted.
md_make_request() can detect this abort, decrease the ->active_io
count, and wait for mddev_suspend().

Reported-by: Nix <nix@esperi.org.uk>
Fix: 68866e425be2(MD: no sync IO while suspended)
Cc: stable@vger.kernel.org
Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Shaohua Li <shli@fb.com>
drivers/md/faulty.c
drivers/md/linear.c
drivers/md/md.c
drivers/md/md.h
drivers/md/multipath.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c