1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-29 13:44:18 +03:00

Compare commits

..

19 Commits

Author SHA1 Message Date
David Teigland
f126c7a55f lvconvert snapshot cleanup checks 2016-12-15 14:25:22 -06:00
David Teigland
4af953d13e lvconvert merge old snapshot missing lv_info check 2016-12-15 14:25:21 -06:00
David Teigland
50536dceb1 lvmlockd: test mode doesn't work
The --test option is not yet compatible with shared VGs
because changes are made in lvmlockd that cannot be
reversed or faked.
2016-12-15 14:25:21 -06:00
David Teigland
c6de4ce96b lvconvert: use command defs for raid/mirror types 2016-12-15 14:25:21 -06:00
David Teigland
29d69f58da lvconvert: move code
Should be no functional changes.

lvconvert.c
	type conversions for raid/mirror/linear/striped

lvconvert_pool.c
	thin/cache/pool creation and utilities

lvconvert_snapshot.c
	cow snapshot creation and utilties

lvconvert_other.c
	generic commands that are routed to a
	specific command in another file once
	the LV type is known.

lvconvert_poll.c
	polling utilities
2016-12-15 14:25:14 -06:00
David Teigland
340d8273e9 tests: use swapmetadata
and some other pool/cache/thin related changes
2016-12-15 14:18:30 -06:00
David Teigland
903be7a453 lvconvert: remove unused code
for merge, cache, thin, pool
2016-12-15 14:18:30 -06:00
David Teigland
6012699e2d lvconvert: use command defs for mergemirrors
and route the generic --merge to one of the
specific merge functions
2016-12-15 14:18:30 -06:00
David Teigland
0d6f6d331c toollib: find VG name in option values when needed 2016-12-15 14:18:30 -06:00
David Teigland
8f1fb60966 lvconvert: use command defs for thin/cache/pool creation
Everything related to thin and cache.
2016-12-15 14:18:25 -06:00
David Teigland
ceff1eef5c lvconvert: add startpoll command using command def
This is a new explicit version of 'lvconvert LV'
which has never been well defined or understood.
2016-12-14 11:30:24 -06:00
David Teigland
749e7cf81b lvconvert: add hidden lv access restrictions
This copies the previous logic which is probably
not correct.
2016-12-14 11:30:23 -06:00
David Teigland
efce1bc2d2 lvconvert: remove unused calls for snapshots
snapshot commands are no longer called from the
monolithic lvconvert code, so remove the unused code.
2016-12-14 11:30:23 -06:00
David Teigland
3f0eded331 lvconvert: snapshot: use command definitions
Lift all the snapshot utilities (merge, split, combine)
out of the monolithic lvconvert implementation, using
the command definitions.  The old code associated with
these commands is now unused and will be removed separately.
2016-12-14 11:30:23 -06:00
David Teigland
94d0bc7304 lvconvert: remove unused calls for repair and replace
repair and replace are no longer called from the
monolithic lvconvert code, so remove the unused code.
2016-12-14 11:30:23 -06:00
David Teigland
0ccc467608 lvconvert: repair and replace: use command definitions
This lifts the lvconvert --repair and --replace commands
out of the monolithic lvconvert implementation.  The
previous calls into repair/replace can no longer be
reached and will be removed in a separate commit.
2016-12-14 11:30:23 -06:00
David Teigland
ba5ae30bb7 lvchange: make use of command definitions
Reorganize the lvchange code to take advantage of
the command definition, and remove the validation
that is done by the command definintion rules.
2016-12-14 11:30:23 -06:00
David Teigland
b9b60a73ae process_each_lv: add check_single_lv function
The new check_single_lv() function is called prior to the
existing process_single_lv().  If the check function returns 0,
the LV will not be processed.

The check_single_lv function is meant to be a standard method
to validate the combination of specific command + specific LV,
and decide if the combination is allowed.  The check_single
function can be used by anything that calls process_each_lv.

As commands are migrated to take advantage of command
definitions, each command definition gets its own entry
point which calls process_each for itself, passing a
pair of check_single/process_single functions which can
be specific to the narrowly defined command def.
2016-12-14 11:30:19 -06:00
David Teigland
c677e0e70b commands: new method for defining commands
. Define a prototype for every lvm command.
. Match every user command with one definition.
. Generate help text and man pages from them.

The new file command-lines.in defines a prototype for every
unique lvm command.  A unique lvm command is a unique
combination of: command name + required option args +
required positional args.  Each of these prototypes also
includes the optional option args and optional positional
args that the command will accept, a description, and a
unique string ID for the definition.  Any valid command
will match one of the prototypes.

Here's an example of the lvresize command definitions from
command-lines.in, there are three unique lvresize commands:

lvresize --size SizeMB LV
OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync, --reportformat String, --resizefs,
--stripes Number, --stripesize SizeKB, --poolmetadatasize SizeMB
OP: PV ...
ID: lvresize_by_size
DESC: Resize an LV by a specified size.

lvresize LV PV ...
OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync,
--reportformat String, --resizefs, --stripes Number, --stripesize SizeKB
ID: lvresize_by_pv
DESC: Resize an LV by specified PV extents.
FLAGS: SECONDARY_SYNTAX

lvresize --poolmetadatasize SizeMB LV_thinpool
OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync,
--reportformat String, --stripes Number, --stripesize SizeKB
OP: PV ...
ID: lvresize_pool_metadata_by_size
DESC: Resize a pool metadata SubLV by a specified size.

The three commands have separate definitions because they have
different required parameters.  Required parameters are specified
on the first line of the definition.  Optional options are
listed after OO, and optional positional args are listed after OP.

This data is used to generate corresponding command definition
structures for lvm in command-lines.h.  usage/help output is also
auto generated, so it is always in sync with the definitions.

