Skip to content

Commit 359cdf5

Browse files
committed
Merge tag 'for-6.12/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm
Pull device mapper fixes from Mikulas Patocka: "Revert the patch that made dm-verity restart or panic on I/O errors, and instead add new explicit options for people who want that behavior" * tag 'for-6.12/dm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm: dm-verity: introduce the options restart_on_error and panic_on_error Revert: "dm-verity: restart or panic on an I/O error"
2 parents 27af290 + f811b83 commit 359cdf5

File tree

2 files changed

+79
-16
lines changed

2 files changed

+79
-16
lines changed

drivers/md/dm-verity-target.c

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@
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

4648
static unsigned int dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE;
@@ -273,10 +275,8 @@ static int verity_handle_err(struct dm_verity *v, enum verity_block_type type,
273275
if (v->mode == DM_VERITY_MODE_LOGGING)
274276
return 0;
275277

276-
if (v->mode == DM_VERITY_MODE_RESTART) {
277-
pr_emerg("dm-verity device corrupted\n");
278-
emergency_restart();
279-
}
278+
if (v->mode == DM_VERITY_MODE_RESTART)
279+
kernel_restart("dm-verity device corrupted");
280280

281281
if (v->mode == DM_VERITY_MODE_PANIC)
282282
panic("dm-verity device corrupted");
@@ -585,6 +585,11 @@ static inline bool verity_is_system_shutting_down(void)
585585
|| system_state == SYSTEM_RESTART;
586586
}
587587

588+
static void restart_io_error(struct work_struct *w)
589+
{
590+
kernel_restart("dm-verity device has I/O error");
591+
}
592+
588593
/*
589594
* End one "io" structure with a given error.
590595
*/
@@ -602,18 +607,18 @@ static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
602607
if (unlikely(status != BLK_STS_OK) &&
603608
unlikely(!(bio->bi_opf & REQ_RAHEAD)) &&
604609
!verity_is_system_shutting_down()) {
605-
if (v->mode == DM_VERITY_MODE_RESTART ||
606-
v->mode == DM_VERITY_MODE_PANIC)
607-
DMERR_LIMIT("%s has error: %s", v->data_dev->name,
608-
blk_status_to_str(status));
609-
610-
if (v->mode == DM_VERITY_MODE_RESTART) {
611-
pr_emerg("dm-verity device corrupted\n");
612-
emergency_restart();
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;
613621
}
614-
615-
if (v->mode == DM_VERITY_MODE_PANIC)
616-
panic("dm-verity device corrupted");
617622
}
618623

619624
bio_endio(bio);
@@ -824,6 +829,8 @@ static void verity_status(struct dm_target *ti, status_type_t type,
824829
DMEMIT("%02x", v->salt[x]);
825830
if (v->mode != DM_VERITY_MODE_EIO)
826831
args++;
832+
if (v->error_mode != DM_VERITY_MODE_EIO)
833+
args++;
827834
if (verity_fec_is_enabled(v))
828835
args += DM_VERITY_OPTS_FEC;
829836
if (v->zero_digest)
@@ -853,6 +860,19 @@ static void verity_status(struct dm_target *ti, status_type_t type,
853860
BUG();
854861
}
855862
}
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+
}
856876
if (v->zero_digest)
857877
DMEMIT(" " DM_VERITY_OPT_IGN_ZEROES);
858878
if (v->validated_blocks)
@@ -905,6 +925,19 @@ static void verity_status(struct dm_target *ti, status_type_t type,
905925
DMEMIT("invalid");
906926
}
907927
}
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+
}
908941
DMEMIT(";");
909942
break;
910943
}
@@ -1107,6 +1140,25 @@ static int verity_parse_verity_mode(struct dm_verity *v, const char *arg_name)
11071140
return 0;
11081141
}
11091142

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+
11101162
static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
11111163
struct dm_verity_sig_opts *verify_args,
11121164
bool only_modifier_opts)
@@ -1141,6 +1193,16 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
11411193
}
11421194
continue;
11431195

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+
11441206
} else if (!strcasecmp(arg_name, DM_VERITY_OPT_IGN_ZEROES)) {
11451207
if (only_modifier_opts)
11461208
continue;

drivers/md/dm-verity.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ struct dm_verity {
6464
unsigned int digest_size; /* digest size for the current hash algorithm */
6565
unsigned int hash_reqsize; /* the size of temporary space for crypto */
6666
enum verity_mode mode; /* mode for handling verification errors */
67+
enum verity_mode error_mode;/* mode for handling I/O errors */
6768
unsigned int corrupted_errs;/* Number of errors for corrupted blocks */
6869

6970
struct workqueue_struct *verify_wq;

0 commit comments

Comments
 (0)