do_resume when loading a new map first calls dm_suspend, which could silently fail. When we proceeded to dm_swap_table, we would bail out with EINVAL. Instead, restore new_map and return ERESTARTSYS when signaled. Signed-off-by: Khazhismel Kumykov <khazhy@xxxxxxxxxx> --- drivers/md/dm-ioctl.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) RFC as I am rather unfamiliar with the locking semantics here - whether we do need to re-grab hash_lock to write to an hc we previously grabbed, and whether the device becoming unhashed while we're in this function is really something that needs to be checked. However, this patch does fix the issue we were seeing - we'd get EINVAL when thread in ioctl was signaled. diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index c2c07bfa6471..b81650c6d096 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1181,8 +1181,22 @@ static int do_resume(struct dm_ioctl *param) suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG; if (param->flags & DM_NOFLUSH_FLAG) suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG; - if (!dm_suspended_md(md)) - dm_suspend(md, suspend_flags); + if (!dm_suspended_md(md)) { + r = dm_suspend(md, suspend_flags); + if (r == -EINTR) + r = -ERESTARTSYS; + if (r) { + down_write(&_hash_lock); + hc = dm_get_mdptr(md); + if (!hc) + r = -ENXIO; + else + hc->new_map = new_map; + up_write(&_hash_lock); + dm_put(md); + return r; + } + } old_size = dm_get_size(md); old_map = dm_swap_table(md, new_map); -- 2.45.2.993.g49e7a77208-goog