dm-crypt: Convert from tasklet to BH workqueue
authorTejun Heo <tj@kernel.org>
Tue, 30 Jan 2024 09:11:54 +0000 (23:11 -1000)
committerMike Snitzer <snitzer@kernel.org>
Sat, 2 Mar 2024 15:30:36 +0000 (10:30 -0500)
The only generic interface to execute asynchronously in the BH context is
tasklet; however, it's marked deprecated and has some design flaws. To
replace tasklets, BH workqueue support was recently added. A BH workqueue
behaves similarly to regular workqueues except that the queued work items
are executed in the BH context.

This commit converts dm-crypt from tasklet to BH workqueue.  It
backfills tasklet code that was removed with commit 0a9bab391e33
("dm-crypt, dm-verity: disable tasklets") and tweaks to use BH
workqueue.

Like a regular workqueue, a BH workqueue allows freeing the currently
executing work item. Converting from tasklet to BH workqueue removes the
need for deferring bio_endio() again to a work item, which was buggy anyway.

I tested this lightly with "--perf-no_read_workqueue
--perf-no_write_workqueue" + some code modifications, but would really
-appreciate if someone who knows the code base better could take a look.

Signed-off-by: Tejun Heo <tj@kernel.org>
Link: http://lkml.kernel.org/r/82b964f0-c2c8-a2c6-5b1f-f3145dc2c8e5@redhat.com
[snitzer: rebase ontop of commit 0a9bab391e33 reduced this commit's changes]
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
drivers/md/dm-crypt.c

index 50467f005177c67b6ae04f0844dee4f81f450904..9a74c6316c5da65ab306607fd7a88c8dba154a1b 100644 (file)
@@ -2296,7 +2296,11 @@ static void kcryptd_queue_crypt(struct dm_crypt_io *io)
                 * irqs_disabled(): the kernel may run some IO completion from the idle thread, but
                 * it is being executed with irqs disabled.
                 */
-               if (!(in_hardirq() || irqs_disabled())) {
+               if (in_hardirq() || irqs_disabled()) {
+                       INIT_WORK(&io->work, kcryptd_crypt);
+                       queue_work(system_bh_wq, &io->work);
+                       return;
+               } else {
                        kcryptd_crypt(&io->work);
                        return;
                }