Commit 359cdf5a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-6.12/dm-fixes' of...

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"
parents 27af290f f811b838
......@@ -36,11 +36,13 @@
#define DM_VERITY_OPT_LOGGING "ignore_corruption"
#define DM_VERITY_OPT_RESTART "restart_on_corruption"
#define DM_VERITY_OPT_PANIC "panic_on_corruption"
#define DM_VERITY_OPT_ERROR_RESTART "restart_on_error"
#define DM_VERITY_OPT_ERROR_PANIC "panic_on_error"
#define DM_VERITY_OPT_IGN_ZEROES "ignore_zero_blocks"
#define DM_VERITY_OPT_AT_MOST_ONCE "check_at_most_once"
#define DM_VERITY_OPT_TASKLET_VERIFY "try_verify_in_tasklet"
#define DM_VERITY_OPTS_MAX (4 + DM_VERITY_OPTS_FEC + \
#define DM_VERITY_OPTS_MAX (5 + DM_VERITY_OPTS_FEC + \
DM_VERITY_ROOT_HASH_VERIFICATION_OPTS)
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,
if (v->mode == DM_VERITY_MODE_LOGGING)
return 0;
if (v->mode == DM_VERITY_MODE_RESTART) {
pr_emerg("dm-verity device corrupted\n");
emergency_restart();
}
if (v->mode == DM_VERITY_MODE_RESTART)
kernel_restart("dm-verity device corrupted");
if (v->mode == DM_VERITY_MODE_PANIC)
panic("dm-verity device corrupted");
......@@ -585,6 +585,11 @@ static inline bool verity_is_system_shutting_down(void)
|| system_state == SYSTEM_RESTART;
}
static void restart_io_error(struct work_struct *w)
{
kernel_restart("dm-verity device has I/O error");
}
/*
* End one "io" structure with a given error.
*/
......@@ -602,18 +607,18 @@ static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
if (unlikely(status != BLK_STS_OK) &&
unlikely(!(bio->bi_opf & REQ_RAHEAD)) &&
!verity_is_system_shutting_down()) {
if (v->mode == DM_VERITY_MODE_RESTART ||
v->mode == DM_VERITY_MODE_PANIC)
DMERR_LIMIT("%s has error: %s", v->data_dev->name,
blk_status_to_str(status));
if (v->mode == DM_VERITY_MODE_RESTART) {
pr_emerg("dm-verity device corrupted\n");
emergency_restart();
if (v->error_mode == DM_VERITY_MODE_PANIC) {
panic("dm-verity device has I/O error");
}
if (v->error_mode == DM_VERITY_MODE_RESTART) {
static DECLARE_WORK(restart_work, restart_io_error);
queue_work(v->verify_wq, &restart_work);
/*
* We deliberately don't call bio_endio here, because
* the machine will be restarted anyway.
*/
return;
}
if (v->mode == DM_VERITY_MODE_PANIC)
panic("dm-verity device corrupted");
}
bio_endio(bio);
......@@ -824,6 +829,8 @@ static void verity_status(struct dm_target *ti, status_type_t type,
DMEMIT("%02x", v->salt[x]);
if (v->mode != DM_VERITY_MODE_EIO)
args++;
if (v->error_mode != DM_VERITY_MODE_EIO)
args++;
if (verity_fec_is_enabled(v))
args += DM_VERITY_OPTS_FEC;
if (v->zero_digest)
......@@ -853,6 +860,19 @@ static void verity_status(struct dm_target *ti, status_type_t type,
BUG();
}
}
if (v->error_mode != DM_VERITY_MODE_EIO) {
DMEMIT(" ");
switch (v->error_mode) {
case DM_VERITY_MODE_RESTART:
DMEMIT(DM_VERITY_OPT_ERROR_RESTART);
break;
case DM_VERITY_MODE_PANIC:
DMEMIT(DM_VERITY_OPT_ERROR_PANIC);
break;
default:
BUG();
}
}
if (v->zero_digest)
DMEMIT(" " DM_VERITY_OPT_IGN_ZEROES);
if (v->validated_blocks)
......@@ -905,6 +925,19 @@ static void verity_status(struct dm_target *ti, status_type_t type,
DMEMIT("invalid");
}
}
if (v->error_mode != DM_VERITY_MODE_EIO) {
DMEMIT(",verity_error_mode=");
switch (v->error_mode) {
case DM_VERITY_MODE_RESTART:
DMEMIT(DM_VERITY_OPT_ERROR_RESTART);
break;
case DM_VERITY_MODE_PANIC:
DMEMIT(DM_VERITY_OPT_ERROR_PANIC);
break;
default:
DMEMIT("invalid");
}
}
DMEMIT(";");
break;
}
......@@ -1107,6 +1140,25 @@ static int verity_parse_verity_mode(struct dm_verity *v, const char *arg_name)
return 0;
}
static inline bool verity_is_verity_error_mode(const char *arg_name)
{
return (!strcasecmp(arg_name, DM_VERITY_OPT_ERROR_RESTART) ||
!strcasecmp(arg_name, DM_VERITY_OPT_ERROR_PANIC));
}
static int verity_parse_verity_error_mode(struct dm_verity *v, const char *arg_name)
{
if (v->error_mode)
return -EINVAL;
if (!strcasecmp(arg_name, DM_VERITY_OPT_ERROR_RESTART))
v->error_mode = DM_VERITY_MODE_RESTART;
else if (!strcasecmp(arg_name, DM_VERITY_OPT_ERROR_PANIC))
v->error_mode = DM_VERITY_MODE_PANIC;
return 0;
}
static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
struct dm_verity_sig_opts *verify_args,
bool only_modifier_opts)
......@@ -1141,6 +1193,16 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v,
}
continue;
} else if (verity_is_verity_error_mode(arg_name)) {
if (only_modifier_opts)
continue;
r = verity_parse_verity_error_mode(v, arg_name);
if (r) {
ti->error = "Conflicting error handling parameters";
return r;
}
continue;
} else if (!strcasecmp(arg_name, DM_VERITY_OPT_IGN_ZEROES)) {
if (only_modifier_opts)
continue;
......
......@@ -64,6 +64,7 @@ struct dm_verity {
unsigned int digest_size; /* digest size for the current hash algorithm */
unsigned int hash_reqsize; /* the size of temporary space for crypto */
enum verity_mode mode; /* mode for handling verification errors */
enum verity_mode error_mode;/* mode for handling I/O errors */
unsigned int corrupted_errs;/* Number of errors for corrupted blocks */
struct workqueue_struct *verify_wq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment