34
34
#define DM_VERITY_OPT_PANIC "panic_on_corruption"
35
35
#define DM_VERITY_OPT_IGN_ZEROES "ignore_zero_blocks"
36
36
#define DM_VERITY_OPT_AT_MOST_ONCE "check_at_most_once"
37
+ #define DM_VERITY_OPT_TASKLET_VERIFY "try_verify_in_tasklet"
37
38
38
39
#define DM_VERITY_OPTS_MAX (3 + DM_VERITY_OPTS_FEC + \
39
40
DM_VERITY_ROOT_HASH_VERIFICATION_OPTS)
@@ -220,7 +221,7 @@ static int verity_handle_err(struct dm_verity *v, enum verity_block_type type,
220
221
struct mapped_device * md = dm_table_get_md (v -> ti -> table );
221
222
222
223
/* Corruption should be visible in device status in all modes */
223
- v -> hash_failed = 1 ;
224
+ v -> hash_failed = true ;
224
225
225
226
if (v -> corrupted_errs >= DM_VERITY_MAX_CORRUPTED_ERRS )
226
227
goto out ;
@@ -286,7 +287,19 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
286
287
287
288
verity_hash_at_level (v , block , level , & hash_block , & offset );
288
289
289
- data = dm_bufio_read (v -> bufio , hash_block , & buf );
290
+ if (io -> in_tasklet ) {
291
+ data = dm_bufio_get (v -> bufio , hash_block , & buf );
292
+ if (data == NULL ) {
293
+ /*
294
+ * In tasklet and the hash was not in the bufio cache.
295
+ * Return early and resume execution from a work-queue
296
+ * to read the hash from disk.
297
+ */
298
+ return - EAGAIN ;
299
+ }
300
+ } else
301
+ data = dm_bufio_read (v -> bufio , hash_block , & buf );
302
+
290
303
if (IS_ERR (data ))
291
304
return PTR_ERR (data );
292
305
@@ -307,6 +320,14 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
307
320
if (likely (memcmp (verity_io_real_digest (v , io ), want_digest ,
308
321
v -> digest_size ) == 0 ))
309
322
aux -> hash_verified = 1 ;
323
+ else if (io -> in_tasklet ) {
324
+ /*
325
+ * Error handling code (FEC included) cannot be run in a
326
+ * tasklet since it may sleep, so fallback to work-queue.
327
+ */
328
+ r = - EAGAIN ;
329
+ goto release_ret_r ;
330
+ }
310
331
else if (verity_fec_decode (v , io ,
311
332
DM_VERITY_BLOCK_TYPE_METADATA ,
312
333
hash_block , data , NULL ) == 0 )
@@ -474,9 +495,14 @@ static int verity_verify_io(struct dm_verity_io *io)
474
495
bool is_zero ;
475
496
struct dm_verity * v = io -> v ;
476
497
struct bvec_iter start ;
477
- unsigned b ;
498
+ /*
499
+ * Copy the iterator in case we need to restart verification in a
500
+ * work-queue.
501
+ */
502
+ struct bvec_iter iter_copy = io -> iter ;
478
503
struct crypto_wait wait ;
479
504
struct bio * bio = dm_bio_from_per_bio_data (io , v -> ti -> per_io_data_size );
505
+ unsigned int b ;
480
506
481
507
for (b = 0 ; b < io -> n_blocks ; b ++ ) {
482
508
int r ;
@@ -485,7 +511,7 @@ static int verity_verify_io(struct dm_verity_io *io)
485
511
486
512
if (v -> validated_blocks &&
487
513
likely (test_bit (cur_block , v -> validated_blocks ))) {
488
- verity_bv_skip_block (v , io , & io -> iter );
514
+ verity_bv_skip_block (v , io , & iter_copy );
489
515
continue ;
490
516
}
491
517
@@ -500,7 +526,7 @@ static int verity_verify_io(struct dm_verity_io *io)
500
526
* If we expect a zero block, don't validate, just
501
527
* return zeros.
502
528
*/
503
- r = verity_for_bv_block (v , io , & io -> iter ,
529
+ r = verity_for_bv_block (v , io , & iter_copy ,
504
530
verity_bv_zero );
505
531
if (unlikely (r < 0 ))
506
532
return r ;
@@ -512,8 +538,8 @@ static int verity_verify_io(struct dm_verity_io *io)
512
538
if (unlikely (r < 0 ))
513
539
return r ;
514
540
515
- start = io -> iter ;
516
- r = verity_for_io_block (v , io , & io -> iter , & wait );
541
+ start = iter_copy ;
542
+ r = verity_for_io_block (v , io , & iter_copy , & wait );
517
543
if (unlikely (r < 0 ))
518
544
return r ;
519
545
@@ -527,8 +553,14 @@ static int verity_verify_io(struct dm_verity_io *io)
527
553
if (v -> validated_blocks )
528
554
set_bit (cur_block , v -> validated_blocks );
529
555
continue ;
556
+ } else if (io -> in_tasklet ) {
557
+ /*
558
+ * Error handling code (FEC included) cannot be run in a
559
+ * tasklet since it may sleep, so fallback to work-queue.
560
+ */
561
+ return - EAGAIN ;
530
562
} else if (verity_fec_decode (v , io , DM_VERITY_BLOCK_TYPE_DATA ,
531
- cur_block , NULL , & start ) == 0 ) {
563
+ cur_block , NULL , & start ) == 0 ) {
532
564
continue ;
533
565
} else {
534
566
if (bio -> bi_status ) {
@@ -566,7 +598,8 @@ static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
566
598
bio -> bi_end_io = io -> orig_bi_end_io ;
567
599
bio -> bi_status = status ;
568
600
569
- verity_fec_finish_io (io );
601
+ if (!io -> in_tasklet )
602
+ verity_fec_finish_io (io );
570
603
571
604
bio_endio (bio );
572
605
}
@@ -575,9 +608,29 @@ static void verity_work(struct work_struct *w)
575
608
{
576
609
struct dm_verity_io * io = container_of (w , struct dm_verity_io , work );
577
610
611
+ io -> in_tasklet = false;
612
+
613
+ verity_fec_init_io (io );
578
614
verity_finish_io (io , errno_to_blk_status (verity_verify_io (io )));
579
615
}
580
616
617
+ static void verity_tasklet (unsigned long data )
618
+ {
619
+ struct dm_verity_io * io = (struct dm_verity_io * )data ;
620
+ int err ;
621
+
622
+ io -> in_tasklet = true;
623
+ err = verity_verify_io (io );
624
+ if (err == - EAGAIN ) {
625
+ /* fallback to retrying with work-queue */
626
+ INIT_WORK (& io -> work , verity_work );
627
+ queue_work (io -> v -> verify_wq , & io -> work );
628
+ return ;
629
+ }
630
+
631
+ verity_finish_io (io , errno_to_blk_status (err ));
632
+ }
633
+
581
634
static void verity_end_io (struct bio * bio )
582
635
{
583
636
struct dm_verity_io * io = bio -> bi_private ;
@@ -588,8 +641,13 @@ static void verity_end_io(struct bio *bio)
588
641
return ;
589
642
}
590
643
591
- INIT_WORK (& io -> work , verity_work );
592
- queue_work (io -> v -> verify_wq , & io -> work );
644
+ if (io -> v -> use_tasklet ) {
645
+ tasklet_init (& io -> tasklet , verity_tasklet , (unsigned long )io );
646
+ tasklet_schedule (& io -> tasklet );
647
+ } else {
648
+ INIT_WORK (& io -> work , verity_work );
649
+ queue_work (io -> v -> verify_wq , & io -> work );
650
+ }
593
651
}
594
652
595
653
/*
@@ -700,8 +758,6 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
700
758
bio -> bi_private = io ;
701
759
io -> iter = bio -> bi_iter ;
702
760
703
- verity_fec_init_io (io );
704
-
705
761
verity_submit_prefetch (v , io );
706
762
707
763
submit_bio_noacct (bio );
@@ -751,6 +807,8 @@ static void verity_status(struct dm_target *ti, status_type_t type,
751
807
args ++ ;
752
808
if (v -> validated_blocks )
753
809
args ++ ;
810
+ if (v -> use_tasklet )
811
+ args ++ ;
754
812
if (v -> signature_key_desc )
755
813
args += DM_VERITY_ROOT_HASH_VERIFICATION_OPTS ;
756
814
if (!args )
@@ -776,6 +834,8 @@ static void verity_status(struct dm_target *ti, status_type_t type,
776
834
DMEMIT (" " DM_VERITY_OPT_IGN_ZEROES );
777
835
if (v -> validated_blocks )
778
836
DMEMIT (" " DM_VERITY_OPT_AT_MOST_ONCE );
837
+ if (v -> use_tasklet )
838
+ DMEMIT (" " DM_VERITY_OPT_TASKLET_VERIFY );
779
839
sz = verity_fec_status_table (v , sz , result , maxlen );
780
840
if (v -> signature_key_desc )
781
841
DMEMIT (" " DM_VERITY_ROOT_HASH_VERIFICATION_OPT_SIG_KEY
@@ -1011,19 +1071,23 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
1011
1071
return r ;
1012
1072
continue ;
1013
1073
1074
+ } else if (!strcasecmp (arg_name , DM_VERITY_OPT_TASKLET_VERIFY )) {
1075
+ v -> use_tasklet = true;
1076
+ continue ;
1077
+
1014
1078
} else if (verity_is_fec_opt_arg (arg_name )) {
1015
1079
r = verity_fec_parse_opt_args (as , v , & argc , arg_name );
1016
1080
if (r )
1017
1081
return r ;
1018
1082
continue ;
1083
+
1019
1084
} else if (verity_verify_is_sig_opt_arg (arg_name )) {
1020
1085
r = verity_verify_sig_parse_opt_args (as , v ,
1021
1086
verify_args ,
1022
1087
& argc , arg_name );
1023
1088
if (r )
1024
1089
return r ;
1025
1090
continue ;
1026
-
1027
1091
}
1028
1092
1029
1093
ti -> error = "Unrecognized verity feature request" ;
@@ -1155,7 +1219,11 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
1155
1219
goto bad ;
1156
1220
}
1157
1221
1158
- v -> tfm = crypto_alloc_ahash (v -> alg_name , 0 , 0 );
1222
+ /*
1223
+ * FIXME: CRYPTO_ALG_ASYNC should be conditional on v->use_tasklet
1224
+ * but verity_parse_opt_args() happens below and has data dep on tfm.
1225
+ */
1226
+ v -> tfm = crypto_alloc_ahash (v -> alg_name , 0 , CRYPTO_ALG_ASYNC );
1159
1227
if (IS_ERR (v -> tfm )) {
1160
1228
ti -> error = "Cannot initialize hash function" ;
1161
1229
r = PTR_ERR (v -> tfm );
@@ -1265,7 +1333,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
1265
1333
1266
1334
v -> bufio = dm_bufio_client_create (v -> hash_dev -> bdev ,
1267
1335
1 << v -> hash_dev_block_bits , 1 , sizeof (struct buffer_aux ),
1268
- dm_bufio_alloc_callback , NULL , 0 );
1336
+ dm_bufio_alloc_callback , NULL ,
1337
+ v -> use_tasklet ? DM_BUFIO_CLIENT_NO_SLEEP : 0 );
1269
1338
if (IS_ERR (v -> bufio )) {
1270
1339
ti -> error = "Cannot initialize dm-bufio" ;
1271
1340
r = PTR_ERR (v -> bufio );
@@ -1312,7 +1381,7 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
1312
1381
static struct target_type verity_target = {
1313
1382
.name = "verity" ,
1314
1383
.features = DM_TARGET_IMMUTABLE ,
1315
- .version = {1 , 8 , 0 },
1384
+ .version = {1 , 9 , 0 },
1316
1385
.module = THIS_MODULE ,
1317
1386
.ctr = verity_ctr ,
1318
1387
.dtr = verity_dtr ,
0 commit comments