mirror of
git://sourceware.org/git/lvm2.git
synced 2025-03-10 16:58:47 +03:00
lvconvert: use command defs for repair and replace
Shift --repair and --replace to the new system based on command defs.
This commit is contained in:
parent
17a255b8d5
commit
ea68bb038e
@ -1364,7 +1364,8 @@ static int _lvconvert_mirrors_aux(struct cmd_context *cmd,
|
||||
struct lvconvert_params *lp,
|
||||
struct dm_list *operable_pvs,
|
||||
uint32_t new_mimage_count,
|
||||
uint32_t new_log_count)
|
||||
uint32_t new_log_count,
|
||||
struct dm_list *pvh)
|
||||
{
|
||||
uint32_t region_size;
|
||||
struct lv_segment *seg = first_seg(lv);
|
||||
@ -1384,7 +1385,7 @@ static int _lvconvert_mirrors_aux(struct cmd_context *cmd,
|
||||
vg_is_clustered(lv->vg));
|
||||
|
||||
if (!operable_pvs)
|
||||
operable_pvs = lp->pvh;
|
||||
operable_pvs = pvh;
|
||||
|
||||
/*
|
||||
* Up-convert from linear to mirror
|
||||
@ -1393,7 +1394,7 @@ static int _lvconvert_mirrors_aux(struct cmd_context *cmd,
|
||||
/* FIXME Share code with lvcreate */
|
||||
|
||||
/*
|
||||
* FIXME should we give not only lp->pvh, but also all PVs
|
||||
* FIXME should we give not only pvh, but also all PVs
|
||||
* currently taken by the mirror? Would make more sense from
|
||||
* user perspective.
|
||||
*/
|
||||
@ -1402,7 +1403,7 @@ static int _lvconvert_mirrors_aux(struct cmd_context *cmd,
|
||||
lp->alloc, MIRROR_BY_LV))
|
||||
return_0;
|
||||
|
||||
if (lp->wait_completion)
|
||||
if (!arg_is_set(cmd, background_ARG))
|
||||
lp->need_polling = 1;
|
||||
|
||||
goto out;
|
||||
@ -1579,7 +1580,8 @@ int mirror_remove_missing(struct cmd_context *cmd,
|
||||
*/
|
||||
static int _lvconvert_mirrors_repair(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct lvconvert_params *lp)
|
||||
struct lvconvert_params *lp,
|
||||
struct dm_list *pvh)
|
||||
{
|
||||
int failed_logs;
|
||||
int failed_mimages;
|
||||
@ -1590,7 +1592,6 @@ static int _lvconvert_mirrors_repair(struct cmd_context *cmd,
|
||||
uint32_t original_mimages = lv_mirror_count(lv);
|
||||
uint32_t original_logs = _get_log_count(lv);
|
||||
|
||||
cmd->handles_missing_pvs = 1;
|
||||
cmd->partial_activation = 1;
|
||||
lp->need_polling = 0;
|
||||
|
||||
@ -1646,7 +1647,7 @@ static int _lvconvert_mirrors_repair(struct cmd_context *cmd,
|
||||
while (replace_mimages || replace_logs) {
|
||||
log_warn("Trying to up-convert to %d images, %d logs.", lp->mirrors, log_count);
|
||||
if (_lvconvert_mirrors_aux(cmd, lv, lp, NULL,
|
||||
lp->mirrors, log_count))
|
||||
lp->mirrors, log_count, pvh))
|
||||
break;
|
||||
if (lp->mirrors > 2)
|
||||
--lp->mirrors;
|
||||
@ -1766,11 +1767,8 @@ static int _lvconvert_mirrors(struct cmd_context *cmd,
|
||||
(old_log_count == new_log_count) && !lp->repair)
|
||||
return 1;
|
||||
|
||||
if (lp->repair)
|
||||
return _lvconvert_mirrors_repair(cmd, lv, lp);
|
||||
|
||||
if (!_lvconvert_mirrors_aux(cmd, lv, lp, NULL,
|
||||
new_mimage_count, new_log_count))
|
||||
new_mimage_count, new_log_count, lp->pvh))
|
||||
return 0;
|
||||
|
||||
if (!lp->need_polling)
|
||||
@ -1801,33 +1799,6 @@ static int _is_valid_raid_conversion(const struct segment_type *from_segtype,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _lvconvert_raid_repair_ask(struct cmd_context *cmd,
|
||||
struct lvconvert_params *lp,
|
||||
int *replace_dev)
|
||||
{
|
||||
const char *dev_policy;
|
||||
|
||||
*replace_dev = 1;
|
||||
|
||||
if (arg_is_set(cmd, usepolicies_ARG)) {
|
||||
dev_policy = find_config_tree_str(cmd, activation_raid_fault_policy_CFG, NULL);
|
||||
|
||||
if (!strcmp(dev_policy, "allocate") ||
|
||||
!strcmp(dev_policy, "replace"))
|
||||
return;
|
||||
|
||||
/* else if (!strcmp(dev_policy, "anything_else")) -- no replace */
|
||||
*replace_dev = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!lp->yes &&
|
||||
yes_no_prompt("Attempt to replace failed RAID images "
|
||||
"(requires full device resync)? [y/n]: ") == 'n') {
|
||||
*replace_dev = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *lp)
|
||||
{
|
||||
int replace = 0, image_count = 0;
|
||||
@ -1963,49 +1934,6 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lp->replace)
|
||||
return lv_raid_replace(lv, lp->replace_pvh, lp->pvh);
|
||||
|
||||
if (lp->repair) {
|
||||
if (!lv_is_active_exclusive_locally(lv_lock_holder(lv))) {
|
||||
log_error("%s must be active %sto perform this operation.",
|
||||
display_lvname(lv),
|
||||
vg_is_clustered(lv->vg) ?
|
||||
"exclusive locally " : "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (seg_is_striped(seg)) {
|
||||
log_error("Cannot repair LV %s of type raid0.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
_lvconvert_raid_repair_ask(cmd, lp, &replace);
|
||||
|
||||
if (replace) {
|
||||
if (!(failed_pvs = _failed_pv_list(lv->vg)))
|
||||
return_0;
|
||||
|
||||
if (!lv_raid_replace(lv, failed_pvs, lp->pvh)) {
|
||||
log_error("Failed to replace faulty devices in %s.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_print_unless_silent("Faulty devices in %s successfully replaced.",
|
||||
display_lvname(lv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* "warn" if policy not set to replace */
|
||||
if (arg_is_set(cmd, usepolicies_ARG))
|
||||
log_warn("Use 'lvconvert --repair %s' to replace "
|
||||
"failed device.", display_lvname(lv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
try_new_takeover_or_reshape:
|
||||
|
||||
/* FIXME This needs changing globally. */
|
||||
@ -2509,7 +2437,7 @@ out:
|
||||
|
||||
static int _lvconvert_thin_pool_repair(struct cmd_context *cmd,
|
||||
struct logical_volume *pool_lv,
|
||||
struct lvconvert_params *lp)
|
||||
struct dm_list *pvh, int poolmetadataspare)
|
||||
{
|
||||
const char *dmdir = dm_dir();
|
||||
const char *thin_dump =
|
||||
@ -2538,7 +2466,7 @@ static int _lvconvert_thin_pool_repair(struct cmd_context *cmd,
|
||||
pmslv = pool_lv->vg->pool_metadata_spare_lv;
|
||||
|
||||
/* Check we have pool metadata spare LV */
|
||||
if (!handle_pool_metadata_spare(pool_lv->vg, 0, lp->pvh, 1))
|
||||
if (!handle_pool_metadata_spare(pool_lv->vg, 0, pvh, 1))
|
||||
return_0;
|
||||
|
||||
if (pmslv != pool_lv->vg->pool_metadata_spare_lv) {
|
||||
@ -2663,8 +2591,8 @@ deactivate_pmslv:
|
||||
}
|
||||
|
||||
/* Try to allocate new pool metadata spare LV */
|
||||
if (!handle_pool_metadata_spare(pool_lv->vg, 0, lp->pvh,
|
||||
lp->poolmetadataspare))
|
||||
if (!handle_pool_metadata_spare(pool_lv->vg, 0, pvh,
|
||||
poolmetadataspare))
|
||||
stack;
|
||||
|
||||
if (dm_snprintf(meta_path, sizeof(meta_path), "%s_meta%%d", pool_lv->name) < 0) {
|
||||
@ -3543,7 +3471,8 @@ static int _convert_thin_pool_uncache(struct cmd_context *cmd, struct logical_vo
|
||||
static int _convert_thin_pool_repair(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct lvconvert_params *lp)
|
||||
{
|
||||
return _lvconvert_thin_pool_repair(cmd, lv, lp);
|
||||
/* return _lvconvert_thin_pool_repair(cmd, lv, lp); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3731,7 +3660,7 @@ static int _convert_mirror_repair(struct cmd_context *cmd, struct logical_volume
|
||||
struct dm_list *failed_pvs;
|
||||
int ret;
|
||||
|
||||
ret = _lvconvert_mirrors_repair(cmd, lv, lp);
|
||||
ret = _lvconvert_mirrors_repair(cmd, lv, lp, lp->pvh);
|
||||
|
||||
if (ret && arg_is_set(cmd, usepolicies_ARG)) {
|
||||
if ((failed_pvs = _failed_pv_list(lv->vg)))
|
||||
@ -4711,3 +4640,305 @@ out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Below is code that has transitioned to using command defs.
|
||||
* ----------------------------------------------------------
|
||||
*
|
||||
* This code does not use read_params (or any other param reading
|
||||
* functions associated with it), or the lp struct. Those have
|
||||
* been primary vehicles for entangling all the lvconvert operations,
|
||||
* so avoiding them is important for untangling. They were also
|
||||
* heavily used for trying to figure out what the lvconvert operation
|
||||
* was meant to be doing, and that is no longer needed since the
|
||||
* command def provides it.
|
||||
*
|
||||
* All input data is already available from cmd->arg_values and
|
||||
* cmd->position_argv (the --option args in the former, the position
|
||||
* args in the later.) There is no need to copy these values into
|
||||
* another redundant struct of input values which just obfuscates.
|
||||
*
|
||||
* The new lvconvert_result struct, passed via custom_handle, is
|
||||
* used for *returning* data from processing, not for passing data
|
||||
* into processing.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Data/results accumulated during processing.
|
||||
*/
|
||||
struct lvconvert_result {
|
||||
int need_polling;
|
||||
struct dm_list poll_idls;
|
||||
};
|
||||
|
||||
static int _lvconvert_repair_pvs_mirror(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct processing_handle *handle,
|
||||
struct dm_list *use_pvh)
|
||||
{
|
||||
struct lvconvert_result *lr = (struct lvconvert_result *) handle->custom_handle;
|
||||
struct lvconvert_params lp = { 0 };
|
||||
struct convert_poll_id_list *idl;
|
||||
struct lvinfo info;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* FIXME: temporary use of lp because _lvconvert_mirrors_repair()
|
||||
* and _aux() still use lp fields everywhere.
|
||||
* Migrate them away from using lp (for the most part just use
|
||||
* local variables, and check arg_values directly).
|
||||
*/
|
||||
|
||||
/*
|
||||
* Fill in any lp fields here that this fn expects to be set before
|
||||
* it's called. It's hard to tell by reading old code, but it seems
|
||||
* that repair takes nothing like stripes/stripsize.
|
||||
*/
|
||||
lp.alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, ALLOC_INHERIT);
|
||||
|
||||
ret = _lvconvert_mirrors_repair(cmd, lv, &lp, use_pvh);
|
||||
|
||||
if (lp.need_polling) {
|
||||
if (!lv_info(cmd, lp.lv_to_poll, 0, &info, 0, 0) || !info.exists)
|
||||
log_print_unless_silent("Conversion starts after activation.");
|
||||
else {
|
||||
if (!(idl = _convert_poll_id_list_create(cmd, lp.lv_to_poll)))
|
||||
return_ECMD_FAILED;
|
||||
dm_list_add(&lr->poll_idls, &idl->list);
|
||||
}
|
||||
lr->need_polling = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _lvconvert_repair_pvs_raid_ask(struct cmd_context *cmd, int *do_it)
|
||||
{
|
||||
const char *dev_policy;
|
||||
|
||||
*do_it = 1;
|
||||
|
||||
if (arg_is_set(cmd, usepolicies_ARG)) {
|
||||
dev_policy = find_config_tree_str(cmd, activation_raid_fault_policy_CFG, NULL);
|
||||
|
||||
if (!strcmp(dev_policy, "allocate") ||
|
||||
!strcmp(dev_policy, "replace"))
|
||||
return;
|
||||
|
||||
/* else if (!strcmp(dev_policy, "anything_else")) -- no replace */
|
||||
*do_it = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!arg_count(cmd, yes_ARG) &&
|
||||
yes_no_prompt("Attempt to replace failed RAID images "
|
||||
"(requires full device resync)? [y/n]: ") == 'n') {
|
||||
*do_it = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int _lvconvert_repair_pvs_raid(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct processing_handle *handle,
|
||||
struct dm_list *use_pvh)
|
||||
{
|
||||
struct dm_list *failed_pvs;
|
||||
int do_it;
|
||||
|
||||
if (!lv_is_active_exclusive_locally(lv_lock_holder(lv))) {
|
||||
log_error("%s must be active %sto perform this operation.",
|
||||
display_lvname(lv),
|
||||
vg_is_clustered(lv->vg) ?
|
||||
"exclusive locally " : "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_lvconvert_repair_pvs_raid_ask(cmd, &do_it);
|
||||
|
||||
if (do_it) {
|
||||
if (!(failed_pvs = _failed_pv_list(lv->vg)))
|
||||
return_0;
|
||||
|
||||
if (!lv_raid_replace(lv, failed_pvs, use_pvh)) {
|
||||
log_error("Failed to replace faulty devices in %s.",
|
||||
display_lvname(lv));
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_print_unless_silent("Faulty devices in %s successfully replaced.",
|
||||
display_lvname(lv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* "warn" if policy not set to replace */
|
||||
if (arg_is_set(cmd, usepolicies_ARG))
|
||||
log_warn("Use 'lvconvert --repair %s' to replace "
|
||||
"failed device.", display_lvname(lv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _lvconvert_repair_pvs(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct processing_handle *handle)
|
||||
{
|
||||
struct dm_list *failed_pvs;
|
||||
struct dm_list *use_pvh;
|
||||
int ret;
|
||||
|
||||
/* First pos arg is required LV, remaining are optional PVs. */
|
||||
if (cmd->position_argc > 1) {
|
||||
if (!(use_pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc, cmd->position_argv, 0)))
|
||||
return_ECMD_FAILED;
|
||||
} else
|
||||
use_pvh = &lv->vg->pvs;
|
||||
|
||||
if (lv_is_raid(lv))
|
||||
ret = _lvconvert_repair_pvs_raid(cmd, lv, handle, use_pvh);
|
||||
else if (lv_is_mirror(lv))
|
||||
ret = _lvconvert_repair_pvs_mirror(cmd, lv, handle, use_pvh);
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
if (ret && arg_is_set(cmd, usepolicies_ARG)) {
|
||||
if ((failed_pvs = _failed_pv_list(lv->vg)))
|
||||
_remove_missing_empty_pv(lv->vg, failed_pvs);
|
||||
}
|
||||
|
||||
return ret ? ECMD_PROCESSED : ECMD_FAILED;
|
||||
}
|
||||
|
||||
static int _lvconvert_repair_thinpool(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct processing_handle *handle)
|
||||
{
|
||||
int poolmetadataspare = arg_int_value(cmd, poolmetadataspare_ARG, DEFAULT_POOL_METADATA_SPARE);
|
||||
struct dm_list *use_pvh;
|
||||
|
||||
/* First pos arg is required LV, remaining are optional PVs. */
|
||||
if (cmd->position_argc > 1) {
|
||||
if (!(use_pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc, cmd->position_argv, 0)))
|
||||
return_ECMD_FAILED;
|
||||
} else
|
||||
use_pvh = &lv->vg->pvs;
|
||||
|
||||
return _lvconvert_thin_pool_repair(cmd, lv, use_pvh, poolmetadataspare);
|
||||
}
|
||||
|
||||
static int _lvconvert_repair_pvs_or_thinpool(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct processing_handle *handle)
|
||||
{
|
||||
if (lv_is_thin_pool(lv))
|
||||
return _lvconvert_repair_thinpool(cmd, lv, handle);
|
||||
else if (lv_is_raid(lv) || lv_is_mirror(lv))
|
||||
return _lvconvert_repair_pvs(cmd, lv, handle);
|
||||
else
|
||||
return_ECMD_FAILED;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: add option --repair-pvs to call _lvconvert_repair_pvs() directly,
|
||||
* and option --repair-thinpool to call _lvconvert_repair_thinpool().
|
||||
*/
|
||||
int lvconvert_repair_pvs_or_thinpool_fn(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
struct processing_handle *handle;
|
||||
struct lvconvert_result lr = { 0 };
|
||||
struct convert_poll_id_list *idl;
|
||||
int saved_ignore_suspended_devices;
|
||||
int ret, poll_ret;
|
||||
|
||||
dm_list_init(&lr.poll_idls);
|
||||
|
||||
if (!(handle = init_processing_handle(cmd, NULL))) {
|
||||
log_error("Failed to initialize processing handle.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
handle->custom_handle = &lr;
|
||||
|
||||
saved_ignore_suspended_devices = ignore_suspended_devices();
|
||||
init_ignore_suspended_devices(1);
|
||||
|
||||
cmd->handles_missing_pvs = 1;
|
||||
|
||||
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL,
|
||||
READ_FOR_UPDATE, handle,
|
||||
&_lvconvert_repair_pvs_or_thinpool);
|
||||
|
||||
init_ignore_suspended_devices(saved_ignore_suspended_devices);
|
||||
|
||||
if (lr.need_polling) {
|
||||
dm_list_iterate_items(idl, &lr.poll_idls)
|
||||
poll_ret = _lvconvert_poll_by_id(cmd, idl->id,
|
||||
arg_is_set(cmd, background_ARG), 0, 0);
|
||||
if (poll_ret > ret)
|
||||
ret = poll_ret;
|
||||
}
|
||||
|
||||
destroy_processing_handle(cmd, handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _lvconvert_replace_pv(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
struct processing_handle *handle)
|
||||
{
|
||||
struct arg_value_group_list *group;
|
||||
struct dm_list *use_pvh;
|
||||
struct dm_list *replace_pvh;
|
||||
char **replace_pvs;
|
||||
const char *tmp_str;
|
||||
int replace_pv_count;
|
||||
int i;
|
||||
|
||||
/* First pos arg is required LV, remaining are optional PVs. */
|
||||
if (cmd->position_argc > 1) {
|
||||
if (!(use_pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc, cmd->position_argv, 0)))
|
||||
return_ECMD_FAILED;
|
||||
} else
|
||||
use_pvh = &lv->vg->pvs;
|
||||
|
||||
if (!(replace_pv_count = arg_count(cmd, replace_ARG)))
|
||||
return_ECMD_FAILED;
|
||||
|
||||
if (!(replace_pvs = dm_pool_alloc(cmd->mem, sizeof(char *) * replace_pv_count)))
|
||||
return_ECMD_FAILED;
|
||||
|
||||
i = 0;
|
||||
dm_list_iterate_items(group, &cmd->arg_value_groups) {
|
||||
if (!grouped_arg_is_set(group->arg_values, replace_ARG))
|
||||
continue;
|
||||
if (!(tmp_str = grouped_arg_str_value(group->arg_values, replace_ARG, NULL))) {
|
||||
log_error("Failed to get '--replace' argument");
|
||||
return_ECMD_FAILED;
|
||||
}
|
||||
if (!(replace_pvs[i++] = dm_pool_strdup(cmd->mem, tmp_str)))
|
||||
return_ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(replace_pvh = create_pv_list(cmd->mem, lv->vg, replace_pv_count, replace_pvs, 0)))
|
||||
return_ECMD_FAILED;
|
||||
|
||||
return lv_raid_replace(lv, replace_pvh, use_pvh);
|
||||
}
|
||||
|
||||
int lvconvert_replace_pv_fn(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
struct processing_handle *handle;
|
||||
struct lvconvert_result lr = { 0 };
|
||||
int ret;
|
||||
|
||||
if (!(handle = init_processing_handle(cmd, NULL))) {
|
||||
log_error("Failed to initialize processing handle.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
handle->custom_handle = &lr;
|
||||
|
||||
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL,
|
||||
READ_FOR_UPDATE, handle,
|
||||
&_lvconvert_replace_pv);
|
||||
|
||||
destroy_processing_handle(cmd, handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -85,6 +85,10 @@ struct command_name command_names[MAX_COMMAND_NAMES] = {
|
||||
static struct command commands[COMMAND_COUNT];
|
||||
static struct cmdline_context _cmdline;
|
||||
|
||||
|
||||
int lvconvert_replace_pv_fn(struct cmd_context *cmd, int argc, char **argv);
|
||||
int lvconvert_repair_pvs_or_thinpool_fn(struct cmd_context *cmd, int argc, char **argv);
|
||||
|
||||
/*
|
||||
* Table of command line functions
|
||||
*
|
||||
@ -93,19 +97,24 @@ static struct cmdline_context _cmdline;
|
||||
* For now, any command id not included here uses the old command fn.
|
||||
*/
|
||||
struct command_function command_functions[COMMAND_ID_COUNT] = {
|
||||
{ lvmconfig_general_CMD, lvmconfig },
|
||||
{ lvmconfig_general_CMD, lvmconfig },
|
||||
|
||||
/* lvconvert: utilities related to snapshots and repair */
|
||||
{ lvconvert_repair_pvs_or_thinpool_CMD, lvconvert_repair_pvs_or_thinpool_fn },
|
||||
{ lvconvert_replace_pv_CMD, lvconvert_replace_pv_fn },
|
||||
};
|
||||
|
||||
#if 0
|
||||
/* all raid-related type conversions */
|
||||
|
||||
{ lvconvert_raid_types_CMD, lvconvert_raid_types_fn },
|
||||
|
||||
/* raid-related utilities (move into lvconvert_raid_types?) */
|
||||
/* lvconvert: raid-related utilities (move into lvconvert_raid_types?) */
|
||||
|
||||
{ lvconvert_split_mirror_images_CMD, lvconvert_split_mirror_images_fn },
|
||||
{ lvconvert_change_mirrorlog_CMD, lvconvert_change_mirrorlog_fn },
|
||||
|
||||
/* utilities for creating/maintaining thin and cache objects. */
|
||||
/* lvconvert: utilities for creating/maintaining thin and cache objects. */
|
||||
|
||||
{ lvconvert_to_thin_with_external_CMD, lvconvert_to_thin_with_external_fn },
|
||||
{ lvconvert_to_cache_vol_CMD, lvconvert_to_cache_vol_fn },
|
||||
@ -115,12 +124,10 @@ struct command_function command_functions[COMMAND_ID_COUNT] = {
|
||||
{ lvconvert_split_and_delete_cachepool_CMD, lvconvert_split_and_delete_cachepool_fn },
|
||||
{ lvconvert_swap_pool_metadata_CMD, lvconvert_swap_pool_metadata_fn },
|
||||
|
||||
/* utilities related to snapshots and repair. */
|
||||
/* lvconvert: utilities related to snapshots and repair. */
|
||||
|
||||
{ lvconvert_merge_CMD, lvconvert_merge_fn },
|
||||
{ lvconvert_combine_split_snapshot_CMD, lvconvert_combine_split_snapshot_fn },
|
||||
{ lvconvert_repair_pvs_or_thinpool_CMD, lvconvert_repair_pvs_or_thinpool_fn },
|
||||
{ lvconvert_replace_pv_CMD, lvconvert_replace_pv_fn },
|
||||
{ lvconvert_split_cow_snapshot_CMD, lvconvert_split_cow_snapshot_fn },
|
||||
{ lvconvert_poll_start_CMD, lvconvert_poll_start_fn },
|
||||
|
||||
|
144
tools/toollib.c
144
tools/toollib.c
@ -2674,7 +2674,8 @@ out:
|
||||
*/
|
||||
static int _get_arg_lvnames(struct cmd_context *cmd,
|
||||
int argc, char **argv,
|
||||
const char *one_vgname, const char *one_lvname,
|
||||
const char *one_vgname,
|
||||
const char *one_lvname,
|
||||
struct dm_list *arg_vgnames,
|
||||
struct dm_list *arg_lvnames,
|
||||
struct dm_list *arg_tags)
|
||||
@ -2795,6 +2796,134 @@ static int _get_arg_lvnames(struct cmd_context *cmd,
|
||||
return ret_max;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some commands will look in specific options to:
|
||||
*
|
||||
* - find the intended LV name if only the VG name was found
|
||||
* in the position arg or env.
|
||||
*
|
||||
* command --foo=lvname VG
|
||||
* . add VG/lvname to arg_lvnames
|
||||
*
|
||||
* - find both the intended VG name and LV name if nothing
|
||||
* was found in the position arg or env.
|
||||
*
|
||||
* command --foo=vgname/lvname
|
||||
* . add vgname to arg_vgnames
|
||||
* . add vgname/lvname to arg_lvnames
|
||||
*
|
||||
* If a VG name was found in the position arg or from env,
|
||||
* and options are searched for an LV name, then if VG name
|
||||
* is repeated in the option name, verify it matches the VG
|
||||
* name found previously.
|
||||
*
|
||||
* command --foo=vgname/lvname VG
|
||||
* . verify vgname matches VG
|
||||
* . add vgname/lvname to arg_lvnames
|
||||
*
|
||||
*
|
||||
* In some cases, lvconvert wants to get the intended vg/lv
|
||||
* from --thinpool, --cachepool.
|
||||
*
|
||||
*
|
||||
* N.B.
|
||||
* lvconvert --snapshot is a special case where the first
|
||||
* positional arg is saved away and skipped, and the second
|
||||
* positional arg is the LV that is passed to process_each.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
static int _get_arg_lvnames_from_options(struct cmd_context *cmd,
|
||||
struct dm_list *arg_vgnames,
|
||||
struct dm_list *arg_lvnames)
|
||||
{
|
||||
struct str_list *sl;
|
||||
const char *arg_name = NULL;;
|
||||
const char *pos_vgname = NULL;
|
||||
const char *pos_lvname = NULL;
|
||||
const char *opt_lvname = NULL;
|
||||
const char *opt_vgname = NULL;
|
||||
const char *use_vgname = NULL;
|
||||
char *tmp_name;
|
||||
char *split;
|
||||
char *vglv;
|
||||
size_t vglv_sz;
|
||||
int i;
|
||||
|
||||
dm_list_iterate_items(sl, arg_vgnames) {
|
||||
pos_vgname = sl->str;
|
||||
break;
|
||||
}
|
||||
|
||||
dm_list_iterate_items(sl, arg_lvnames) {
|
||||
if ((pos_lvname = strchr(sl->str, '/')))
|
||||
pos_lvname++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (arg_is_set(cmd, thinpool_ARG))
|
||||
arg_name = arg_str_value(cmd, thinpool_ARG, NULL);
|
||||
else if (arg_is_set(cmd, cachepool_ARG))
|
||||
arg_name = arg_str_value(cmd, cachepool_ARG, NULL);
|
||||
|
||||
if (arg_name) {
|
||||
if ((split = strchr(arg_name, '/'))) {
|
||||
/* combined VG/LV */
|
||||
|
||||
if (!(tmp_name = dm_pool_strdup(cmd->mem, arg_name))) {
|
||||
log_error("string alloc failed.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(split = strchr(tmp_name, '/')))
|
||||
return ECMD_FAILED;
|
||||
|
||||
opt_vgname = tmp_name;
|
||||
opt_lvname = split + 1;
|
||||
*split = '\0';
|
||||
} else {
|
||||
/* only LV */
|
||||
opt_lvname = arg_name;
|
||||
}
|
||||
|
||||
if (pos_vgname && opt_vgname && strcmp(pos_vgname, opt_vgname)) {
|
||||
log_error("VG name mismatch from position arg (%s) and option arg (%s).",
|
||||
pos_vgname, opt_vgname);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!pos_vgname && opt_vgname) {
|
||||
if (!str_list_add(cmd->mem, arg_vgnames,
|
||||
dm_pool_strdup(cmd->mem, opt_vgname))) {
|
||||
log_error("strlist allocation failed.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
use_vgname = opt_vgname;
|
||||
} else {
|
||||
use_vgname = pos_vgname;
|
||||
}
|
||||
|
||||
if (use_vgname && !pos_lvname && opt_lvname) {
|
||||
vglv_sz = strlen(use_vgname) + strlen(opt_lvname) + 2;
|
||||
|
||||
if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) ||
|
||||
dm_snprintf(vglv, vglv_sz, "%s/%s", use_vgname, opt_lvname) < 0) {
|
||||
log_error("vg/lv string alloc failed.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!str_list_add(cmd->mem, arg_lvnames, vglv)) {
|
||||
log_error("strlist allocation failed.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t read_flags,
|
||||
struct dm_list *vgnameids_to_process,
|
||||
struct dm_list *arg_vgnames,
|
||||
@ -2957,6 +3086,19 @@ int process_each_lv(struct cmd_context *cmd,
|
||||
goto_out;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Some commands will search for VG/LV position args from option
|
||||
* values, e.g. lvconvert.
|
||||
*/
|
||||
if (cmd->command->flags & ALLOW_VGLV_ARG_FROM_OPTIONS) {
|
||||
if ((ret = _get_arg_lvnames_from_options(cmd, argc, argv, &arg_vgnames, &arg_lvnames) != ECMD_PROCESSED)) {
|
||||
ret_max = ret;
|
||||
goto_out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!handle && !(handle = init_processing_handle(cmd, NULL))) {
|
||||
ret_max = ECMD_FAILED;
|
||||
goto_out;
|
||||
|
Loading…
x
Reference in New Issue
Block a user