diff --git a/lib/libcryptsetup.h b/lib/libcryptsetup.h index bfb98c53..1f5e20d6 100644 --- a/lib/libcryptsetup.h +++ b/lib/libcryptsetup.h @@ -1183,6 +1183,8 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot); #define CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE (UINT32_C(1) << 25) /** dm-integrity: reset automatic recalculation */ #define CRYPT_ACTIVATE_RECALCULATE_RESET (UINT32_C(1) << 26) +/** dm-verity: try to use tasklets */ +#define CRYPT_ACTIVATE_TASKLETS (UINT32_C(1) << 27) /** * Active device runtime attributes diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index a8d8c2a0..b4656215 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -205,6 +205,9 @@ static void _dm_set_verity_compat(struct crypt_device *cd, if (_dm_satisfies_version(1, 7, 0, verity_maj, verity_min, verity_patch)) _dm_flags |= DM_VERITY_PANIC_CORRUPTION_SUPPORTED; + if (_dm_satisfies_version(1, 9, 0, verity_maj, verity_min, verity_patch)) + _dm_flags |= DM_VERITY_TASKLETS_SUPPORTED; + _dm_verity_checked = true; } @@ -734,6 +737,8 @@ static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags) num_options++; if (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) num_options++; + if (flags & CRYPT_ACTIVATE_TASKLETS) + num_options++; max_fec_size = (tgt->u.verity.fec_device ? strlen(device_block_path(tgt->u.verity.fec_device)) : 0) + 256; fec_features = crypt_safe_alloc(max_fec_size); @@ -764,13 +769,14 @@ static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags) } else *verity_verify_args = '\0'; - if (num_options) { /* MAX length int32 + 18 + 22 + 20 + 19 + 19 */ - r = snprintf(features, sizeof(features), " %d%s%s%s%s%s", num_options, + if (num_options) { /* MAX length int32 + 18 + 22 + 20 + 19 + 19 + 22 */ + r = snprintf(features, sizeof(features), " %d%s%s%s%s%s%s", num_options, (flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) ? " ignore_corruption" : "", (flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) ? " restart_on_corruption" : "", (flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION) ? " panic_on_corruption" : "", (flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS) ? " ignore_zero_blocks" : "", - (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? " check_at_most_once" : ""); + (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? " check_at_most_once" : "", + (flags & CRYPT_ACTIVATE_TASKLETS) ? " try_verify_in_tasklet" : ""); if (r < 0 || (size_t)r >= sizeof(features)) goto out; } else @@ -1705,6 +1711,12 @@ int dm_create_device(struct crypt_device *cd, const char *name, r = -EINVAL; } + if (dmd->flags & CRYPT_ACTIVATE_TASKLETS && + !(dmt_flags & DM_VERITY_TASKLETS_SUPPORTED)) { + log_err(cd, _("Requested dm-verity tasklets option is not supported.")); + r = -EINVAL; + } + if (dmd->flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION && !(dmt_flags & DM_VERITY_PANIC_CORRUPTION_SUPPORTED)) { log_err(cd, _("Requested dm-verity data corruption handling options are not supported.")); @@ -2289,6 +2301,8 @@ static int _dm_target_query_verity(struct crypt_device *cd, *act_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS; else if (!strcasecmp(arg, "check_at_most_once")) *act_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE; + else if (!strcasecmp(arg, "try_verify_in_tasklet")) + *act_flags |= CRYPT_ACTIVATE_TASKLETS; else if (!strcasecmp(arg, "use_fec_from_device")) { str = strsep(¶ms, " "); str2 = crypt_lookup_dev(str); diff --git a/lib/utils_dm.h b/lib/utils_dm.h index 3bde9f3e..284b8c37 100644 --- a/lib/utils_dm.h +++ b/lib/utils_dm.h @@ -75,6 +75,7 @@ static inline uint32_t act2dmflags(uint32_t act_flags) #define DM_CRYPT_NO_WORKQUEUE_SUPPORTED (1 << 25) /* dm-crypt suppot for bypassing workqueues */ #define DM_INTEGRITY_FIX_HMAC_SUPPORTED (1 << 26) /* hmac covers also superblock */ #define DM_INTEGRITY_RESET_RECALC_SUPPORTED (1 << 27) /* dm-integrity automatic recalculation supported */ +#define DM_VERITY_TASKLETS_SUPPORTED (1 << 28) /* dm-verity tasklets supported */ typedef enum { DM_CRYPT = 0, DM_VERITY, DM_INTEGRITY, DM_LINEAR, DM_ERROR, DM_ZERO, DM_UNKNOWN } dm_target_type; enum tdirection { TARGET_EMPTY = 0, TARGET_SET, TARGET_QUERY }; diff --git a/man/veritysetup.8.adoc b/man/veritysetup.8.adoc index 837e258d..36d15018 100644 --- a/man/veritysetup.8.adoc +++ b/man/veritysetup.8.adoc @@ -58,7 +58,7 @@ The is a hexadecimal string. ** can be [--hash-offset, --no-superblock, --ignore-corruption or --restart-on-corruption, --panic-on-corruption, --ignore-zero-blocks, ---check-at-most-once, --root-hash-signature, --root-hash-file]. +--check-at-most-once, --root-hash-signature, --root-hash-file, --use-tasklets]. If option --root-hash-file is used, the root hash is read from instead of from the command line parameter. Expects hex-encoded text, @@ -213,6 +213,10 @@ Path to root hash signature file used to verify the root hash (in kernel). This feature requires Linux kernel version 5.4 or more recent. +*--use-tasklets*:: +Try to use kernel tasklets in dm-verity driver for performance reasons. +This option is available since Linux kernel version 6.0. + *--deferred*:: Defers device removal in *close* command until the last user closes it. diff --git a/src/utils_arg_names.h b/src/utils_arg_names.h index 81b868cc..c174ecab 100644 --- a/src/utils_arg_names.h +++ b/src/utils_arg_names.h @@ -158,6 +158,7 @@ #define OPT_USE_FSYNC "use-fsync" #define OPT_USE_RANDOM "use-random" #define OPT_USE_URANDOM "use-urandom" +#define OPT_USE_TASKLETS "use-tasklets" #define OPT_UUID "uuid" #define OPT_VERACRYPT "veracrypt" #define OPT_VERACRYPT_PIM "veracrypt-pim" diff --git a/src/veritysetup.c b/src/veritysetup.c index 2d96bd65..88249efa 100644 --- a/src/veritysetup.c +++ b/src/veritysetup.c @@ -184,6 +184,8 @@ static int _activate(const char *dm_device, activate_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS; if (ARG_SET(OPT_CHECK_AT_MOST_ONCE_ID)) activate_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE; + if (ARG_SET(OPT_USE_TASKLETS_ID)) + activate_flags |= CRYPT_ACTIVATE_TASKLETS; if (!ARG_SET(OPT_NO_SUPERBLOCK_ID)) { params.flags = flags; @@ -436,13 +438,15 @@ static int action_status(void) CRYPT_ACTIVATE_RESTART_ON_CORRUPTION| CRYPT_ACTIVATE_PANIC_ON_CORRUPTION| CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS| - CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE)) - log_std(" flags: %s%s%s%s%s\n", + CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE| + CRYPT_ACTIVATE_TASKLETS)) + log_std(" flags: %s%s%s%s%s%s\n", (cad.flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) ? "ignore_corruption " : "", (cad.flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) ? "restart_on_corruption " : "", (cad.flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION) ? "panic_on_corruption " : "", (cad.flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS) ? "ignore_zero_blocks " : "", - (cad.flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? "check_at_most_once" : ""); + (cad.flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? "check_at_most_once" : "", + (cad.flags & CRYPT_ACTIVATE_TASKLETS) ? "try_verify_in_tasklet" : ""); } out: crypt_free(cd); diff --git a/src/veritysetup_arg_list.h b/src/veritysetup_arg_list.h index 9e936c51..9b1f949a 100644 --- a/src/veritysetup_arg_list.h +++ b/src/veritysetup_arg_list.h @@ -63,6 +63,8 @@ ARG(OPT_ROOT_HASH_SIGNATURE, '\0', POPT_ARG_STRING, N_("Path to root hash signat ARG(OPT_SALT, 's', POPT_ARG_STRING, N_("Salt"), N_("hex string"), CRYPT_ARG_STRING, {}, {}) +ARG(OPT_USE_TASKLETS, '\0', POPT_ARG_NONE, N_("Use kernel tasklets for performance"), NULL, CRYPT_ARG_BOOL, {}, OPT_USE_TASKLETS_ACTIONS) + ARG(OPT_UUID, '\0', POPT_ARG_STRING, N_("UUID for device to use"), NULL, CRYPT_ARG_STRING, {}, {}) ARG(OPT_VERBOSE, 'v', POPT_ARG_NONE, N_("Shows more detailed error messages"), NULL, CRYPT_ARG_BOOL, {}, {}) diff --git a/src/veritysetup_args.h b/src/veritysetup_args.h index 2d5aaf54..4c2c61c0 100644 --- a/src/veritysetup_args.h +++ b/src/veritysetup_args.h @@ -39,6 +39,7 @@ #define OPT_PANIC_ON_CORRUPTION_ACTIONS { OPEN_ACTION } #define OPT_ROOT_HASH_FILE_ACTIONS { FORMAT_ACTION, OPEN_ACTION, VERIFY_ACTION } #define OPT_ROOT_HASH_SIGNATURE_ACTIONS { OPEN_ACTION } +#define OPT_USE_TASKLETS_ACTIONS { OPEN_ACTION } enum { OPT_UNUSED_ID = 0, diff --git a/tests/verity-compat-test b/tests/verity-compat-test index c3019768..f9bfdb46 100755 --- a/tests/verity-compat-test +++ b/tests/verity-compat-test @@ -476,6 +476,11 @@ if check_version 1 3; then if check_version 1 7; then check_option 512 $HASH $SALT 1 sha256 "--panic-on-corruption" "panic_on_corruption" fi + + if check_version 1 9; then + echo "Verity data performance options test." + check_option 512 $HASH $SALT 1 sha256 "--use-tasklets" "try_verify_in_tasklet" + fi fi echo "Veritysetup [hash-offset bigger than 2G works] "