Skip to content

Commit c0499a0

Browse files
committed
Merge tag 'for-6.9/dm-bh-wq' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper BH workqueue conversion from Mike Snitzer: "Convert the DM verity and crypt targets from (ab)using tasklets to using BH workqueues. These changes were coordinated with Tejun and are based ontop of DM's 6.9 changes and Tejun's 6.9 workqueue tree" * tag 'for-6.9/dm-bh-wq' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm-verity: Convert from tasklet to BH workqueue dm-crypt: Convert from tasklet to BH workqueue
2 parents d2bac08 + c375b22 commit c0499a0

File tree

3 files changed

+50
-25
lines changed

3 files changed

+50
-25
lines changed

drivers/md/dm-crypt.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2296,7 +2296,11 @@ static void kcryptd_queue_crypt(struct dm_crypt_io *io)
22962296
* irqs_disabled(): the kernel may run some IO completion from the idle thread, but
22972297
* it is being executed with irqs disabled.
22982298
*/
2299-
if (!(in_hardirq() || irqs_disabled())) {
2299+
if (in_hardirq() || irqs_disabled()) {
2300+
INIT_WORK(&io->work, kcryptd_crypt);
2301+
queue_work(system_bh_wq, &io->work);
2302+
return;
2303+
} else {
23002304
kcryptd_crypt(&io->work);
23012305
return;
23022306
}

drivers/md/dm-verity-target.c

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ static unsigned int dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE
4646

4747
module_param_named(prefetch_cluster, dm_verity_prefetch_cluster, uint, 0644);
4848

49-
static DEFINE_STATIC_KEY_FALSE(use_tasklet_enabled);
49+
static DEFINE_STATIC_KEY_FALSE(use_bh_wq_enabled);
5050

5151
struct dm_verity_prefetch_work {
5252
struct work_struct work;
@@ -299,7 +299,7 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
299299

300300
verity_hash_at_level(v, block, level, &hash_block, &offset);
301301

302-
if (static_branch_unlikely(&use_tasklet_enabled) && io->in_tasklet) {
302+
if (static_branch_unlikely(&use_bh_wq_enabled) && io->in_bh) {
303303
data = dm_bufio_get(v->bufio, hash_block, &buf);
304304
if (data == NULL) {
305305
/*
@@ -327,15 +327,14 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
327327

328328
r = verity_hash(v, verity_io_hash_req(v, io),
329329
data, 1 << v->hash_dev_block_bits,
330-
verity_io_real_digest(v, io), !io->in_tasklet);
330+
verity_io_real_digest(v, io), !io->in_bh);
331331
if (unlikely(r < 0))
332332
goto release_ret_r;
333333

334334
if (likely(memcmp(verity_io_real_digest(v, io), want_digest,
335335
v->digest_size) == 0))
336336
aux->hash_verified = 1;
337-
else if (static_branch_unlikely(&use_tasklet_enabled) &&
338-
io->in_tasklet) {
337+
else if (static_branch_unlikely(&use_bh_wq_enabled) && io->in_bh) {
339338
/*
340339
* Error handling code (FEC included) cannot be run in a
341340
* tasklet since it may sleep, so fallback to work-queue.
@@ -576,7 +575,7 @@ static int verity_verify_io(struct dm_verity_io *io)
576575
struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
577576
unsigned int b;
578577

579-
if (static_branch_unlikely(&use_tasklet_enabled) && io->in_tasklet) {
578+
if (static_branch_unlikely(&use_bh_wq_enabled) && io->in_bh) {
580579
/*
581580
* Copy the iterator in case we need to restart
582581
* verification in a work-queue.
@@ -616,7 +615,7 @@ static int verity_verify_io(struct dm_verity_io *io)
616615
continue;
617616
}
618617

619-
r = verity_hash_init(v, req, &wait, !io->in_tasklet);
618+
r = verity_hash_init(v, req, &wait, !io->in_bh);
620619
if (unlikely(r < 0))
621620
return r;
622621

@@ -635,8 +634,7 @@ static int verity_verify_io(struct dm_verity_io *io)
635634
if (v->validated_blocks)
636635
set_bit(cur_block, v->validated_blocks);
637636
continue;
638-
} else if (static_branch_unlikely(&use_tasklet_enabled) &&
639-
io->in_tasklet) {
637+
} else if (static_branch_unlikely(&use_bh_wq_enabled) && io->in_bh) {
640638
/*
641639
* Error handling code (FEC included) cannot be run in a
642640
* tasklet since it may sleep, so fallback to work-queue.
@@ -690,7 +688,7 @@ static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
690688
bio->bi_end_io = io->orig_bi_end_io;
691689
bio->bi_status = status;
692690

693-
if (!static_branch_unlikely(&use_tasklet_enabled) || !io->in_tasklet)
691+
if (!static_branch_unlikely(&use_bh_wq_enabled) || !io->in_bh)
694692
verity_fec_finish_io(io);
695693

696694
bio_endio(bio);
@@ -700,11 +698,28 @@ static void verity_work(struct work_struct *w)
700698
{
701699
struct dm_verity_io *io = container_of(w, struct dm_verity_io, work);
702700

703-
io->in_tasklet = false;
701+
io->in_bh = false;
704702

705703
verity_finish_io(io, errno_to_blk_status(verity_verify_io(io)));
706704
}
707705

706+
static void verity_bh_work(struct work_struct *w)
707+
{
708+
struct dm_verity_io *io = container_of(w, struct dm_verity_io, bh_work);
709+
int err;
710+
711+
io->in_bh = true;
712+
err = verity_verify_io(io);
713+
if (err == -EAGAIN || err == -ENOMEM) {
714+
/* fallback to retrying with work-queue */
715+
INIT_WORK(&io->work, verity_work);
716+
queue_work(io->v->verify_wq, &io->work);
717+
return;
718+
}
719+
720+
verity_finish_io(io, errno_to_blk_status(err));
721+
}
722+
708723
static void verity_end_io(struct bio *bio)
709724
{
710725
struct dm_verity_io *io = bio->bi_private;
@@ -717,8 +732,13 @@ static void verity_end_io(struct bio *bio)
717732
return;
718733
}
719734

720-
INIT_WORK(&io->work, verity_work);
721-
queue_work(io->v->verify_wq, &io->work);
735+
if (static_branch_unlikely(&use_bh_wq_enabled) && io->v->use_bh_wq) {
736+
INIT_WORK(&io->bh_work, verity_bh_work);
737+
queue_work(system_bh_wq, &io->bh_work);
738+
} else {
739+
INIT_WORK(&io->work, verity_work);
740+
queue_work(io->v->verify_wq, &io->work);
741+
}
722742
}
723743

724744
/*
@@ -885,7 +905,7 @@ static void verity_status(struct dm_target *ti, status_type_t type,
885905
args++;
886906
if (v->validated_blocks)
887907
args++;
888-
if (v->use_tasklet)
908+
if (v->use_bh_wq)
889909
args++;
890910
if (v->signature_key_desc)
891911
args += DM_VERITY_ROOT_HASH_VERIFICATION_OPTS;
@@ -912,7 +932,7 @@ static void verity_status(struct dm_target *ti, status_type_t type,
912932
DMEMIT(" " DM_VERITY_OPT_IGN_ZEROES);
913933
if (v->validated_blocks)
914934
DMEMIT(" " DM_VERITY_OPT_AT_MOST_ONCE);
915-
if (v->use_tasklet)
935+
if (v->use_bh_wq)
916936
DMEMIT(" " DM_VERITY_OPT_TASKLET_VERIFY);
917937
sz = verity_fec_status_table(v, sz, result, maxlen);
918938
if (v->signature_key_desc)
@@ -1031,8 +1051,8 @@ static void verity_dtr(struct dm_target *ti)
10311051

10321052
kfree(v->signature_key_desc);
10331053

1034-
if (v->use_tasklet)
1035-
static_branch_dec(&use_tasklet_enabled);
1054+
if (v->use_bh_wq)
1055+
static_branch_dec(&use_bh_wq_enabled);
10361056

10371057
kfree(v);
10381058

@@ -1166,8 +1186,8 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
11661186
continue;
11671187

11681188
} else if (!strcasecmp(arg_name, DM_VERITY_OPT_TASKLET_VERIFY)) {
1169-
v->use_tasklet = true;
1170-
static_branch_inc(&use_tasklet_enabled);
1189+
v->use_bh_wq = true;
1190+
static_branch_inc(&use_bh_wq_enabled);
11711191
continue;
11721192

11731193
} else if (verity_is_fec_opt_arg(arg_name)) {
@@ -1338,7 +1358,7 @@ static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv)
13381358
}
13391359

13401360
v->tfm = crypto_alloc_ahash(v->alg_name, 0,
1341-
v->use_tasklet ? CRYPTO_ALG_ASYNC : 0);
1361+
v->use_bh_wq ? CRYPTO_ALG_ASYNC : 0);
13421362
if (IS_ERR(v->tfm)) {
13431363
ti->error = "Cannot initialize hash function";
13441364
r = PTR_ERR(v->tfm);
@@ -1463,7 +1483,7 @@ static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv)
14631483
v->bufio = dm_bufio_client_create(v->hash_dev->bdev,
14641484
1 << v->hash_dev_block_bits, 1, sizeof(struct buffer_aux),
14651485
dm_bufio_alloc_callback, NULL,
1466-
v->use_tasklet ? DM_BUFIO_CLIENT_NO_SLEEP : 0);
1486+
v->use_bh_wq ? DM_BUFIO_CLIENT_NO_SLEEP : 0);
14671487
if (IS_ERR(v->bufio)) {
14681488
ti->error = "Cannot initialize dm-bufio";
14691489
r = PTR_ERR(v->bufio);
@@ -1482,7 +1502,7 @@ static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv)
14821502
* reducing wait times when reading from a dm-verity device.
14831503
*
14841504
* Also as required for the "try_verify_in_tasklet" feature: WQ_HIGHPRI
1485-
* allows verify_wq to preempt softirq since verification in tasklet
1505+
* allows verify_wq to preempt softirq since verification in BH workqueue
14861506
* will fall-back to using it for error handling (or if the bufio cache
14871507
* doesn't have required hashes).
14881508
*/

drivers/md/dm-verity.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ struct dm_verity {
5454
unsigned char levels; /* the number of tree levels */
5555
unsigned char version;
5656
bool hash_failed:1; /* set if hash of any block failed */
57-
bool use_tasklet:1; /* try to verify in tasklet before work-queue */
57+
bool use_bh_wq:1; /* try to verify in BH wq before normal work-queue */
5858
unsigned int digest_size; /* digest size for the current hash algorithm */
5959
unsigned int ahash_reqsize;/* the size of temporary space for crypto */
6060
enum verity_mode mode; /* mode for handling verification errors */
@@ -84,9 +84,10 @@ struct dm_verity_io {
8484

8585
sector_t block;
8686
unsigned int n_blocks;
87-
bool in_tasklet;
87+
bool in_bh;
8888

8989
struct work_struct work;
90+
struct work_struct bh_work;
9091

9192
char *recheck_buffer;
9293

0 commit comments

Comments
 (0)