md: always hold reconfig_mutex when calling mddev_suspend()
authorNeilBrown <neilb@suse.com>
Thu, 19 Oct 2017 01:17:16 +0000 (12:17 +1100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 8 Jul 2018 13:30:49 +0000 (15:30 +0200)
commite44e4cf3a8dbfee3f6e078f254c26e5a5168c6a2
tree1aebf0a888142ac29c33c2b2d031aa7d1a6014ba
parentb8d8cde449fd51db0bb407dece03d36ced1acb83
md: always hold reconfig_mutex when calling mddev_suspend()

commit 4d5324f760aacaefeb721b172aa14bf66045c332 upstream.

Most often mddev_suspend() is called with
reconfig_mutex held.  Make this a requirement in
preparation a subsequent patch.  Also require
reconfig_mutex to be held for mddev_resume(),
partly for symmetry and partly to guarantee
no races with incr/decr of mddev->suspend.

Taking the mutex in r5c_disable_writeback_async() is
a little tricky as this is called from a work queue
via log->disable_writeback_work, and flush_work()
is called on that while holding ->reconfig_mutex.
If the work item hasn't run before flush_work()
is called, the work function will not be able to
get the mutex.

So we use mddev_trylock() inside the wait_event() call, and have that
abort when conf->log is set to NULL, which happens before
flush_work() is called.
We wait in mddev->sb_wait and ensure this is woken
when any of the conditions change.  This requires
waking mddev->sb_wait in mddev_unlock().  This is only
like to trigger extra wake_ups of threads that needn't
be woken when metadata is being written, and that
doesn't happen often enough that the cost would be
noticeable.

Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Shaohua Li <shli@fb.com>
Signed-off-by: Jack Wang <jinpu.wang@profitbricks.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/md/dm-raid.c
drivers/md/md.c
drivers/md/raid5-cache.c