3535#define DM_VERITY_OPT_LOGGING "ignore_corruption"
3636#define DM_VERITY_OPT_RESTART "restart_on_corruption"
3737#define DM_VERITY_OPT_PANIC "panic_on_corruption"
38+ #define DM_VERITY_OPT_ERROR_RESTART "restart_on_error"
39+ #define DM_VERITY_OPT_ERROR_PANIC "panic_on_error"
3840#define DM_VERITY_OPT_IGN_ZEROES "ignore_zero_blocks"
3941#define DM_VERITY_OPT_AT_MOST_ONCE "check_at_most_once"
4042#define DM_VERITY_OPT_TASKLET_VERIFY "try_verify_in_tasklet"
4143
42- #define DM_VERITY_OPTS_MAX (4 + DM_VERITY_OPTS_FEC + \
44+ #define DM_VERITY_OPTS_MAX (5 + DM_VERITY_OPTS_FEC + \
4345 DM_VERITY_ROOT_HASH_VERIFICATION_OPTS)
4446
4547static unsigned int dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE ;
@@ -582,6 +584,11 @@ static inline bool verity_is_system_shutting_down(void)
582584 || system_state == SYSTEM_RESTART ;
583585}
584586
587+ static void restart_io_error (struct work_struct * w )
588+ {
589+ kernel_restart ("dm-verity device has I/O error" );
590+ }
591+
585592/*
586593 * End one "io" structure with a given error.
587594 */
@@ -596,6 +603,23 @@ static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
596603 if (!static_branch_unlikely (& use_bh_wq_enabled ) || !io -> in_bh )
597604 verity_fec_finish_io (io );
598605
606+ if (unlikely (status != BLK_STS_OK ) &&
607+ unlikely (!(bio -> bi_opf & REQ_RAHEAD )) &&
608+ !verity_is_system_shutting_down ()) {
609+ if (v -> error_mode == DM_VERITY_MODE_PANIC ) {
610+ panic ("dm-verity device has I/O error" );
611+ }
612+ if (v -> error_mode == DM_VERITY_MODE_RESTART ) {
613+ static DECLARE_WORK (restart_work , restart_io_error ) ;
614+ queue_work (v -> verify_wq , & restart_work );
615+ /*
616+ * We deliberately don't call bio_endio here, because
617+ * the machine will be restarted anyway.
618+ */
619+ return ;
620+ }
621+ }
622+
599623 bio_endio (bio );
600624}
601625
@@ -804,6 +828,8 @@ static void verity_status(struct dm_target *ti, status_type_t type,
804828 DMEMIT ("%02x" , v -> salt [x ]);
805829 if (v -> mode != DM_VERITY_MODE_EIO )
806830 args ++ ;
831+ if (v -> error_mode != DM_VERITY_MODE_EIO )
832+ args ++ ;
807833 if (verity_fec_is_enabled (v ))
808834 args += DM_VERITY_OPTS_FEC ;
809835 if (v -> zero_digest )
@@ -833,6 +859,19 @@ static void verity_status(struct dm_target *ti, status_type_t type,
833859 BUG ();
834860 }
835861 }
862+ if (v -> error_mode != DM_VERITY_MODE_EIO ) {
863+ DMEMIT (" " );
864+ switch (v -> error_mode ) {
865+ case DM_VERITY_MODE_RESTART :
866+ DMEMIT (DM_VERITY_OPT_ERROR_RESTART );
867+ break ;
868+ case DM_VERITY_MODE_PANIC :
869+ DMEMIT (DM_VERITY_OPT_ERROR_PANIC );
870+ break ;
871+ default :
872+ BUG ();
873+ }
874+ }
836875 if (v -> zero_digest )
837876 DMEMIT (" " DM_VERITY_OPT_IGN_ZEROES );
838877 if (v -> validated_blocks )
@@ -885,6 +924,19 @@ static void verity_status(struct dm_target *ti, status_type_t type,
885924 DMEMIT ("invalid" );
886925 }
887926 }
927+ if (v -> error_mode != DM_VERITY_MODE_EIO ) {
928+ DMEMIT (",verity_error_mode=" );
929+ switch (v -> error_mode ) {
930+ case DM_VERITY_MODE_RESTART :
931+ DMEMIT (DM_VERITY_OPT_ERROR_RESTART );
932+ break ;
933+ case DM_VERITY_MODE_PANIC :
934+ DMEMIT (DM_VERITY_OPT_ERROR_PANIC );
935+ break ;
936+ default :
937+ DMEMIT ("invalid" );
938+ }
939+ }
888940 DMEMIT (";" );
889941 break ;
890942 }
@@ -1051,6 +1103,25 @@ static int verity_parse_verity_mode(struct dm_verity *v, const char *arg_name)
10511103 return 0 ;
10521104}
10531105
1106+ static inline bool verity_is_verity_error_mode (const char * arg_name )
1107+ {
1108+ return (!strcasecmp (arg_name , DM_VERITY_OPT_ERROR_RESTART ) ||
1109+ !strcasecmp (arg_name , DM_VERITY_OPT_ERROR_PANIC ));
1110+ }
1111+
1112+ static int verity_parse_verity_error_mode (struct dm_verity * v , const char * arg_name )
1113+ {
1114+ if (v -> error_mode )
1115+ return - EINVAL ;
1116+
1117+ if (!strcasecmp (arg_name , DM_VERITY_OPT_ERROR_RESTART ))
1118+ v -> error_mode = DM_VERITY_MODE_RESTART ;
1119+ else if (!strcasecmp (arg_name , DM_VERITY_OPT_ERROR_PANIC ))
1120+ v -> error_mode = DM_VERITY_MODE_PANIC ;
1121+
1122+ return 0 ;
1123+ }
1124+
10541125static int verity_parse_opt_args (struct dm_arg_set * as , struct dm_verity * v ,
10551126 struct dm_verity_sig_opts * verify_args ,
10561127 bool only_modifier_opts )
@@ -1085,6 +1156,16 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
10851156 }
10861157 continue ;
10871158
1159+ } else if (verity_is_verity_error_mode (arg_name )) {
1160+ if (only_modifier_opts )
1161+ continue ;
1162+ r = verity_parse_verity_error_mode (v , arg_name );
1163+ if (r ) {
1164+ ti -> error = "Conflicting error handling parameters" ;
1165+ return r ;
1166+ }
1167+ continue ;
1168+
10881169 } else if (!strcasecmp (arg_name , DM_VERITY_OPT_IGN_ZEROES )) {
10891170 if (only_modifier_opts )
10901171 continue ;
0 commit comments