3636#define DM_VERITY_OPT_LOGGING "ignore_corruption"
3737#define DM_VERITY_OPT_RESTART "restart_on_corruption"
3838#define DM_VERITY_OPT_PANIC "panic_on_corruption"
39+ #define DM_VERITY_OPT_ERROR_RESTART "restart_on_error"
40+ #define DM_VERITY_OPT_ERROR_PANIC "panic_on_error"
3941#define DM_VERITY_OPT_IGN_ZEROES "ignore_zero_blocks"
4042#define DM_VERITY_OPT_AT_MOST_ONCE "check_at_most_once"
4143#define DM_VERITY_OPT_TASKLET_VERIFY "try_verify_in_tasklet"
4244
43- #define DM_VERITY_OPTS_MAX (4 + DM_VERITY_OPTS_FEC + \
45+ #define DM_VERITY_OPTS_MAX (5 + DM_VERITY_OPTS_FEC + \
4446 DM_VERITY_ROOT_HASH_VERIFICATION_OPTS)
4547
4648static unsigned int dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE ;
@@ -583,6 +585,11 @@ static inline bool verity_is_system_shutting_down(void)
583585 || system_state == SYSTEM_RESTART ;
584586}
585587
588+ static void restart_io_error (struct work_struct * w )
589+ {
590+ kernel_restart ("dm-verity device has I/O error" );
591+ }
592+
586593/*
587594 * End one "io" structure with a given error.
588595 */
@@ -597,6 +604,23 @@ static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
597604 if (!static_branch_unlikely (& use_bh_wq_enabled ) || !io -> in_bh )
598605 verity_fec_finish_io (io );
599606
607+ if (unlikely (status != BLK_STS_OK ) &&
608+ unlikely (!(bio -> bi_opf & REQ_RAHEAD )) &&
609+ !verity_is_system_shutting_down ()) {
610+ if (v -> error_mode == DM_VERITY_MODE_PANIC ) {
611+ panic ("dm-verity device has I/O error" );
612+ }
613+ if (v -> error_mode == DM_VERITY_MODE_RESTART ) {
614+ static DECLARE_WORK (restart_work , restart_io_error ) ;
615+ queue_work (v -> verify_wq , & restart_work );
616+ /*
617+ * We deliberately don't call bio_endio here, because
618+ * the machine will be restarted anyway.
619+ */
620+ return ;
621+ }
622+ }
623+
600624 bio_endio (bio );
601625}
602626
@@ -805,6 +829,8 @@ static void verity_status(struct dm_target *ti, status_type_t type,
805829 DMEMIT ("%02x" , v -> salt [x ]);
806830 if (v -> mode != DM_VERITY_MODE_EIO )
807831 args ++ ;
832+ if (v -> error_mode != DM_VERITY_MODE_EIO )
833+ args ++ ;
808834 if (verity_fec_is_enabled (v ))
809835 args += DM_VERITY_OPTS_FEC ;
810836 if (v -> zero_digest )
@@ -834,6 +860,19 @@ static void verity_status(struct dm_target *ti, status_type_t type,
834860 BUG ();
835861 }
836862 }
863+ if (v -> error_mode != DM_VERITY_MODE_EIO ) {
864+ DMEMIT (" " );
865+ switch (v -> error_mode ) {
866+ case DM_VERITY_MODE_RESTART :
867+ DMEMIT (DM_VERITY_OPT_ERROR_RESTART );
868+ break ;
869+ case DM_VERITY_MODE_PANIC :
870+ DMEMIT (DM_VERITY_OPT_ERROR_PANIC );
871+ break ;
872+ default :
873+ BUG ();
874+ }
875+ }
837876 if (v -> zero_digest )
838877 DMEMIT (" " DM_VERITY_OPT_IGN_ZEROES );
839878 if (v -> validated_blocks )
@@ -886,6 +925,19 @@ static void verity_status(struct dm_target *ti, status_type_t type,
886925 DMEMIT ("invalid" );
887926 }
888927 }
928+ if (v -> error_mode != DM_VERITY_MODE_EIO ) {
929+ DMEMIT (",verity_error_mode=" );
930+ switch (v -> error_mode ) {
931+ case DM_VERITY_MODE_RESTART :
932+ DMEMIT (DM_VERITY_OPT_ERROR_RESTART );
933+ break ;
934+ case DM_VERITY_MODE_PANIC :
935+ DMEMIT (DM_VERITY_OPT_ERROR_PANIC );
936+ break ;
937+ default :
938+ DMEMIT ("invalid" );
939+ }
940+ }
889941 DMEMIT (";" );
890942 break ;
891943 }
@@ -1088,6 +1140,25 @@ static int verity_parse_verity_mode(struct dm_verity *v, const char *arg_name)
10881140 return 0 ;
10891141}
10901142
1143+ static inline bool verity_is_verity_error_mode (const char * arg_name )
1144+ {
1145+ return (!strcasecmp (arg_name , DM_VERITY_OPT_ERROR_RESTART ) ||
1146+ !strcasecmp (arg_name , DM_VERITY_OPT_ERROR_PANIC ));
1147+ }
1148+
1149+ static int verity_parse_verity_error_mode (struct dm_verity * v , const char * arg_name )
1150+ {
1151+ if (v -> error_mode )
1152+ return - EINVAL ;
1153+
1154+ if (!strcasecmp (arg_name , DM_VERITY_OPT_ERROR_RESTART ))
1155+ v -> error_mode = DM_VERITY_MODE_RESTART ;
1156+ else if (!strcasecmp (arg_name , DM_VERITY_OPT_ERROR_PANIC ))
1157+ v -> error_mode = DM_VERITY_MODE_PANIC ;
1158+
1159+ return 0 ;
1160+ }
1161+
10911162static int verity_parse_opt_args (struct dm_arg_set * as , struct dm_verity * v ,
10921163 struct dm_verity_sig_opts * verify_args ,
10931164 bool only_modifier_opts )
@@ -1122,6 +1193,16 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
11221193 }
11231194 continue ;
11241195
1196+ } else if (verity_is_verity_error_mode (arg_name )) {
1197+ if (only_modifier_opts )
1198+ continue ;
1199+ r = verity_parse_verity_error_mode (v , arg_name );
1200+ if (r ) {
1201+ ti -> error = "Conflicting error handling parameters" ;
1202+ return r ;
1203+ }
1204+ continue ;
1205+
11251206 } else if (!strcasecmp (arg_name , DM_VERITY_OPT_IGN_ZEROES )) {
11261207 if (only_modifier_opts )
11271208 continue ;
0 commit comments