Example of the corresponding generated structure in
command-lines.h for the first lvresize prototype
(these structures are never edited directly):

commands[83].name = "lvresize";
commands[83].command_line_id = "lvresize_by_size";
commands[83].command_line_enum = lvresize_by_size_CMD;
commands[83].fn = lvresize;
commands[83].ro_count = 1;
commands[83].rp_count = 1;
commands[83].oo_count = 22;
commands[83].op_count = 1;
commands[83].cmd_flags = 0;
commands[83].desc = "DESC: Resize an LV by a specified size.";
commands[83].usage = "lvresize --size Number[m|unit] LV"
" [ --resizefs, --poolmetadatasize Number[m|unit], COMMON_OPTIONS ]"
" [ PV ... ]";
commands[83].usage_common =
" [ --alloc contiguous|cling|cling_by_tags|normal|anywhere|inherit, --nosync, --reportformat String, --autobackup y|n, --stripes Number, --stripesize Number[k|unit], --nofsck, --commandprofile String, --config String, --debug, --driverloaded y|n, --help, --profile String, --quiet, --verbose, --version, --yes, --test, --force, --noudevsync ]";
commands[83].required_opt_args[0].opt = size_ARG;
commands[83].required_opt_args[0].def.val_bits = val_enum_to_bit(sizemb_VAL);
commands[83].required_pos_args[0].pos = 1;
commands[83].required_pos_args[0].def.val_bits = val_enum_to_bit(lv_VAL);
commands[83].optional_opt_args[0].opt = commandprofile_ARG;
commands[83].optional_opt_args[0].def.val_bits = val_enum_to_bit(string_VAL);
commands[83].optional_opt_args[1].opt = config_ARG;
commands[83].optional_opt_args[1].def.val_bits = val_enum_to_bit(string_VAL);
commands[83].optional_opt_args[2].opt = debug_ARG;
commands[83].optional_opt_args[3].opt = driverloaded_ARG;
commands[83].optional_opt_args[3].def.val_bits = val_enum_to_bit(bool_VAL);
commands[83].optional_opt_args[4].opt = help_ARG;
commands[83].optional_opt_args[5].opt = profile_ARG;
commands[83].optional_opt_args[5].def.val_bits = val_enum_to_bit(string_VAL);
commands[83].optional_opt_args[6].opt = quiet_ARG;
commands[83].optional_opt_args[7].opt = verbose_ARG;
commands[83].optional_opt_args[8].opt = version_ARG;
commands[83].optional_opt_args[9].opt = yes_ARG;
commands[83].optional_opt_args[10].opt = test_ARG;
commands[83].optional_opt_args[11].opt = alloc_ARG;
commands[83].optional_opt_args[11].def.val_bits = val_enum_to_bit(alloc_VAL);
commands[83].optional_opt_args[12].opt = autobackup_ARG;
commands[83].optional_opt_args[12].def.val_bits = val_enum_to_bit(bool_VAL);
commands[83].optional_opt_args[13].opt = force_ARG;
commands[83].optional_opt_args[14].opt = nofsck_ARG;
commands[83].optional_opt_args[15].opt = nosync_ARG;
commands[83].optional_opt_args[16].opt = noudevsync_ARG;
commands[83].optional_opt_args[17].opt = reportformat_ARG;
commands[83].optional_opt_args[17].def.val_bits = val_enum_to_bit(string_VAL);
commands[83].optional_opt_args[18].opt = resizefs_ARG;
commands[83].optional_opt_args[19].opt = stripes_ARG;
commands[83].optional_opt_args[19].def.val_bits = val_enum_to_bit(number_VAL);
commands[83].optional_opt_args[20].opt = stripesize_ARG;
commands[83].optional_opt_args[20].def.val_bits = val_enum_to_bit(sizekb_VAL);
commands[83].optional_opt_args[21].opt = poolmetadatasize_ARG;
commands[83].optional_opt_args[21].def.val_bits = val_enum_to_bit(sizemb_VAL);
commands[83].optional_pos_args[0].pos = 2;
commands[83].optional_pos_args[0].def.val_bits = val_enum_to_bit(pv_VAL);
commands[83].optional_pos_args[0].def.flags = ARG_DEF_FLAG_MAY_REPEAT;

Every user-entered command is compared against the set of
command structures, and matched with one.  An error is
reported if an entered command does not have the required
parameters for any definition.  The closest match is printed
as a suggestion, and running lvresize --help will display
the usage for each possible lvresize command.

The prototype syntax used for help/man output includes
required --option and positional args on the first line,
and optional --option and positional args enclosed in [ ]
on subsequent lines.

  command_name <required_opt_args> <required_pos_args>
          [ <optional_opt_args> ]
          [ <optional_pos_args> ]

$ lvresize --help
  lvresize - Resize a logical volume

  Resize an LV by a specified size.
  lvresize --size Number[m|unit] LV
        [ --resizefs,
          --poolmetadatasize Number[m|unit],
          COMMON_OPTIONS ]
        [ PV ... ]

  Resize a pool metadata SubLV by a specified size.
  lvresize --poolmetadatasize Number[m|unit] LV_thinpool
        [ COMMON_OPTIONS ]
        [ PV ... ]

  Common options:
        [ --alloc contiguous|cling|cling_by_tags|normal|anywhere|inherit,
          --nosync,
          --reportformat String,
          --autobackup y|n,
          --stripes Number,
          --stripesize Number[k|unit],
          --nofsck,
          --commandprofile String,
          --config String,
          --debug,
          --driverloaded y|n,
          --help,
          --profile String,
          --quiet,
          --verbose,
          --version,
          --yes,
          --test,
          --force,
          --noudevsync ]

  (Use --help --help for usage notes.)

