3434#define DM_VERITY_OPT_PANIC "panic_on_corruption"
3535#define DM_VERITY_OPT_IGN_ZEROES "ignore_zero_blocks"
3636#define DM_VERITY_OPT_AT_MOST_ONCE "check_at_most_once"
37+ #define DM_VERITY_OPT_TASKLET_VERIFY "try_verify_in_tasklet"
3738
3839#define DM_VERITY_OPTS_MAX (3 + DM_VERITY_OPTS_FEC + \
3940 DM_VERITY_ROOT_HASH_VERIFICATION_OPTS)
@@ -220,7 +221,7 @@ static int verity_handle_err(struct dm_verity *v, enum verity_block_type type,
220221 struct mapped_device * md = dm_table_get_md (v -> ti -> table );
221222
222223 /* Corruption should be visible in device status in all modes */
223- v -> hash_failed = 1 ;
224+ v -> hash_failed = true ;
224225
225226 if (v -> corrupted_errs >= DM_VERITY_MAX_CORRUPTED_ERRS )
226227 goto out ;
@@ -286,7 +287,19 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
286287
287288 verity_hash_at_level (v , block , level , & hash_block , & offset );
288289
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+
290303 if (IS_ERR (data ))
291304 return PTR_ERR (data );
292305
@@ -307,6 +320,14 @@ static int verity_verify_level(struct dm_verity *v, struct dm_verity_io *io,
307320 if (likely (memcmp (verity_io_real_digest (v , io ), want_digest ,
308321 v -> digest_size ) == 0 ))
309322 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+ }
310331 else if (verity_fec_decode (v , io ,
311332 DM_VERITY_BLOCK_TYPE_METADATA ,
312333 hash_block , data , NULL ) == 0 )
@@ -474,9 +495,14 @@ static int verity_verify_io(struct dm_verity_io *io)
474495 bool is_zero ;
475496 struct dm_verity * v = io -> v ;
476497 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 ;
478503 struct crypto_wait wait ;
479504 struct bio * bio = dm_bio_from_per_bio_data (io , v -> ti -> per_io_data_size );
505+ unsigned int b ;
480506
481507 for (b = 0 ; b < io -> n_blocks ; b ++ ) {
482508 int r ;
@@ -485,7 +511,7 @@ static int verity_verify_io(struct dm_verity_io *io)
485511
486512 if (v -> validated_blocks &&
487513 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 );
489515 continue ;
490516 }
491517
@@ -500,7 +526,7 @@ static int verity_verify_io(struct dm_verity_io *io)
500526 * If we expect a zero block, don't validate, just
501527 * return zeros.
502528 */
503- r = verity_for_bv_block (v , io , & io -> iter ,
529+ r = verity_for_bv_block (v , io , & iter_copy ,
504530 verity_bv_zero );
505531 if (unlikely (r < 0 ))
506532 return r ;
@@ -512,8 +538,8 @@ static int verity_verify_io(struct dm_verity_io *io)
512538 if (unlikely (r < 0 ))
513539 return r ;
514540
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 );
517543 if (unlikely (r < 0 ))
518544 return r ;
519545
@@ -527,8 +553,14 @@ static int verity_verify_io(struct dm_verity_io *io)
527553 if (v -> validated_blocks )
528554 set_bit (cur_block , v -> validated_blocks );
529555 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 ;
530562 } else if (verity_fec_decode (v , io , DM_VERITY_BLOCK_TYPE_DATA ,
531- cur_block , NULL , & start ) == 0 ) {
563+ cur_block , NULL , & start ) == 0 ) {
532564 continue ;
533565 } else {
534566 if (bio -> bi_status ) {
@@ -566,7 +598,8 @@ static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
566598 bio -> bi_end_io = io -> orig_bi_end_io ;
567599 bio -> bi_status = status ;
568600
569- verity_fec_finish_io (io );
601+ if (!io -> in_tasklet )
602+ verity_fec_finish_io (io );
570603
571604 bio_endio (bio );
572605}
@@ -575,9 +608,29 @@ static void verity_work(struct work_struct *w)
575608{
576609 struct dm_verity_io * io = container_of (w , struct dm_verity_io , work );
577610
611+ io -> in_tasklet = false;
612+
613+ verity_fec_init_io (io );
578614 verity_finish_io (io , errno_to_blk_status (verity_verify_io (io )));
579615}
580616
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+
581634static void verity_end_io (struct bio * bio )
582635{
583636 struct dm_verity_io * io = bio -> bi_private ;
@@ -588,8 +641,13 @@ static void verity_end_io(struct bio *bio)
588641 return ;
589642 }
590643
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+ }
593651}
594652
595653/*
@@ -700,8 +758,6 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
700758 bio -> bi_private = io ;
701759 io -> iter = bio -> bi_iter ;
702760
703- verity_fec_init_io (io );
704-
705761 verity_submit_prefetch (v , io );
706762
707763 submit_bio_noacct (bio );
@@ -751,6 +807,8 @@ static void verity_status(struct dm_target *ti, status_type_t type,
751807 args ++ ;
752808 if (v -> validated_blocks )
753809 args ++ ;
810+ if (v -> use_tasklet )
811+ args ++ ;
754812 if (v -> signature_key_desc )
755813 args += DM_VERITY_ROOT_HASH_VERIFICATION_OPTS ;
756814 if (!args )
@@ -776,6 +834,8 @@ static void verity_status(struct dm_target *ti, status_type_t type,
776834 DMEMIT (" " DM_VERITY_OPT_IGN_ZEROES );
777835 if (v -> validated_blocks )
778836 DMEMIT (" " DM_VERITY_OPT_AT_MOST_ONCE );
837+ if (v -> use_tasklet )
838+ DMEMIT (" " DM_VERITY_OPT_TASKLET_VERIFY );
779839 sz = verity_fec_status_table (v , sz , result , maxlen );
780840 if (v -> signature_key_desc )
781841 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,
10111071 return r ;
10121072 continue ;
10131073
1074+ } else if (!strcasecmp (arg_name , DM_VERITY_OPT_TASKLET_VERIFY )) {
1075+ v -> use_tasklet = true;
1076+ continue ;
1077+
10141078 } else if (verity_is_fec_opt_arg (arg_name )) {
10151079 r = verity_fec_parse_opt_args (as , v , & argc , arg_name );
10161080 if (r )
10171081 return r ;
10181082 continue ;
1083+
10191084 } else if (verity_verify_is_sig_opt_arg (arg_name )) {
10201085 r = verity_verify_sig_parse_opt_args (as , v ,
10211086 verify_args ,
10221087 & argc , arg_name );
10231088 if (r )
10241089 return r ;
10251090 continue ;
1026-
10271091 }
10281092
10291093 ti -> error = "Unrecognized verity feature request" ;
@@ -1155,7 +1219,11 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
11551219 goto bad ;
11561220 }
11571221
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 );
11591227 if (IS_ERR (v -> tfm )) {
11601228 ti -> error = "Cannot initialize hash function" ;
11611229 r = PTR_ERR (v -> tfm );
@@ -1265,7 +1333,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
12651333
12661334 v -> bufio = dm_bufio_client_create (v -> hash_dev -> bdev ,
12671335 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 );
12691338 if (IS_ERR (v -> bufio )) {
12701339 ti -> error = "Cannot initialize dm-bufio" ;
12711340 r = PTR_ERR (v -> bufio );
@@ -1312,7 +1381,7 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
13121381static struct target_type verity_target = {
13131382 .name = "verity" ,
13141383 .features = DM_TARGET_IMMUTABLE ,
1315- .version = {1 , 8 , 0 },
1384+ .version = {1 , 9 , 0 },
13161385 .module = THIS_MODULE ,
13171386 .ctr = verity_ctr ,
13181387 .dtr = verity_dtr ,
0 commit comments