From: Li Lingfeng lilingfeng3@huawei.com
mainline inclusion from mainline-v6.4-rc8 commit 2760904d895279f87196f0fa9ec570c79fe6a2e4 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7FI5Z CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h...
----------------------------------------
As described in commit 38d11da522aa ("dm: don't lock fs when the map is NULL in process of resume"), a deadlock may be triggered between do_resume() and do_mount().
This commit preserves the fix from commit 38d11da522aa but moves it to where it also serves to fix a similar deadlock between do_suspend() and do_mount(). It does so, if the active map is NULL, by clearing DM_SUSPEND_LOCKFS_FLAG in dm_suspend() which is called by both do_suspend() and do_resume().
Fixes: 38d11da522aa ("dm: don't lock fs when the map is NULL in process of resume") Signed-off-by: Li Lingfeng lilingfeng3@huawei.com Signed-off-by: Mike Snitzer snitzer@kernel.org
Conflicts: drivers/md/dm-ioctl.c Signed-off-by: Li Lingfeng lilingfeng3@huawei.com Reviewed-by: Yu Kuai yukuai3@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- drivers/md/dm-ioctl.c | 6 +----- drivers/md/dm.c | 4 ++++ 2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 3af982ed8424..c8c27d23bb45 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1034,13 +1034,9 @@ static int do_resume(struct dm_ioctl *param)
/* Do we need to load a new map ? */ if (new_map) { - int srcu_idx; - /* Suspend if it isn't already suspended */ - old_map = dm_get_live_table(md, &srcu_idx); - if (param->flags & DM_SKIP_LOCKFS_FLAG || !old_map) + if (param->flags & DM_SKIP_LOCKFS_FLAG) suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG; - dm_put_live_table(md, srcu_idx); if (param->flags & DM_NOFLUSH_FLAG) suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; if (!dm_suspended_md(md)) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 326b3ea2a21f..0aa6fd33abf1 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -2747,6 +2747,10 @@ int dm_suspend(struct mapped_device *md, unsigned suspend_flags) }
map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock)); + if (!map) { + /* avoid deadlock with fs/namespace.c:do_mount() */ + suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG; + }
r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE, DMF_SUSPENDED); if (r)