$ lvresize --poolmetadatasize 4
  Failed to find a matching command definition.
  Closest command usage is:
  lvresize --poolmetadatasize Number[m|unit] LV_thinpool

Command definitions that are not to be advertised/suggested
have the flag SECONDARY_SYNTAX.  These commands will not be
printed in the normal help output.

Man page prototypes are also generated from the same original
command definitions, and are always in sync with the code
and help text.

Very early in command execution, a matching command definition
is found.  lvm then knows the operation being done, and that
the provided args conform to the definition.  This will allow
lots of ad hoc checking/validation to be removed throughout
the code.

Each command definition can also be routed to a specific
function to implement it.  The function is associated with
an enum value for the command definition (generated from
the ID string.)  These per-command-definition implementation
functions have not yet been created, so all commands
currently fall back to the existing per-command-name
implementation functions.

Using per-command-definition functions will allow lots of
code to be removed which tries to figure out what the
command is meant to do.  This is currently based on ad hoc
and complicated option analysis.  When using the new
functions, what the command is doing is already known
from the associated command definition.

So, this first phase validates every user-entered command
against the set of command prototypes, then calls the existing
implementation.  The second phase can associate an implementation
function with each definition, and take further advantage of the
known operation to avoid the complicated option analysis.
2016-12-14 11:25:12 -06:00
8 changed files with 391 additions and 405 deletions

View File

@@ -5635,6 +5635,11 @@ static int _access_vg_lock_type(struct cmd_context *cmd, struct volume_group *vg
}
}
if (test_mode()) {
log_error("Test mode is not yet supported with lock type %s.", vg->lock_type);
return 0;
}
return 1;
}

View File

@@ -337,24 +337,28 @@ OO: OO_LVCONVERT_RAID, OO_LVCONVERT
OP: PV ...
ID: lvconvert_raid_types
DESC: Convert LV to striped.
RULE: all not lv_is_locked lv_is_pvmove
lvconvert --type mirror LV
OO: OO_LVCONVERT_RAID, OO_LVCONVERT, --mirrorlog MirrorLog
OP: PV ...
ID: lvconvert_raid_types
DESC: Convert LV to type mirror (also see type raid1).
RULE: all not lv_is_locked lv_is_pvmove
lvconvert --type raid LV
OO: OO_LVCONVERT_RAID, OO_LVCONVERT
OP: PV ...
ID: lvconvert_raid_types
DESC: Convert LV to raid.
RULE: all not lv_is_locked lv_is_pvmove
lvconvert --mirrors SNumber LV
OO: OO_LVCONVERT_RAID, OO_LVCONVERT, --mirrorlog MirrorLog
OP: PV ...
ID: lvconvert_raid_types
DESC: Convert LV to raid1 or mirror, or change number of mirror images.
RULE: all not lv_is_locked lv_is_pvmove
---
@@ -366,12 +370,14 @@ OO: OO_LVCONVERT
OP: PV ...
ID: lvconvert_split_mirror_images
DESC: Split images from a raid1 or mirror LV and use them to create a new LV.
RULE: all not lv_is_locked lv_is_pvmove
lvconvert --splitmirrors Number --trackchanges LV_raid1_cache
OO: OO_LVCONVERT
OP: PV ...
ID: lvconvert_split_mirror_images
DESC: Split images from a raid1 LV and track changes to origin.
RULE: all not lv_is_locked lv_is_pvmove
lvconvert --mergemirrors LV_linear_raid|VG|Tag ...
OO: OO_LVCONVERT
@@ -384,6 +390,7 @@ OO: OO_LVCONVERT
OP: PV ...
ID: lvconvert_change_mirrorlog
DESC: Change the type of mirror log used by a mirror LV.
RULE: all not lv_is_locked lv_is_pvmove
---
@@ -518,6 +525,7 @@ OO: --background, --interval Number, OO_LVCONVERT
ID: lvconvert_merge_snapshot
DESC: Merge COW snapshot LV into its origin.
RULE: all not lv_is_locked lv_is_pvmove lv_is_merging_origin lv_is_virtual_origin lv_is_external_origin lv_is_merging_cow
RULE: all and lv_is_visible
---
@@ -545,6 +553,7 @@ DESC: Combine a former COW snapshot (second arg) with a former
DESC: origin LV (first arg) to reverse a splitsnapshot command.
FLAGS: SECONDARY_SYNTAX
RULE: all not lv_is_locked lv_is_pvmove
RULE: all and lv_is_visible
lvconvert --snapshot LV LV_linear
OO: --type snapshot, --chunksize SizeKB, --zero Bool, OO_LVCONVERT
@@ -552,6 +561,7 @@ ID: lvconvert_combine_split_snapshot
DESC: Combine a former COW snapshot (second arg) with a former
DESC: origin LV (first arg) to reverse a splitsnapshot command.
RULE: all not lv_is_locked lv_is_pvmove
RULE: all and lv_is_visible
---
@@ -878,6 +888,7 @@ OO: OO_LVCONVERT
ID: lvconvert_merge_thin
DESC: Merge thin LV into its origin LV.
RULE: all not lv_is_locked lv_is_pvmove lv_is_merging_origin lv_is_virtual_origin lv_is_external_origin lv_is_merging_cow
RULE: all and lv_is_visible
---

View File

