Split low level code for creating dm devices.

The separate code for reloading device tables
will be used in later features.
This commit is contained in:
Ondrej Kozina
2018-11-13 13:33:55 +01:00
committed by Milan Broz
parent 6e1e11f6cd
commit 120ebea917
10 changed files with 175 additions and 70 deletions

View File

@@ -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_prepare_uuid(cd, name, type, uuid, dev_uuid, sizeof(dev_uuid)))
goto out;
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 (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
goto out;
if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
goto out_no_removal;
if (!dm_task_set_name(dmt, name))
goto out;
if (!dm_task_set_name(dmt, name))
goto out_no_removal;
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_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))
if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
r = 0;
out:
if (!dm_task_run(dmt))
goto 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;
}