Commit 120ebea9 authored by Ondrej Kozina's avatar Ondrej Kozina Committed by Milan Broz

Split low level code for creating dm devices.

The separate code for reloading device tables
will be used in later features.
parent 6e1e11f6
......@@ -237,7 +237,7 @@ int INTEGRITY_activate(struct crypt_device *cd,
return r;
}
r = dm_create_device(cd, name, "INTEGRITY", &dmdi, 0);
r = dm_create_device(cd, name, "INTEGRITY", &dmdi);
if (r < 0 && (dm_flags(cd, DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) {
log_err(cd, _("Kernel doesn't support dm-integrity mapping."));
return -ENOTSUP;
......@@ -309,7 +309,7 @@ int INTEGRITY_format(struct crypt_device *cd,
if (params && params->integrity_key_size)
dmdi.u.integrity.vk = crypt_alloc_volume_key(params->integrity_key_size, NULL);
r = dm_create_device(cd, tmp_name, "INTEGRITY", &dmdi, 0);
r = dm_create_device(cd, tmp_name, "INTEGRITY", &dmdi);
crypt_free_volume_key(dmdi.u.integrity.vk);
if (r)
......
......@@ -900,6 +900,8 @@ out:
return r;
}
static int _dm_resume_device(const char *name, uint32_t flags);
static int _error_device(const char *name, size_t size)
{
struct dm_task *dmt;
......@@ -923,7 +925,7 @@ static int _error_device(const char *name, size_t size)
if (!dm_task_run(dmt))
goto error;
if (!_dm_simple(DM_DEVICE_RESUME, name, 1)) {
if (_dm_resume_device(name, 0)) {
_dm_simple(DM_DEVICE_CLEAR, name, 0);
goto error;
}
......@@ -1051,16 +1053,14 @@ int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char
static int _dm_create_device(struct crypt_device *cd, const char *name, const char *type,
struct device *device, uint32_t flags,
const char *uuid, uint64_t size,
dm_target_type target, char *params, int reload)
dm_target_type target, char *params)
{
struct dm_task *dmt = NULL;
struct dm_info dmi;
char dev_uuid[DM_UUID_LEN] = {0};
const char *target_name;
int r = -EINVAL;
uint32_t read_ahead = 0;
uint32_t cookie = 0;
uint32_t dmt_flags;
uint32_t dmt_flags, cookie = 0, read_ahead = 0;
uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
/* Only need DM_SECURE_SUPPORTED, no target specific fail matters */
......@@ -1082,74 +1082,49 @@ static int _dm_create_device(struct crypt_device *cd, const char *name, const ch
udev_flags |= CRYPT_TEMP_UDEV_FLAGS;
/* All devices must have DM_UUID, only resize on old device is exception */
if (reload) {
if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
goto out_no_removal;
if (!dm_task_set_name(dmt, name))
goto out_no_removal;
} else {
if (!dm_prepare_uuid(cd, name, type, uuid, dev_uuid, sizeof(dev_uuid)))
goto out_no_removal;
if (!dm_prepare_uuid(cd, name, type, uuid, dev_uuid, sizeof(dev_uuid)))
goto out;
if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
goto out_no_removal;
if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
goto out;
if (!dm_task_set_name(dmt, name))
goto out_no_removal;
if (!dm_task_set_name(dmt, name))
goto out;
if (!dm_task_set_uuid(dmt, dev_uuid))
goto out_no_removal;
}
if (!dm_task_set_uuid(dmt, dev_uuid))
goto out;
if ((dmt_flags & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
goto out_no_removal;
goto out;
if ((flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
goto out_no_removal;
goto out;
if (!dm_task_add_target(dmt, 0, size, target_name, params))
goto out_no_removal;
goto out;
#ifdef DM_READ_AHEAD_MINIMUM_FLAG
if (device_read_ahead(device, &read_ahead) &&
!dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
goto out_no_removal;
goto out;
#endif
/* do not set cookie for DM_DEVICE_RELOAD task */
if (!reload && _dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out_no_removal;
if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
if (!dm_task_run(dmt))
goto out_no_removal;
if (reload) {
dm_task_destroy(dmt);
if (!(dmt = dm_task_create(DM_DEVICE_RESUME)))
goto out;
if (!dm_task_set_name(dmt, name))
goto out;
if (uuid && !dm_task_set_uuid(dmt, dev_uuid))
goto out;
if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
if (!dm_task_run(dmt))
goto out;
}
if (!dm_task_get_info(dmt, &dmi))
goto out;
r = 0;
out:
if (dm_task_get_info(dmt, &dmi))
r = 0;
if (_dm_use_udev()) {
(void)_dm_udev_wait(cookie);
cookie = 0;
}
if (r < 0 && !reload)
if (r < 0)
_dm_remove(name, 1, 0);
out_no_removal:
out:
if (cookie && _dm_use_udev())
(void)_dm_udev_wait(cookie);
......@@ -1164,6 +1139,96 @@ out_no_removal:
return r;
}
static int _dm_resume_device(const char *name, uint32_t flags)
{
struct dm_task *dmt;
int r = -EINVAL;
uint32_t cookie = 0;
uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
if (flags & CRYPT_ACTIVATE_PRIVATE)
udev_flags |= CRYPT_TEMP_UDEV_FLAGS;
if (!(dmt = dm_task_create(DM_DEVICE_RESUME)))
return r;
if (!dm_task_set_name(dmt, name))
goto out;
if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
if (dm_task_run(dmt))
r = 0;
out:
if (cookie && _dm_use_udev())
(void)_dm_udev_wait(cookie);
dm_task_destroy(dmt);
dm_task_update_nodes();
return r;
}
static int _dm_reload_device(struct crypt_device *cd,
const char *name, struct device *device,
uint32_t flags, uint64_t size,
dm_target_type target, const char *params)
{
const char *target_name;
int r = -EINVAL;
struct dm_task *dmt = NULL;
uint32_t dmt_flags = 0, read_ahead = 0;
if (target == DM_CRYPT)
target_name = DM_CRYPT_TARGET;
else if (target == DM_VERITY)
target_name = DM_VERITY_TARGET;
else if (target == DM_INTEGRITY)
target_name = DM_INTEGRITY_TARGET;
else
return -EINVAL;
/* All devices must have DM_UUID, only resize on old device is exception */
if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
goto out;
if (!dm_task_set_name(dmt, name))
goto out;
if (dm_flags(cd, target, &dmt_flags))
goto out;
if ((dmt_flags & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
goto out;
/* FIXME: resume only ?*/
if ((flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
goto out;
if (!dm_task_add_target(dmt, 0, size, target_name, params))
goto out;
#ifdef DM_READ_AHEAD_MINIMUM_FLAG
if (device_read_ahead(device, &read_ahead) &&
!dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
goto out;
#endif
if (dm_task_run(dmt))
r = 0;
out:
if (dmt)
dm_task_destroy(dmt);
/* If code just loaded target module, update versions */
_dm_check_versions(cd, target);
return r;
}
static int check_retry(struct crypt_device *cd, uint32_t *dmd_flags, uint32_t dmt_flags)
{
int ret = 0;
......@@ -1197,8 +1262,7 @@ static int check_retry(struct crypt_device *cd, uint32_t *dmd_flags, uint32_t dm
int dm_create_device(struct crypt_device *cd, const char *name,
const char *type,
struct crypt_dm_active_device *dmd,
int reload)
struct crypt_dm_active_device *dmd)
{
char *table_params = NULL;
uint32_t dmd_flags, dmt_flags;
......@@ -1223,16 +1287,16 @@ int dm_create_device(struct crypt_device *cd, const char *name,
goto out;
r = _dm_create_device(cd, name, type, dmd->data_device, dmd_flags,
dmd->uuid, dmd->size, dmd->target, table_params, reload);
dmd->uuid, dmd->size, dmd->target, table_params);
if (r < 0 && dm_flags(cd, dmd->target, &dmt_flags))
goto out;
if (!reload && r && dmd->target == DM_CRYPT && check_retry(cd, &dmd_flags, dmt_flags)) {
if (r && dmd->target == DM_CRYPT && check_retry(cd, &dmd_flags, dmt_flags)) {
crypt_safe_free(table_params);
table_params = get_dm_crypt_params(dmd, dmd_flags);
r = _dm_create_device(cd, name, type, dmd->data_device, dmd_flags,
dmd->uuid, dmd->size, dmd->target, table_params, reload);
dmd->uuid, dmd->size, dmd->target, table_params);
}
if (r == -EINVAL &&
......@@ -1263,6 +1327,46 @@ out:
return r;
}
int dm_reload_device(struct crypt_device *cd, const char *name,
struct crypt_dm_active_device *dmd, unsigned resume)
{
char *table_params = NULL;
uint32_t dmt_flags;
int r = -EINVAL;
if (dm_init_context(cd, dmd->target))
return -ENOTSUP;
dm_flags(cd, dmd->target, &dmt_flags);
if (dmd->target == DM_CRYPT)
table_params = get_dm_crypt_params(dmd, dmd->flags);
else if (dmd->target == DM_VERITY)
table_params = get_dm_verity_params(dmd->u.verity.vp, dmd, dmd->flags);
else if (dmd->target == DM_INTEGRITY)
table_params = get_dm_integrity_params(dmd, dmd->flags, dmt_flags);
else
return r;
r = _dm_reload_device(cd, name, dmd->data_device, dmd->flags, dmd->size,
dmd->target, table_params);
if (r == -EINVAL && dmd->target == DM_CRYPT) {
if ((dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)) &&
!dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
log_err(cd, _("Requested dm-crypt performance options are not supported."));
if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
!dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & DM_DISCARDS_SUPPORTED))
log_err(cd, _("Discard/TRIM is not supported."));
}
if (!r && resume)
r = _dm_resume_device(name, dmd->flags);
dm_exit_context();
return r;
}
static int dm_status_dmi(const char *name, struct dm_info *dmi,
const char *target, char **status_line)
{
......@@ -2138,7 +2242,7 @@ int dm_suspend_and_wipe_key(struct crypt_device *cd, const char *name)
}
if (!_dm_message(name, "key wipe", dmt_flags)) {
_dm_simple(DM_DEVICE_RESUME, name, 1);
_dm_resume_device(name, 0);
r = -EINVAL;
goto out;
}
......@@ -2180,7 +2284,7 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
hex_key(&msg[8], vk->keylength, vk->key);
if (!_dm_message(name, msg, dmt_flags) ||
!_dm_simple(DM_DEVICE_RESUME, name, 1)) {
_dm_resume_device(name, 0)) {
r = -EINVAL;
goto out;
}
......
......@@ -239,7 +239,7 @@ int LOOPAES_activate(struct crypt_device *cd,
log_dbg(cd, "Trying to activate loop-AES device %s using cipher %s.",
name, dmd.u.crypt.cipher);
r = dm_create_device(cd, name, CRYPT_LOOPAES, &dmd, 0);
r = dm_create_device(cd, name, CRYPT_LOOPAES, &dmd);
if (r < 0 && !dm_flags(cd, DM_CRYPT, &dmc_flags) &&
(dmc_flags & req_flags) != req_flags) {
......
......@@ -110,7 +110,7 @@ static int LUKS_endec_template(char *src, size_t srcLength,
return -EACCES;
}
r = dm_create_device(ctx, name, "TEMP", &dmd, 0);
r = dm_create_device(ctx, name, "TEMP", &dmd);
if (r < 0) {
if (r != -EACCES && r != -ENOTSUP)
_error_hint(ctx, device_path(dmd.data_device),
......
......@@ -1189,7 +1189,7 @@ int LUKS1_activate(struct crypt_device *cd,
return -ENOMEM;
dmd.u.crypt.cipher = dm_cipher;
r = dm_create_device(cd, name, CRYPT_LUKS1, &dmd, 0);
r = dm_create_device(cd, name, CRYPT_LUKS1, &dmd);
free(dm_cipher);
return r;
......
......@@ -1934,7 +1934,7 @@ int LUKS2_activate(struct crypt_device *cd,
r = device_block_adjust(cd, dmd.data_device, device_check,
dmd.u.crypt.offset, &dmd.size, &dmd.flags);
if (!r)
r = dm_create_device(cd, name, CRYPT_LUKS2, &dmd, 0);
r = dm_create_device(cd, name, CRYPT_LUKS2, &dmd);
if (r < 0 && dmd.u.crypt.integrity)
dm_remove_device(cd, dm_int_name, 0);
......
......@@ -517,7 +517,7 @@ int PLAIN_activate(struct crypt_device *cd,
log_dbg(cd, "Trying to activate PLAIN device %s using cipher %s.",
name, dmd.u.crypt.cipher);
r = dm_create_device(cd, name, CRYPT_PLAIN, &dmd, 0);
r = dm_create_device(cd, name, CRYPT_PLAIN, &dmd);
free(dm_cipher);
return r;
......@@ -2211,7 +2211,7 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
else if (isLUKS2(cd->type))
r = LUKS2_unmet_requirements(cd, &cd->u.luks2.hdr, 0, 0);
if (!r)
r = dm_create_device(cd, name, cd->type, &dmd, 1);
r = dm_reload_device(cd, name, &dmd, 1);
}
out:
if (dmd.target == DM_CRYPT) {
......
......@@ -846,7 +846,7 @@ int TCRYPT_activate(struct crypt_device *cd,
log_dbg(cd, "Trying to activate TCRYPT device %s using cipher %s.",
dm_name, dmd.u.crypt.cipher);
r = dm_create_device(cd, dm_name, CRYPT_TCRYPT, &dmd, 0);
r = dm_create_device(cd, dm_name, CRYPT_TCRYPT, &dmd);
device_free(cd, device);
device = NULL;
......
......@@ -139,8 +139,9 @@ int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint
int dm_query_device(struct crypt_device *cd, const char *name,
uint32_t get_flags, struct crypt_dm_active_device *dmd);
int dm_create_device(struct crypt_device *cd, const char *name,
const char *type, struct crypt_dm_active_device *dmd,
int reload);
const char *type, struct crypt_dm_active_device *dmd);
int dm_reload_device(struct crypt_device *cd, const char *name,
struct crypt_dm_active_device *dmd, unsigned resume);
int dm_suspend_device(struct crypt_device *cd, const char *name);
int dm_suspend_and_wipe_key(struct crypt_device *cd, const char *name);
int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
......
......@@ -303,7 +303,7 @@ int VERITY_activate(struct crypt_device *cd,
return r;
}
r = dm_create_device(cd, name, CRYPT_VERITY, &dmd, 0);
r = dm_create_device(cd, name, CRYPT_VERITY, &dmd);
if (r < 0 && (dm_flags(cd, DM_VERITY, &dmv_flags) || !(dmv_flags & DM_VERITY_SUPPORTED))) {
log_err(cd, _("Kernel doesn't support dm-verity mapping."));
return -ENOTSUP;
......
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