@@ -24,18 +24,18 @@ typedef enum {
* For a mirrored or raid LV, split mirror into two mirrors, optionally tracking
* future changes to the main mirror to allow future recombination.
*/
CONV_SPLIT = 2,
CONV_SPLIT_MIRRORS = 5,
CONV_SPLIT = 1,
CONV_SPLIT_MIRRORS = 2,
/* Every other segment type or mirror log conversion we haven't separated out */
CONV_OTHER = 12,
CONV_OTHER = 3,
} conversion_type_t;
struct lvconvert_params {
/* Exactly one of these 12 command categories is determined */
int split; /* 2 */
int keep_mimages; /* 5 */ /* --splitmirrors */
/* other */ /* 12 */
/* Exactly one of these command categories is determined */
int split; /* 1 */
int keep_mimages; /* 2 */ /* --splitmirrors */
/* other */ /* 3 */
/* FIXME Eliminate all cases where more than one of the above are set then use conv_type instead */
conversion_type_t conv_type;
@@ -55,12 +55,7 @@ struct lvconvert_params {
int yes;
int zero;
const char *lv_name;
const char *lv_split_name;
const char *lv_name_full;
const char *vg_name;
int wait_completion;
int need_polling;
uint32_t region_size;
@@ -77,13 +72,12 @@ struct lvconvert_params {
alloc_policy_t alloc;
int pv_count;
char **pvs;
struct dm_list *pvh;
int wait_completion;
int need_polling;
struct logical_volume *lv_to_poll;
struct dm_list idls;
const char *origin_name;
};
@@ -96,73 +90,6 @@ static void _set_conv_type(struct lvconvert_params *lp, int conv_type)
lp->conv_type = conv_type;
}
static int _lvconvert_name_params(struct lvconvert_params *lp,
struct cmd_context *cmd,
int *pargc, char ***pargv)
{
if (!*pargc) {
if (lp->split) {
log_error("Logical volume for split is missing.");
return 0;
}
if (!lp->lv_name_full) {
log_error("Please provide logical volume path.");
return 0;
}
} else if (!lp->lv_name_full) {
lp->lv_name_full = (*pargv)[0];
(*pargv)++, (*pargc)--;
}
if (!validate_restricted_lvname_param(cmd, &lp->vg_name, &lp->origin_name))
return_0;
if (!validate_restricted_lvname_param(cmd, &lp->vg_name, &lp->lv_split_name))
return_0;
if (!lp->vg_name && !strchr(lp->lv_name_full, '/')) {
/* Check for $LVM_VG_NAME */
if (!(lp->vg_name = extract_vgname(cmd, NULL))) {
log_error("Please specify a logical volume path.");
return 0;
}
}
if (!validate_lvname_param(cmd, &lp->vg_name, &lp->lv_name_full))
return_0;
lp->lv_name = lp->lv_name_full;
if (!validate_name(lp->vg_name)) {
log_error("Please provide a valid volume group name");
return 0;
}
/*
* FIXME: avoid this distinct validation out of scope of _convert_*()
*
* We should not rely on namespace here any more!
* It is the duty of lvcreate/lvrename to avoid reserved names.
*/
if (!lp->keep_mimages &&
!strstr(lp->lv_name, "_tdata") &&
!strstr(lp->lv_name, "_tmeta") &&
!strstr(lp->lv_name, "_cdata") &&
!strstr(lp->lv_name, "_cmeta") &&
!strstr(lp->lv_name, "_corig") &&
!apply_lvname_restrictions(lp->lv_name))
return_0;
if (*pargc) {
if (lp->split) {
log_error("Too many arguments provided with --split.");
return 0;
}
}
return 1;
}
static int _raid0_type_requested(const char *type_str)
{
return (!strcmp(type_str, SEG_TYPE_NAME_RAID0) || !strcmp(type_str, SEG_TYPE_NAME_RAID0_META));
@@ -207,9 +134,9 @@ static int _read_conversion_type(struct cmd_context *cmd,
return 0;
}
static int _read_params(struct cmd_context *cmd, int argc, char **argv,
struct lvconvert_params *lp)
static int _read_params(struct cmd_context *cmd, struct lvconvert_params *lp)
{
const char *vg_name = NULL;
int region_size;
int pagesize = lvm_getpagesize();
@@ -245,7 +172,11 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
lp->track_changes = 1;
if (lp->split) {
lp->lv_split_name = arg_str_value(cmd, name_ARG, NULL);
if ((lp->lv_split_name = arg_str_value(cmd, name_ARG, NULL))) {
if (!validate_restricted_lvname_param(cmd, &vg_name, &lp->lv_split_name))
return_0;
}
/*
* The '--splitmirrors n' argument is equivalent to '--mirrors -n'
@@ -265,7 +196,11 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
return 0;
}
lp->lv_split_name = arg_str_value(cmd, name_ARG, NULL);
if ((lp->lv_split_name = arg_str_value(cmd, name_ARG, NULL))) {
if (!validate_restricted_lvname_param(cmd, &vg_name, &lp->lv_split_name))
return_0;
}
lp->keep_mimages = 1;
_set_conv_type(lp, CONV_SPLIT_MIRRORS);
lp->mirrors = arg_uint_value(cmd, splitmirrors_ARG, 0);
@@ -391,12 +326,6 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
lp->force = arg_count(cmd, force_ARG);
lp->yes = arg_count(cmd, yes_ARG);
if (!_lvconvert_name_params(lp, cmd, &argc, &argv))
return_0;
lp->pv_count = argc;
lp->pvs = argv;
return 1;
}
@@ -674,22 +603,6 @@ static int _lvconvert_mirrors_parse_params(struct cmd_context *cmd,
return 0;
}
/*
* Collapsing a stack of mirrors:
*
* If called with no argument, try collapsing the resync layers
*/
if (!lp->mirrors_supplied && !lp->mirrorlog &&
!lp->corelog && !arg_is_set(cmd, regionsize_ARG) &&
!lp->keep_mimages) {
*new_mimage_count = *old_mimage_count;
*new_log_count = *old_log_count;
if (find_temporary_mirror(lv) || lv_is_converting(lv))
lp->need_polling = 1;
return 1;
}
/*
* Adjusting mimage count?
*/
@@ -1403,128 +1316,6 @@ try_new_takeover_or_reshape:
return 0;
}
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 what the old code expects in lp
* for repair; it doesn't take the stripes option, but it seems to
* expect lp.stripes to be set to 1.
*/
lp.alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, ALLOC_INHERIT);
lp.stripes = 1;
ret = _lvconvert_mirrors_repair(cmd, lv, &lp, use_pvh);
if (lp.need_polling) {
if (!lv_info(cmd, lv, 0, &info, 0, 0) || !info.exists)
log_print_unless_silent("Conversion starts after activation.");
else {
if (!(idl = convert_poll_id_list_create(cmd, lv)))
return 0;
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;
}
}
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, arg_count(cmd, force_ARG), 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;
}
/*
* Functions called to perform a specific operation on a specific LV type.
*
* _convert_<lvtype>_<operation>
*
* For cases where an operation does not apply to the LV itself, but
* is implicitly redirected to a sub-LV, these functions locate the
* correct sub-LV and call the operation on that sub-LV. If a sub-LV
* of the proper type is not found, these functions report the error.
*
* FIXME: the _lvconvert_foo() functions can be cleaned up since they
* are now only called for valid combinations of LV type and operation.
* After that happens, the code remaining in those functions can be
* moved into the _convert_lvtype_operation() functions below.
*/
/*
* Change the number of images in a mirror LV.
* lvconvert --mirrors Number LV
@@ -1704,51 +1495,21 @@ static int _convert_mirror(struct cmd_context *cmd, struct logical_volume *lv,
if (segtype_is_raid(lp->segtype))
return _convert_mirror_raid(cmd, lv, lp);
log_error("Operation not permitted on mirror LV %s.", display_lvname(lv));
log_error("Operations permitted on a mirror LV are:\n"
" --mirrors\n"
" --splitmirrors\n"
" --mirrorlog\n"
" --type linear\n"
" --type raid*\n");
log_error("Unknown operation on mirror LV %s.", display_lvname(lv));
return 0;
}
static int _convert_raid(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
/* Permitted convert options on visible or hidden RaidLVs */
const char *permitted_options = lv_is_visible(lv) ?
" --mirrors\n"
" --splitmirrors\n"
" --type raid*\n"
" --type mirror\n"
" --type striped\n"
" --type linear\n"
:
" --mirrors\n"
" --splitmirrors\n"
" --replace\n"
" --type raid*\n"
" --type mirror\n"
" --type striped\n"
" --type linear\n";
/* Applicable to any hidden _or_ visible LVs. */
if (arg_is_set(cmd, mirrors_ARG))
return _convert_raid_number(cmd, lv, lp);
if (arg_is_set(cmd, splitmirrors_ARG))
return _convert_raid_splitmirrors(cmd, lv, lp);
if (segtype_is_raid(lp->segtype)) {
/* Only --type allowed on hidden RaidLV. */
if (!lv_is_visible(lv) && !arg_is_set(cmd, type_ARG))
goto out;
if (segtype_is_raid(lp->segtype))
return _convert_raid_raid(cmd, lv, lp);
}
if (segtype_is_mirror(lp->segtype))
return _convert_raid_mirror(cmd, lv, lp);
@@ -1759,10 +1520,7 @@ static int _convert_raid(struct cmd_context *cmd, struct logical_volume *lv,
if (_linear_type_requested(lp->type_str))
return _convert_raid_linear(cmd, lv, lp);
out:
log_error("Operation not permitted on raid LV %s.", display_lvname(lv));
log_error("Operations permitted on a raid LV are:\n%s", permitted_options);
log_error("Unknown operation on raid LV %s.", display_lvname(lv));
return 0;
}
@@ -1785,11 +1543,7 @@ static int _convert_striped(struct cmd_context *cmd, struct logical_volume *lv,
if (arg_is_set(cmd, mirrors_ARG) && mirrors_type && !strcmp(mirrors_type, SEG_TYPE_NAME_RAID1))
return _convert_striped_raid(cmd, lv, lp);
log_error("Operation not permitted on striped or linear LV %s.", display_lvname(lv));
log_error("Operations permitted on a striped or linear LV are:\n"
" --type mirror\n"
" --type raid*\n");
log_error("Unknown operation on striped or linear LV %s.", display_lvname(lv));
return 0;
}
@@ -1818,39 +1572,6 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
struct lv_segment *seg = first_seg(lv);
int ret = 0;
/*
* Check some conditions that can never be processed.
*/
if (lv_is_locked(lv)) {
log_error("Cannot convert locked LV %s.", display_lvname(lv));
goto out;
}
if (lv_is_pvmove(lv)) {
log_error("Cannot convert pvmove LV %s.", display_lvname(lv));
goto out;
}
if (!lv_is_visible(lv)) {
/*
* FIXME: there are some exceptions to the rule of only
* operating on visible LVs. These should be fixed by running
* the command on the visible LV with an option indicating
* which sub LV is intended rather than naming the !visible LV.
*/
if (!lv_is_cache_pool_metadata(lv) &&
!lv_is_cache_pool_data(lv) &&
!lv_is_thin_pool_metadata(lv) &&
!lv_is_thin_pool_data(lv) &&
!lv_is_used_cache_pool(lv) &&
!lv_is_mirrored(lv) &&
!lv_is_raid(lv)) {
log_error("Cannot convert internal LV %s.", display_lvname(lv));
goto out;
}
}
/* Set up segtype either from type_str or else to match the existing one. */
if (!*lp->type_str)
lp->segtype = seg->segtype;
@@ -1925,18 +1646,38 @@ out:
return ret ? ECMD_PROCESSED : ECMD_FAILED;
}
static int _lvconvert_and_add_to_poll_list(struct cmd_context *cmd,
struct lvconvert_params *lp,
struct logical_volume *lv)
{
int ret;
struct lvinfo info;
struct convert_poll_id_list *idl;
/*
* Change LV between raid/mirror/linear/striped
*/
/* _lvconvert() call may alter the reference in lp->lv_to_poll */
if ((ret = _lvconvert(cmd, lv, lp)) != ECMD_PROCESSED)
stack;
else if (lp->need_polling) {
static int _lvconvert_raid_types_single(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle)
{
struct lvconvert_params *lp = (struct lvconvert_params *) handle->custom_handle;
struct dm_list *use_pvh;
struct convert_poll_id_list *idl;
struct lvinfo info;
int ret;
if (cmd->position_argc > 1) {
/* First pos arg is required LV, remaining are optional PVs. */
if (!(use_pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0)))
return_ECMD_FAILED;
lp->pv_count = cmd->position_argc - 1;
} else
use_pvh = &lv->vg->pvs;
lp->pvh = use_pvh;
lp->lv_to_poll = lv;
ret = _lvconvert(cmd, lv, lp);
if (ret != ECMD_PROCESSED)
return_ECMD_FAILED;
if (lp->need_polling) {
/* _lvconvert() call may alter the reference in lp->lv_to_poll */
if (!lv_info(cmd, lp->lv_to_poll, 0, &info, 0, 0) || !info.exists)
log_print_unless_silent("Conversion starts after activation.");
else {
@@ -1946,65 +1687,82 @@ static int _lvconvert_and_add_to_poll_list(struct cmd_context *cmd,
}
}
return ret;
return ECMD_PROCESSED;
}
static int _lvconvert_single(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle)
static int _lvconvert_raid_types_check(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle,
int lv_is_named_arg)
{
struct lvconvert_params *lp = (struct lvconvert_params *) handle->custom_handle;
struct volume_group *vg = lv->vg;
int lvt_enum = get_lvt_enum(lv);
struct lv_types *lvtype = get_lv_type(lvt_enum);
if (test_mode() && is_lockd_type(vg->lock_type)) {
log_error("Test mode is not yet supported with lock type %s.",
vg->lock_type);
return ECMD_FAILED;
if (!lv_is_visible(lv)) {
if (!lv_is_cache_pool_metadata(lv) &&
!lv_is_cache_pool_data(lv) &&
!lv_is_thin_pool_metadata(lv) &&
!lv_is_thin_pool_data(lv) &&
!lv_is_used_cache_pool(lv) &&
!lv_is_mirrored(lv) &&
!lv_is_raid(lv))
goto fail_hidden;
}
/*
* lp->pvh holds the list of PVs available for allocation or removal
* FIXME: this validation could be done by command defs.
*
* Outside the standard linear/striped/mirror/raid LV
* types, cache is the only special LV type that is handled
* (the command is redirected to origin).
*/
if (lp->pv_count) {
if (!(lp->pvh = create_pv_list(cmd->mem, vg, lp->pv_count, lp->pvs, 0)))
return_ECMD_FAILED;
} else
lp->pvh = &vg->pvs;
switch (lvt_enum) {
case thin_LVT:
case thinpool_LVT:
case cachepool_LVT:
case snapshot_LVT:
log_error("Operation not permitted (%s %d) on LV %s type %s.",
cmd->command->command_line_id, cmd->command->command_line_enum,
display_lvname(lv), lvtype ? lvtype->name : "unknown");
return 0;
}
lp->lv_to_poll = lv;
return 1;
return _lvconvert_and_add_to_poll_list(cmd, lp, lv);
fail_hidden:
log_error("Operation not permitted (%s %d) on hidden LV %s.",
cmd->command->command_line_id, cmd->command->command_line_enum,
display_lvname(lv));
return 0;
}
int lvconvert(struct cmd_context * cmd, int argc, char **argv)
int lvconvert_raid_types_cmd(struct cmd_context * cmd, int argc, char **argv)
{
int poll_ret, ret;
int saved_ignore_suspended_devices;
struct processing_handle *handle;
struct convert_poll_id_list *idl;
struct lvconvert_params lp = {
.conv_type = CONV_OTHER,
.target_attr = ~0,
.idls = DM_LIST_HEAD_INIT(lp.idls),
};
struct processing_handle *handle = init_processing_handle(cmd, NULL);
cmd->command->flags &= ~GET_VGNAME_FROM_OPTIONS;
if (!handle) {
if (!(handle = init_processing_handle(cmd, NULL))) {
log_error("Failed to initialize processing handle.");
return ECMD_FAILED;
}
handle->custom_handle = &lp;
if (!_read_params(cmd, argc, argv, &lp)) {
if (!_read_params(cmd, &lp)) {
ret = EINVALID_CMD_LINE;
goto_out;
}
saved_ignore_suspended_devices = ignore_suspended_devices();
ret = process_each_lv(cmd, 0, NULL, lp.vg_name, lp.lv_name, READ_FOR_UPDATE,
handle, NULL, &_lvconvert_single);
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
handle, &_lvconvert_raid_types_check, &_lvconvert_raid_types_single);
init_ignore_suspended_devices(saved_ignore_suspended_devices);
@@ -2023,6 +1781,140 @@ out:
return ret;
}
/*
* change mirror log
*/
static int _lvconvert_visible_check(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle,
int lv_is_named_arg)
{
if (!lv_is_visible(lv)) {
log_error("Operation not permitted (%s %d) on hidden LV %s.",
cmd->command->command_line_id, cmd->command->command_line_enum,
display_lvname(lv));
return 0;
}
return 1;
}
static int _lvconvert_change_mirrorlog_single(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle)
{
struct lvconvert_params *lp = (struct lvconvert_params *) handle->custom_handle;
struct dm_list *use_pvh;
if (cmd->position_argc > 1) {
/* First pos arg is required LV, remaining are optional PVs. */
if (!(use_pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0)))
return_ECMD_FAILED;
lp->pv_count = cmd->position_argc - 1;
} else
use_pvh = &lv->vg->pvs;
lp->pvh = use_pvh;
/* FIXME: extract the mirrorlog functionality out of _lvconvert()? */
return _lvconvert(cmd, lv, lp);
}
int lvconvert_change_mirrorlog_cmd(struct cmd_context * cmd, int argc, char **argv)
{
struct processing_handle *handle;
struct lvconvert_params lp = {
.conv_type = CONV_OTHER,
.target_attr = ~0,
.idls = DM_LIST_HEAD_INIT(lp.idls),
};
int ret;
if (!(handle = init_processing_handle(cmd, NULL))) {
log_error("Failed to initialize processing handle.");
return ECMD_FAILED;
}
handle->custom_handle = &lp;
/* FIXME: extract the relevant bits of read_params and put here. */
if (!_read_params(cmd, &lp)) {
ret = EINVALID_CMD_LINE;
goto_out;
}
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
handle, &_lvconvert_visible_check, &_lvconvert_change_mirrorlog_single);
out:
destroy_processing_handle(cmd, handle);
return ret;
}
/*
* split mirror images
*/
static int _lvconvert_split_mirror_images_single(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle)
{
struct lvconvert_params *lp = (struct lvconvert_params *) handle->custom_handle;
struct dm_list *use_pvh;
if (cmd->position_argc > 1) {
/* First pos arg is required LV, remaining are optional PVs. */
if (!(use_pvh = create_pv_list(cmd->mem, lv->vg, cmd->position_argc - 1, cmd->position_argv + 1, 0)))
return_ECMD_FAILED;
lp->pv_count = cmd->position_argc - 1;
} else
use_pvh = &lv->vg->pvs;
lp->pvh = use_pvh;
/* FIXME: extract the split functionality out of _lvconvert()? */
return _lvconvert(cmd, lv, lp);
}
int lvconvert_split_mirror_images_cmd(struct cmd_context * cmd, int argc, char **argv)
{
struct processing_handle *handle;
struct lvconvert_params lp = {
.conv_type = CONV_OTHER,
.target_attr = ~0,
.idls = DM_LIST_HEAD_INIT(lp.idls),
};
int ret;
if (!(handle = init_processing_handle(cmd, NULL))) {
log_error("Failed to initialize processing handle.");
return ECMD_FAILED;
}
handle->custom_handle = &lp;
/* FIXME: extract the relevant bits of read_params and put here. */
if (!_read_params(cmd, &lp)) {
ret = EINVALID_CMD_LINE;
goto_out;
}
/* FIXME: are there any hidden LVs that should be disallowed? */
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
handle, NULL, &_lvconvert_split_mirror_images_single);
out:
destroy_processing_handle(cmd, handle);
return ret;
}
/*
* merge mirror images
*
* Called from both lvconvert --mergemirrors and lvconvert --merge.
*/
int lvconvert_merge_mirror_images_single(struct cmd_context *cmd,
struct logical_volume *lv,
struct processing_handle *handle)
@@ -2035,9 +1927,133 @@ int lvconvert_merge_mirror_images_single(struct cmd_context *cmd,
int lvconvert_merge_mirror_images_cmd(struct cmd_context *cmd, int argc, char **argv)
{
/* arg can be a VG name, which is the standard option usage */
cmd->command->flags &= ~GET_VGNAME_FROM_OPTIONS;
return process_each_lv(cmd, cmd->position_argc, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
NULL, NULL, &lvconvert_merge_mirror_images_single);
NULL, &_lvconvert_visible_check, &lvconvert_merge_mirror_images_single);
}
/*
* repair/replace code, is called from lvconvert --repair/--replace
* utilities in lvconvert_other.c
*/
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 what the old code expects in lp
* for repair; it doesn't take the stripes option, but it seems to
* expect lp.stripes to be set to 1.
*/
lp.alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, ALLOC_INHERIT);
lp.stripes = 1;
ret = _lvconvert_mirrors_repair(cmd, lv, &lp, use_pvh);
if (lp.need_polling) {
if (!lv_info(cmd, lv, 0, &info, 0, 0) || !info.exists)
log_print_unless_silent("Conversion starts after activation.");
else {
if (!(idl = convert_poll_id_list_create(cmd, lv)))
return 0;
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;
}
}
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, arg_count(cmd, force_ARG), 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;
}
/*
* All lvconvert command defs have their own function,
* so the generic function name is unused.
*/
int lvconvert(struct cmd_context *cmd, int argc, char **argv)
{
log_error(INTERNAL_ERROR "Missing function for command definition %s.",
cmd->command->command_line_id);
return ECMD_FAILED;
}

