Commit eaf9a736 authored by Mike Snitzer's avatar Mike Snitzer

dm: set DMF_SUSPENDED* _before_ clearing DMF_NOFLUSH_SUSPENDING

Otherwise, there is potential for both DMF_SUSPENDED* and
DMF_NOFLUSH_SUSPENDING to not be set during dm_suspend() -- which is
definitely _not_ a valid state.

This fix, in conjuction with "dm rq: fix the starting and stopping of
blk-mq queues", addresses the potential for request-based DM multipath's
__multipath_map() to see !dm_noflush_suspending() during suspend.
Reported-by: default avatarBart Van Assche <bart.vanassche@sandisk.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
Cc: stable@vger.kernel.org
parent 7d9595d8
...@@ -2082,7 +2082,8 @@ static void unlock_fs(struct mapped_device *md) ...@@ -2082,7 +2082,8 @@ static void unlock_fs(struct mapped_device *md)
* Caller must hold md->suspend_lock * Caller must hold md->suspend_lock
*/ */
static int __dm_suspend(struct mapped_device *md, struct dm_table *map, static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
unsigned suspend_flags, int interruptible) unsigned suspend_flags, int interruptible,
int dmf_suspended_flag)
{ {
bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG; bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG;
bool noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG; bool noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG;
...@@ -2149,6 +2150,8 @@ static int __dm_suspend(struct mapped_device *md, struct dm_table *map, ...@@ -2149,6 +2150,8 @@ static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
* to finish. * to finish.
*/ */
r = dm_wait_for_completion(md, interruptible); r = dm_wait_for_completion(md, interruptible);
if (!r)
set_bit(dmf_suspended_flag, &md->flags);
if (noflush) if (noflush)
clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags); clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
...@@ -2210,12 +2213,10 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) ...@@ -2210,12 +2213,10 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags)
map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock)); map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE); r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE, DMF_SUSPENDED);
if (r) if (r)
goto out_unlock; goto out_unlock;
set_bit(DMF_SUSPENDED, &md->flags);
dm_table_postsuspend_targets(map); dm_table_postsuspend_targets(map);
out_unlock: out_unlock:
...@@ -2309,9 +2310,8 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla ...@@ -2309,9 +2310,8 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla
* would require changing .presuspend to return an error -- avoid this * would require changing .presuspend to return an error -- avoid this
* until there is a need for more elaborate variants of internal suspend. * until there is a need for more elaborate variants of internal suspend.
*/ */
(void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE); (void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE,
DMF_SUSPENDED_INTERNALLY);
set_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
dm_table_postsuspend_targets(map); dm_table_postsuspend_targets(map);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment