36
36
#define DM_VERITY_OPT_LOGGING "ignore_corruption"
37
37
#define DM_VERITY_OPT_RESTART "restart_on_corruption"
38
38
#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"
39
41
#define DM_VERITY_OPT_IGN_ZEROES "ignore_zero_blocks"
40
42
#define DM_VERITY_OPT_AT_MOST_ONCE "check_at_most_once"
41
43
#define DM_VERITY_OPT_TASKLET_VERIFY "try_verify_in_tasklet"
42
44
43
- #define DM_VERITY_OPTS_MAX (4 + DM_VERITY_OPTS_FEC + \
45
+ #define DM_VERITY_OPTS_MAX (5 + DM_VERITY_OPTS_FEC + \
44
46
DM_VERITY_ROOT_HASH_VERIFICATION_OPTS)
45
47
46
48
static unsigned int dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE ;
@@ -583,6 +585,11 @@ static inline bool verity_is_system_shutting_down(void)
583
585
|| system_state == SYSTEM_RESTART ;
584
586
}
585
587
588
+ static void restart_io_error (struct work_struct * w )
589
+ {
590
+ kernel_restart ("dm-verity device has I/O error" );
591
+ }
592
+
586
593
/*
587
594
* End one "io" structure with a given error.
588
595
*/
@@ -597,6 +604,23 @@ static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
597
604
if (!static_branch_unlikely (& use_bh_wq_enabled ) || !io -> in_bh )
598
605
verity_fec_finish_io (io );
599
606
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
+
600
624
bio_endio (bio );
601
625
}
602
626
@@ -805,6 +829,8 @@ static void verity_status(struct dm_target *ti, status_type_t type,
805
829
DMEMIT ("%02x" , v -> salt [x ]);
806
830
if (v -> mode != DM_VERITY_MODE_EIO )
807
831
args ++ ;
832
+ if (v -> error_mode != DM_VERITY_MODE_EIO )
833
+ args ++ ;
808
834
if (verity_fec_is_enabled (v ))
809
835
args += DM_VERITY_OPTS_FEC ;
810
836
if (v -> zero_digest )
@@ -834,6 +860,19 @@ static void verity_status(struct dm_target *ti, status_type_t type,
834
860
BUG ();
835
861
}
836
862
}
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
+ }
837
876
if (v -> zero_digest )
838
877
DMEMIT (" " DM_VERITY_OPT_IGN_ZEROES );
839
878
if (v -> validated_blocks )
@@ -886,6 +925,19 @@ static void verity_status(struct dm_target *ti, status_type_t type,
886
925
DMEMIT ("invalid" );
887
926
}
888
927
}
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
+ }
889
941
DMEMIT (";" );
890
942
break ;
891
943
}
@@ -1088,6 +1140,25 @@ static int verity_parse_verity_mode(struct dm_verity *v, const char *arg_name)
1088
1140
return 0 ;
1089
1141
}
1090
1142
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
+
1091
1162
static int verity_parse_opt_args (struct dm_arg_set * as , struct dm_verity * v ,
1092
1163
struct dm_verity_sig_opts * verify_args ,
1093
1164
bool only_modifier_opts )
@@ -1122,6 +1193,16 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
1122
1193
}
1123
1194
continue ;
1124
1195
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
+
1125
1206
} else if (!strcasecmp (arg_name , DM_VERITY_OPT_IGN_ZEROES )) {
1126
1207
if (only_modifier_opts )
1127
1208
continue ;
0 commit comments