View File

@@ -19,36 +19,6 @@
#include "lvconvert_poll.h"
#include "command-lines-count.h"
/*
* FIXME: it's very unlikely that the same !visible exceptions apply to every
* lvconvert command. Add specific !visible exceptions in command-specific
* check functions.
*/
int lvconvert_generic_check(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle,
int lv_is_named_arg)
{
if (!lv_is_visible(lv)) {
if (lv_is_cache_pool_metadata(lv) ||
lv_is_cache_pool_data(lv) ||
lv_is_thin_pool_metadata(lv) ||
lv_is_thin_pool_data(lv) ||
lv_is_used_cache_pool(lv) ||
lv_is_mirrored(lv) ||
lv_is_raid(lv)) {
return 1;
}
log_error("Operation not permitted (%s %d) on hidden LV %s.",
cmd->command->command_line_id, cmd->command->command_line_enum,
display_lvname(lv));
return 0;
}
return 1;
}
/*
* Reomove missing and empty PVs from VG, if are also in provided list
*/
@@ -153,7 +123,7 @@ int lvconvert_repair_pvs_or_thinpool_cmd(struct cmd_context *cmd, int argc, char
cmd->handles_missing_pvs = 1;
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
handle, &lvconvert_generic_check, &_lvconvert_repair_pvs_or_thinpool_single);
handle, NULL, &_lvconvert_repair_pvs_or_thinpool_single);
init_ignore_suspended_devices(saved_ignore_suspended_devices);
@@ -230,7 +200,7 @@ int lvconvert_replace_pv_cmd(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &lr;
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
handle, &lvconvert_generic_check, &_lvconvert_replace_pv_single);
handle, NULL, &_lvconvert_replace_pv_single);
destroy_processing_handle(cmd, handle);

