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;
 }
 
 /*


Reply via email to