mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
vdo: refactor conversion to vdo lv
Introduce struct vdo_convert_params {} to pass-in all the parameters needed for the conversion of an LV to a vdopool + vdo LV. Function convert_vdo_lv() is also able to create a new LV and swap segments, so the passed in LV can be later on use for futher conversion so this refactoring makes it ready for more enhanced usage.
This commit is contained in:
parent
7544b9fc10
commit
6ec2f1f44b
@ -1402,6 +1402,8 @@ int convert_vdo_pool_lv(struct logical_volume *data_lv,
|
||||
uint32_t *virtual_extents,
|
||||
int format,
|
||||
uint64_t vdo_pool_header_size);
|
||||
struct logical_volume *convert_vdo_lv(struct logical_volume *lv,
|
||||
const struct vdo_convert_params *vcp);
|
||||
int set_vdo_write_policy(enum dm_vdo_write_policy *vwp, const char *policy);
|
||||
int fill_vdo_target_params(struct cmd_context *cmd,
|
||||
struct dm_vdo_target_params *vtp,
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "lib/activate/activate.h"
|
||||
#include "lib/config/defaults.h"
|
||||
#include "lib/misc/lvm-exec.h"
|
||||
#include "lib/metadata/lv_alloc.h"
|
||||
|
||||
#include <sys/sysinfo.h> // sysinfo
|
||||
#include <stdarg.h>
|
||||
@ -441,6 +442,115 @@ int convert_vdo_pool_lv(struct logical_volume *data_lv,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert LV into vdopool data LV and build virtual VDO LV on top of it.
|
||||
* After this it swaps these two LVs so the returned LV is VDO LV!
|
||||
*/
|
||||
struct logical_volume *convert_vdo_lv(struct logical_volume *lv,
|
||||
const struct vdo_convert_params *vcp)
|
||||
{
|
||||
struct cmd_context *cmd = lv->vg->cmd;
|
||||
char vdopool_name[NAME_LEN], vdopool_tmpl[NAME_LEN];
|
||||
struct lvcreate_params lvc = {
|
||||
.activate = vcp->activate,
|
||||
.alloc = ALLOC_INHERIT,
|
||||
.lv_name = vcp->lv_name ? : lv->name, /* preserve the name */
|
||||
.major = -1,
|
||||
.minor = -1,
|
||||
.permission = LVM_READ | LVM_WRITE,
|
||||
.pool_name = vdopool_name,
|
||||
.pvh = &lv->vg->pvs,
|
||||
.read_ahead = DM_READ_AHEAD_AUTO,
|
||||
.stripes = 1,
|
||||
.suppress_zero_warn = 1, /* suppress warning for this VDO */
|
||||
.tags = DM_LIST_HEAD_INIT(lvc.tags),
|
||||
.virtual_extents = vcp->virtual_extents ? : lv->le_count, /* same size for Pool and Virtual LV */
|
||||
};
|
||||
struct logical_volume *vdo_lv, tmp_lv = {
|
||||
.segments = DM_LIST_HEAD_INIT(tmp_lv.segments)
|
||||
};
|
||||
|
||||
if (!(lvc.segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_VDO)))
|
||||
return_NULL;
|
||||
|
||||
if (activation() &&
|
||||
lvc.segtype->ops->target_present &&
|
||||
!lvc.segtype->ops->target_present(cmd, NULL, &lvc.target_attr)) {
|
||||
log_error("%s: Required device-mapper target(s) not detected in your kernel.",
|
||||
lvc.segtype->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!vcp->lv_name) {
|
||||
/* TODO: maybe _vpool would be sufficient */
|
||||
if (dm_snprintf(vdopool_tmpl, sizeof(vdopool_tmpl), "%s_vpool%%d", lv->name) < 0) {
|
||||
log_error("Can't prepare vdo pool name for %s.", display_lvname(lv));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!generate_lv_name(lv->vg, vdopool_tmpl, vdopool_name, sizeof(vdopool_name))) {
|
||||
log_error("Can't generate new name for %s.", vdopool_tmpl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Rename to use _vpool name and release the passed-in name here */
|
||||
if (!lv_rename_update(cmd, lv, vdopool_name, 1))
|
||||
return_NULL;
|
||||
} else
|
||||
lvc.pool_name = lv->name;
|
||||
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
log_error("Aborting. Failed to activate pool metadata %s.",
|
||||
display_lvname(lv));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (vcp->do_zero) {
|
||||
if (test_mode()) {
|
||||
log_verbose("Test mode: Skipping activation, zeroing and signature wiping.");
|
||||
} else if (!(wipe_lv(lv, (struct wipe_params)
|
||||
{
|
||||
.do_zero = 1,
|
||||
.do_wipe_signatures = vcp->do_wipe_signatures,
|
||||
.yes = vcp->yes,
|
||||
.force = vcp->force
|
||||
}))) {
|
||||
log_error("Aborting. Failed to wipe VDO data store %s.",
|
||||
display_lvname(lv));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!convert_vdo_pool_lv(lv, &vcp->vdo_params, &lv->le_count, 1, 0))
|
||||
return_NULL;
|
||||
|
||||
/* Create VDO LV with the name, we just release above */
|
||||
if (!(vdo_lv = lv_create_single(lv->vg, &lvc)))
|
||||
return_NULL;
|
||||
|
||||
if (vcp->lv_name)
|
||||
return vdo_lv;
|
||||
|
||||
/* Swap vdo_lv and lv segment, so passed-in LV appears as virtual VDO_LV */
|
||||
if (!move_lv_segments(&tmp_lv, lv, 0, 0) ||
|
||||
!move_lv_segments(lv, vdo_lv, 0, 0) ||
|
||||
!move_lv_segments(vdo_lv, &tmp_lv, 0, 0))
|
||||
return_NULL;
|
||||
|
||||
/* Also swap naming, so the passed in LV keeps the passed-in name */
|
||||
vdo_lv->name = lv->name;
|
||||
lv->name = lvc.lv_name;
|
||||
|
||||
/* Swap segment referencing */
|
||||
if (!remove_seg_from_segs_using_this_lv(lv, first_seg(lv)))
|
||||
return_NULL;
|
||||
|
||||
if (!set_lv_segment_area_lv(first_seg(lv), 0, vdo_lv, 0, 0))
|
||||
return_NULL;
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
int set_vdo_write_policy(enum dm_vdo_write_policy *vwp, const char *policy)
|
||||
{
|
||||
if (strcasecmp(policy, "sync") == 0)
|
||||
|
@ -5453,97 +5453,56 @@ static int _lvconvert_to_vdopool_single(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct processing_handle *handle)
|
||||
{
|
||||
const char *vg_name = NULL;
|
||||
unsigned int vdo_pool_zero;
|
||||
uint64_t vdo_pool_header_size;
|
||||
struct volume_group *vg = lv->vg;
|
||||
struct logical_volume *vdo_lv;
|
||||
struct dm_vdo_target_params vdo_params; /* vdo */
|
||||
struct lvcreate_params lvc = {
|
||||
const char *vg_name = NULL;
|
||||
uint64_t vdo_pool_header_size;
|
||||
struct vdo_convert_params vcp = {
|
||||
.activate = CHANGE_AEY,
|
||||
.alloc = ALLOC_INHERIT,
|
||||
.major = -1,
|
||||
.minor = -1,
|
||||
.suppress_zero_warn = 1, /* Suppress warning for this VDO */
|
||||
.permission = LVM_READ | LVM_WRITE,
|
||||
.pool_name = lv->name,
|
||||
.pvh = &vg->pvs,
|
||||
.read_ahead = arg_uint_value(cmd, readahead_ARG, DM_READ_AHEAD_AUTO),
|
||||
.stripes = 1,
|
||||
.lv_name = arg_str_value(cmd, name_ARG, NULL),
|
||||
.virtual_extents = extents_from_size(cmd,
|
||||
arg_uint64_value(cmd, virtualsize_ARG, UINT64_C(0)),
|
||||
vg->extent_size),
|
||||
.do_zero = arg_int_value(cmd, zero_ARG, 1),
|
||||
.do_wipe_signatures = 1,
|
||||
.yes = arg_count(cmd, yes_ARG),
|
||||
.force = arg_count(cmd, force_ARG)
|
||||
};
|
||||
|
||||
if (lvc.lv_name &&
|
||||
!validate_restricted_lvname_param(cmd, &vg_name, &lvc.lv_name))
|
||||
if (vcp.lv_name) {
|
||||
if (!validate_restricted_lvname_param(cmd, &vg_name, &vcp.lv_name))
|
||||
goto_out;
|
||||
} else
|
||||
vcp.lv_name = "lvol%d";
|
||||
|
||||
if (!fill_vdo_target_params(cmd, &vcp.vdo_params, &vdo_pool_header_size, vg->profile))
|
||||
goto_out;
|
||||
|
||||
lvc.virtual_extents = extents_from_size(cmd,
|
||||
arg_uint64_value(cmd, virtualsize_ARG, UINT64_C(0)),
|
||||
vg->extent_size);
|
||||
|
||||
if (!(lvc.segtype = get_segtype_from_string(cmd, SEG_TYPE_NAME_VDO)))
|
||||
goto_out;
|
||||
|
||||
if (activation() && lvc.segtype->ops->target_present) {
|
||||
if (!lvc.segtype->ops->target_present(cmd, NULL, &lvc.target_attr)) {
|
||||
log_error("%s: Required device-mapper target(s) not detected in your kernel.",
|
||||
lvc.segtype->name);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fill_vdo_target_params(cmd, &vdo_params, &vdo_pool_header_size, vg->profile))
|
||||
goto_out;
|
||||
|
||||
if (!get_vdo_settings(cmd, &vdo_params, NULL))
|
||||
if (!get_vdo_settings(cmd, &vcp.vdo_params, NULL))
|
||||
goto_out;
|
||||
|
||||
/* If LV is inactive here, ensure it's not active elsewhere. */
|
||||
if (!lockd_lv(cmd, lv, "ex", 0))
|
||||
goto_out;
|
||||
|
||||
if (!activate_lv(cmd, lv)) {
|
||||
log_error("Cannot activate %s.", display_lvname(lv));
|
||||
goto out;
|
||||
}
|
||||
|
||||
vdo_pool_zero = arg_int_value(cmd, zero_ARG, 1);
|
||||
|
||||
log_warn("WARNING: Converting logical volume %s to VDO pool volume %s formatting.",
|
||||
display_lvname(lv), vdo_pool_zero ? "with" : "WITHOUT");
|
||||
display_lvname(lv), vcp.do_zero ? "with" : "WITHOUT");
|
||||
|
||||
if (vdo_pool_zero)
|
||||
if (vcp.do_zero)
|
||||
log_warn("THIS WILL DESTROY CONTENT OF LOGICAL VOLUME (filesystem etc.)");
|
||||
else
|
||||
log_warn("WARNING: Using invalid VDO pool data MAY DESTROY YOUR DATA!");
|
||||
|
||||
if (!arg_count(cmd, yes_ARG) &&
|
||||
if (!vcp.yes &&
|
||||
yes_no_prompt("Do you really want to convert %s? [y/n]: ",
|
||||
display_lvname(lv)) == 'n') {
|
||||
log_error("Conversion aborted.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (vdo_pool_zero) {
|
||||
if (test_mode()) {
|
||||
log_verbose("Test mode: Skipping activation, zeroing and signature wiping.");
|
||||
} else if (!wipe_lv(lv, (struct wipe_params) { .do_zero = 1, .do_wipe_signatures = 1,
|
||||
.yes = arg_count(cmd, yes_ARG),
|
||||
.force = arg_count(cmd, force_ARG)})) {
|
||||
log_error("Aborting. Failed to wipe VDO data store.");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!convert_vdo_pool_lv(lv, &vdo_params, &lvc.virtual_extents,
|
||||
vdo_pool_zero, vdo_pool_header_size))
|
||||
if (!(vdo_lv = convert_vdo_lv(lv, &vcp)))
|
||||
goto_out;
|
||||
|
||||
dm_list_init(&lvc.tags);
|
||||
|
||||
if (!(vdo_lv = lv_create_single(vg, &lvc)))
|
||||
goto_out; /* FIXME: hmmm what to do now */
|
||||
|
||||
log_print_unless_silent("Converted %s to VDO pool volume and created virtual %s VDO volume.",
|
||||
display_lvname(lv), display_lvname(vdo_lv));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user