View File

@@ -200,7 +200,10 @@ static int _lvconvert_merge_old_snapshot(struct cmd_context *cmd,
if (!lv_update_and_reload(origin))
return_0;
*lv_to_poll = origin;
if (!lv_info(cmd, origin, 0, &info, 0, 0) || !info.exists)
log_print_unless_silent("Conversion starts after activation.");
else
*lv_to_poll = origin;
}
if (merge_on_activate)
@@ -290,20 +293,6 @@ int lvconvert_merge_snapshot_single(struct cmd_context *cmd,
return ECMD_PROCESSED;
}
static int _lvconvert_merge_snapshot_check(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle,
int lv_is_named_arg)
{
if (!lv_is_visible(lv)) {
log_error("Operation not permitted (%s %d) on hidden LV %s.",
cmd->command->command_line_id, cmd->command->command_line_enum,
display_lvname(lv));
return 0;
}
return 1;
}
int lvconvert_merge_snapshot_cmd(struct cmd_context *cmd, int argc, char **argv)
{
struct processing_handle *handle;
@@ -321,7 +310,7 @@ int lvconvert_merge_snapshot_cmd(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &lr;
ret = process_each_lv(cmd, cmd->position_argc, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
handle, &_lvconvert_merge_snapshot_check, &lvconvert_merge_snapshot_single);
handle, NULL, &lvconvert_merge_snapshot_single);
if (lr.need_polling) {
dm_list_iterate_items(idl, &lr.poll_idls) {
@@ -357,7 +346,7 @@ static int _lvconvert_split_snapshot_single(struct cmd_context *cmd,
int lvconvert_split_snapshot_cmd(struct cmd_context *cmd, int argc, char **argv)
{
return process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE,
NULL, &lvconvert_generic_check, &_lvconvert_split_snapshot_single);
NULL, NULL, &_lvconvert_split_snapshot_single);
}
/*
@@ -419,5 +408,5 @@ static int _lvconvert_combine_split_snapshot_single(struct cmd_context *cmd,
int lvconvert_combine_split_snapshot_cmd(struct cmd_context *cmd, int argc, char **argv)
{
return process_each_lv(cmd, 1, cmd->position_argv + 1, NULL, NULL, READ_FOR_UPDATE,
NULL, &lvconvert_generic_check, &_lvconvert_combine_split_snapshot_single);
NULL, NULL, &_lvconvert_combine_split_snapshot_single);
}

View File

@@ -147,20 +147,17 @@ struct command_function command_functions[COMMAND_ID_COUNT] = {
{ lvconvert_split_and_keep_cachepool_CMD, lvconvert_split_cachepool_cmd },
{ lvconvert_split_and_remove_cachepool_CMD, lvconvert_split_cachepool_cmd },
/* lvconvert raid-related type conversions */
{ lvconvert_raid_types_CMD, lvconvert_raid_types_cmd },
/* lvconvert utilities for raid/mirror */
{ lvconvert_merge_mirror_images_CMD, lvconvert_merge_mirror_images_cmd },
#if 0
{ lvconvert_split_mirror_images_CMD, lvconvert_split_mirror_images_cmd },
{ lvconvert_split_mirror_images_CMD, lvconvert_split_mirror_images_cmd},
{ lvconvert_change_mirrorlog_CMD, lvconvert_change_mirrorlog_cmd },
#endif
{ lvconvert_merge_mirror_images_CMD, lvconvert_merge_mirror_images_cmd },
/* redirected to merge_snapshot/merge_thin/merge_mirrors */
{ lvconvert_merge_CMD, lvconvert_merge_cmd },
#if 0
/* all raid-related type conversions */
{ lvconvert_raid_types_CMD, lvconvert_raid_types_cmd },
#endif
};

View File

@@ -2934,11 +2934,11 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
int ret = 0;
int whole_selected = 0;
int handle_supplied = handle != NULL;
int lv_is_named_arg;
unsigned process_lv;
unsigned process_all = 0;
unsigned tags_supplied = 0;
unsigned lvargs_supplied = 0;
int lv_is_named_arg;
int lv_arg_pos;
struct lv_list *lvl;
struct dm_str_list *sl;

View File

@@ -271,15 +271,13 @@ int lvconvert_swap_pool_metadata_cmd(struct cmd_context *cmd, int argc, char **a
int lvconvert_merge_thin_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvconvert_split_cachepool_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvconvert_raid_types_cmd(struct cmd_context * cmd, int argc, char **argv);
int lvconvert_split_mirror_images_cmd(struct cmd_context * cmd, int argc, char **argv);
int lvconvert_merge_mirror_images_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvconvert_change_mirrorlog_cmd(struct cmd_context * cmd, int argc, char **argv);
int lvconvert_merge_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvconvert_generic_check(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle,
int lv_is_named_arg);
int lvconvert_repair_pvs_mirror(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle,
struct dm_list *use_pvh);