diff options
author | NeilBrown <neilb@suse.com> | 2017-10-18 21:17:16 -0400 |
---|---|---|
committer | Shaohua Li <shli@fb.com> | 2017-11-02 00:32:18 -0400 |
commit | 4d5324f760aacaefeb721b172aa14bf66045c332 (patch) | |
tree | 4115e3a5b37b7890c402d07ce551648b93f63844 /drivers/md/dm-raid.c | |
parent | 230b55fa8d64007339319539f8f8e68114d08529 (diff) |
md: always hold reconfig_mutex when calling mddev_suspend()
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>
Diffstat (limited to 'drivers/md/dm-raid.c')
-rw-r--r-- | drivers/md/dm-raid.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 252770696a05..8b1d93114f40 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -3628,8 +3628,11 @@ static void raid_postsuspend(struct dm_target *ti) | |||
3628 | { | 3628 | { |
3629 | struct raid_set *rs = ti->private; | 3629 | struct raid_set *rs = ti->private; |
3630 | 3630 | ||
3631 | if (!test_and_set_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags)) | 3631 | if (!test_and_set_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags)) { |
3632 | mddev_lock_nointr(&rs->md); | ||
3632 | mddev_suspend(&rs->md); | 3633 | mddev_suspend(&rs->md); |
3634 | mddev_unlock(&rs->md); | ||
3635 | } | ||
3633 | 3636 | ||
3634 | rs->md.ro = 1; | 3637 | rs->md.ro = 1; |
3635 | } | 3638 | } |
@@ -3886,8 +3889,11 @@ static void raid_resume(struct dm_target *ti) | |||
3886 | if (!(rs->ctr_flags & RESUME_STAY_FROZEN_FLAGS)) | 3889 | if (!(rs->ctr_flags & RESUME_STAY_FROZEN_FLAGS)) |
3887 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); | 3890 | clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); |
3888 | 3891 | ||
3889 | if (test_and_clear_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags)) | 3892 | if (test_and_clear_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags)) { |
3893 | mddev_lock_nointr(mddev); | ||
3890 | mddev_resume(mddev); | 3894 | mddev_resume(mddev); |
3895 | mddev_unlock(mddev); | ||
3896 | } | ||
3891 | } | 3897 | } |
3892 | 3898 | ||
3893 | static struct target_type raid_target = { | 3899 | static struct target_type raid_target = { |