]> git.itanic.dy.fi Git - linux-stable/commitdiff
dm: update targets using system workqueues to use a local workqueue
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Wed, 20 Apr 2022 05:12:26 +0000 (14:12 +0900)
committerMike Snitzer <snitzer@kernel.org>
Tue, 14 Feb 2023 19:23:08 +0000 (14:23 -0500)
Flushing system-wide workqueues is dangerous and will be forbidden.
Use a local workqueue in dm-mpath.c, dm-raid1.c, and dm-stripe.c.

Link: https://lkml.kernel.org/r/49925af7-78a8-a3dd-bce6-cfc02e1a9236@I-love.SAKURA.ne.jp
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
drivers/md/dm-mpath.c
drivers/md/dm-raid1.c
drivers/md/dm-stripe.c

index 371a38bc0c6117940d956e23a1d536e2e306c74a..61ab1a8d2c9c449896a730d4ac9f31aa3ed579c4 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/atomic.h>
 #include <linux/blk-mq.h>
 
+static struct workqueue_struct *dm_mpath_wq;
+
 #define DM_MSG_PREFIX "multipath"
 #define DM_PG_INIT_DELAY_MSECS 2000
 #define DM_PG_INIT_DELAY_DEFAULT ((unsigned int) -1)
@@ -1353,7 +1355,7 @@ static int fail_path(struct pgpath *pgpath)
        dm_path_uevent(DM_UEVENT_PATH_FAILED, m->ti,
                       pgpath->path.dev->name, atomic_read(&m->nr_valid_paths));
 
-       schedule_work(&m->trigger_event);
+       queue_work(dm_mpath_wq, &m->trigger_event);
 
        enable_nopath_timeout(m);
 
@@ -2205,12 +2207,11 @@ static struct target_type multipath_target = {
 
 static int __init dm_multipath_init(void)
 {
-       int r;
+       int r = -ENOMEM;
 
        kmultipathd = alloc_workqueue("kmpathd", WQ_MEM_RECLAIM, 0);
        if (!kmultipathd) {
                DMERR("failed to create workqueue kmpathd");
-               r = -ENOMEM;
                goto bad_alloc_kmultipathd;
        }
 
@@ -2224,10 +2225,15 @@ static int __init dm_multipath_init(void)
                                                  WQ_MEM_RECLAIM);
        if (!kmpath_handlerd) {
                DMERR("failed to create workqueue kmpath_handlerd");
-               r = -ENOMEM;
                goto bad_alloc_kmpath_handlerd;
        }
 
+       dm_mpath_wq = alloc_workqueue("dm_mpath_wq", 0, 0);
+       if (!dm_mpath_wq) {
+               DMERR("failed to create workqueue dm_mpath_wq");
+               goto bad_alloc_dm_mpath_wq;
+       }
+
        r = dm_register_target(&multipath_target);
        if (r < 0) {
                DMERR("request-based register failed %d", r);
@@ -2238,6 +2244,8 @@ static int __init dm_multipath_init(void)
        return 0;
 
 bad_register_target:
+       destroy_workqueue(dm_mpath_wq);
+bad_alloc_dm_mpath_wq:
        destroy_workqueue(kmpath_handlerd);
 bad_alloc_kmpath_handlerd:
        destroy_workqueue(kmultipathd);
@@ -2247,6 +2255,7 @@ static int __init dm_multipath_init(void)
 
 static void __exit dm_multipath_exit(void)
 {
+       destroy_workqueue(dm_mpath_wq);
        destroy_workqueue(kmpath_handlerd);
        destroy_workqueue(kmultipathd);
 
index b20c0ad13712c24d38596022d944b5265667b1f4..bc417a5e5b892f5c70389a08db50498f96a2efa2 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/dm-kcopyd.h>
 #include <linux/dm-region-hash.h>
 
+static struct workqueue_struct *dm_raid1_wq;
+
 #define DM_MSG_PREFIX "raid1"
 
 #define MAX_RECOVERY 1 /* Maximum number of regions recovered in parallel. */
@@ -251,7 +253,7 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type)
                DMWARN("All sides of mirror have failed.");
 
 out:
-       schedule_work(&ms->trigger_event);
+       queue_work(dm_raid1_wq, &ms->trigger_event);
 }
 
 static int mirror_flush(struct dm_target *ti)
@@ -1496,22 +1498,28 @@ static struct target_type mirror_target = {
 
 static int __init dm_mirror_init(void)
 {
-       int r;
+       int r = -ENOMEM;
+
+       dm_raid1_wq = alloc_workqueue("dm_raid1_wq", 0, 0);
+       if (!dm_raid1_wq)
+               goto bad_target;
 
        r = dm_register_target(&mirror_target);
        if (r < 0) {
-               DMERR("Failed to register mirror target");
+               destroy_workqueue(dm_raid1_wq);
                goto bad_target;
        }
 
        return 0;
 
 bad_target:
+       DMERR("Failed to register mirror target");
        return r;
 }
 
 static void __exit dm_mirror_exit(void)
 {
+       destroy_workqueue(dm_raid1_wq);
        dm_unregister_target(&mirror_target);
 }
 
index 4335828a43e424c86c7c50f356b313a05eb01d8d..8d69511571068c04734145918a549fd267757d80 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/slab.h>
 #include <linux/log2.h>
 
+static struct workqueue_struct *dm_stripe_wq;
+
 #define DM_MSG_PREFIX "striped"
 #define DM_IO_ERROR_THRESHOLD 15
 
@@ -428,7 +430,7 @@ static int stripe_end_io(struct dm_target *ti, struct bio *bio,
                        atomic_inc(&(sc->stripe[i].error_count));
                        if (atomic_read(&(sc->stripe[i].error_count)) <
                            DM_IO_ERROR_THRESHOLD)
-                               schedule_work(&sc->trigger_event);
+                               queue_work(dm_stripe_wq, &sc->trigger_event);
                }
 
        return DM_ENDIO_DONE;
@@ -481,9 +483,14 @@ int __init dm_stripe_init(void)
 {
        int r;
 
+       dm_stripe_wq = alloc_workqueue("dm_stripe_wq", 0, 0);
+       if (!dm_stripe_wq)
+               return -ENOMEM;
        r = dm_register_target(&stripe_target);
-       if (r < 0)
+       if (r < 0) {
+               destroy_workqueue(dm_stripe_wq);
                DMWARN("target registration failed");
+       }
 
        return r;
 }
@@ -491,4 +498,5 @@ int __init dm_stripe_init(void)
 void dm_stripe_exit(void)
 {
        dm_unregister_target(&stripe_target);
+       destroy_workqueue(dm_stripe_wq);
 }