Skip to content

Commit 7a636b4

Browse files
khazhykMikulas Patocka
authored andcommitted
dm resume: don't return EINVAL when signalled
If the dm_resume method is called on a device that is not suspended, the method will suspend the device briefly, before resuming it (so that the table will be swapped). However, there was a bug that the return value of dm_suspended_md was not checked. dm_suspended_md may return an error when it is interrupted by a signal. In this case, do_resume would call dm_swap_table, which would return -EINVAL. This commit fixes the logic, so that error returned by dm_suspend is checked and the resume operation is undone. Signed-off-by: Mikulas Patocka <[email protected]> Signed-off-by: Khazhismel Kumykov <[email protected]> Cc: [email protected]
1 parent 1e1fd56 commit 7a636b4

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

drivers/md/dm-ioctl.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,8 +1181,26 @@ static int do_resume(struct dm_ioctl *param)
11811181
suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
11821182
if (param->flags & DM_NOFLUSH_FLAG)
11831183
suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
1184-
if (!dm_suspended_md(md))
1185-
dm_suspend(md, suspend_flags);
1184+
if (!dm_suspended_md(md)) {
1185+
r = dm_suspend(md, suspend_flags);
1186+
if (r) {
1187+
down_write(&_hash_lock);
1188+
hc = dm_get_mdptr(md);
1189+
if (hc && !hc->new_map) {
1190+
hc->new_map = new_map;
1191+
new_map = NULL;
1192+
} else {
1193+
r = -ENXIO;
1194+
}
1195+
up_write(&_hash_lock);
1196+
if (new_map) {
1197+
dm_sync_table(md);
1198+
dm_table_destroy(new_map);
1199+
}
1200+
dm_put(md);
1201+
return r;
1202+
}
1203+
}
11861204

11871205
old_size = dm_get_size(md);
11881206
old_map = dm_swap_table(md, new_map);

0 commit comments

Comments
 (0)