The command "dmsetup remove_all" may take a long time (a minute for removing 1000 devices), so make it interruptible with fatal signals.
Signed-off-by: Mikulas Patocka <[email protected]> --- drivers/md/dm-ioctl.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) Index: linux-2.6/drivers/md/dm-ioctl.c =================================================================== --- linux-2.6.orig/drivers/md/dm-ioctl.c 2026-03-16 14:37:37.000000000 +0100 +++ linux-2.6/drivers/md/dm-ioctl.c 2026-03-16 16:44:46.000000000 +0100 @@ -64,7 +64,7 @@ struct vers_iter { static struct rb_root name_rb_tree = RB_ROOT; static struct rb_root uuid_rb_tree = RB_ROOT; -static void dm_hash_remove_all(bool keep_open_devices, bool mark_deferred, bool only_deferred); +static int dm_hash_remove_all(bool keep_open_devices, bool mark_deferred, bool only_deferred, bool interruptible); /* * Guards access to both hash tables. @@ -78,7 +78,7 @@ static DEFINE_MUTEX(dm_hash_cells_mutex) static void dm_hash_exit(void) { - dm_hash_remove_all(false, false, false); + dm_hash_remove_all(false, false, false, false); } /* @@ -333,7 +333,7 @@ static struct dm_table *__hash_remove(st return table; } -static void dm_hash_remove_all(bool keep_open_devices, bool mark_deferred, bool only_deferred) +static int dm_hash_remove_all(bool keep_open_devices, bool mark_deferred, bool only_deferred, bool interruptible) { int dev_skipped; struct rb_node *n; @@ -347,6 +347,11 @@ retry: down_write(&_hash_lock); for (n = rb_first(&name_rb_tree); n; n = rb_next(n)) { + if (interruptible && fatal_signal_pending(current)) { + up_write(&_hash_lock); + return -EINTR; + } + hc = container_of(n, struct hash_cell, name_node); md = hc->md; dm_get(md); @@ -386,6 +391,8 @@ retry: if (dev_skipped && !only_deferred) DMWARN("remove_all left %d open device(s)", dev_skipped); + + return 0; } /* @@ -513,7 +520,7 @@ static struct mapped_device *dm_hash_ren void dm_deferred_remove(void) { - dm_hash_remove_all(true, false, true); + dm_hash_remove_all(true, false, true, false); } /* @@ -529,9 +536,9 @@ typedef int (*ioctl_fn)(struct file *fil static int remove_all(struct file *filp, struct dm_ioctl *param, size_t param_size) { - dm_hash_remove_all(true, !!(param->flags & DM_DEFERRED_REMOVE), false); + int r = dm_hash_remove_all(true, !!(param->flags & DM_DEFERRED_REMOVE), false, true); param->data_size = 0; - return 0; + return r; } /*
