1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-10-07 15:33:21 +03:00

Compare commits

..

6 Commits

Author SHA1 Message Date
David Teigland
9c183d8892 lvconvert: remove unused calls for snapshots
snapshot commands are no longer called from the
monolithic lvconvert code, so remove the unused code.
2016-11-21 15:55:27 -06:00
David Teigland
8e76477c45 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-11-21 15:55:23 -06:00
David Teigland
ed631ae6b6 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-11-21 14:50:21 -06:00
David Teigland
cd1203cadc 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-11-21 14:50:21 -06:00
David Teigland
347a98cbbc 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-11-21 14:50:17 -06:00
David Teigland
b01d88626d 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-11-17 11:46:27 -06:00
21 changed files with 143 additions and 541 deletions

View File

@@ -85,9 +85,12 @@ offset=$(( offset + 2 ))
# update in case mirror ever gets faster and allows parallel read
aux delay_dev "$dev2" 0 2000 ${offset}:1
lvcreate -aey -l5 -Zn -Wn --type mirror --regionsize 16K -m2 -n $lv1 $vg "$dev1" "$dev2" "$dev4" "$dev3:$DEVRANGE"
# FIXME: add a new explicit option to define the polling behavior
# done here with 'lvconvert vg/lv'. That option can specify
# that the command succeeds even if the LV doesn't need polling.
should not lvconvert -m-1 $vg/$lv1 "$dev1"
aux enable_dev "$dev2"
lvconvert --startpoll $vg/$lv1 || true # wait
should lvconvert $vg/$lv1 # wait
lvconvert -m2 $vg/$lv1 "$dev1" "$dev2" "$dev4" "$dev3:0" # If the above "should" failed...
aux wait_for_sync $vg $lv1
@@ -113,7 +116,7 @@ LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
# Next convert should fail b/c we can't have 2 at once
should not lvconvert -m+1 $vg/$lv1 "$dev5"
aux enable_dev "$dev4"
lvconvert --startpoll $vg/$lv1 || true # wait
should lvconvert $vg/$lv1 # wait
lvconvert -m2 $vg/$lv1 # In case the above "should" actually failed
check mirror $vg $lv1 "$dev3"
@@ -156,7 +159,7 @@ lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE
lvchange -an $vg/$lv1
lvconvert -m+1 $vg/$lv1 "$dev4"
lvchange -aey $vg/$lv1
lvconvert --startpoll $vg/$lv1 || true # wait
should lvconvert $vg/$lv1 # wait
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
lvremove -ff $vg
@@ -168,7 +171,7 @@ lvremove -ff $vg
lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE"
LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
lvconvert -m-1 $vg/$lv1 "$dev4"
lvconvert --startpoll $vg/$lv1 || true # wait
should lvconvert $vg/$lv1 # wait
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
@@ -179,7 +182,7 @@ lvremove -ff $vg
lvcreate -aey -l2 --type mirror -m1 -n $lv1 $vg "$dev1" "$dev2" "$dev3:$DEVRANGE"
LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+2 -b $vg/$lv1 "$dev4" "$dev5"
lvconvert -m-1 $vg/$lv1 "$dev4"
lvconvert --startpoll $vg/$lv1 || true # wait
should lvconvert $vg/$lv1 # wait
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
@@ -192,9 +195,9 @@ LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
# FIXME: Extra wait here for mirror upconvert synchronization
# otherwise we may fail her on parallel upconvert and downconvert
# lvconvert-mirror-updown.sh tests this errornous case separately
lvconvert --startpoll $vg/$lv1 || true
should lvconvert $vg/$lv1
lvconvert -m-1 $vg/$lv1 "$dev2"
lvconvert --startpoll $vg/$lv1 || true
should lvconvert $vg/$lv1
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1
@@ -207,9 +210,9 @@ LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -m+1 -b $vg/$lv1 "$dev4"
# FIXME: Extra wait here for mirror upconvert synchronization
# otherwise we may fail her on parallel upconvert and downconvert
# lvconvert-mirror-updown.sh tests this errornous case separately
lvconvert --startpoll $vg/$lv1 || true
should lvconvert $vg/$lv1
lvconvert -m-1 $vg/$lv1 "$dev2"
lvconvert --startpoll $vg/$lv1 || true
should lvconvert $vg/$lv1
check mirror $vg $lv1 "$dev3"
check mirror_no_temporaries $vg $lv1

View File

@@ -54,7 +54,7 @@ mkdir test_mnt
setup_merge_ $vg1 $lv1
mount "$(lvdev_ $vg1 $lv1)" test_mnt
lvconvert --mergesnapshot $vg1/$(snap_lv_name_ $lv1)
lvconvert --merge $vg1/$(snap_lv_name_ $lv1)
umount test_mnt
vgchange -an $vg1

View File

@@ -34,7 +34,7 @@ snap_and_merge() {
SLEEP_PID=$!
# initiate background merge
lvconvert -b --mergesnapshot $vg/$lv2
lvconvert -b --merge $vg/$lv2
lvs -a -o+lv_merging,lv_merge_failed $vg
kill $SLEEP_PID

View File

@@ -51,15 +51,15 @@ mkdir test_mnt
# test full merge of a single LV
setup_merge_ $vg $lv1
# make sure lvconvert --mergesnapshot requires explicit LV listing
not lvconvert --mergesnapshot
lvconvert --mergesnapshot $vg/$(snap_lv_name_ $lv1)
# make sure lvconvert --merge requires explicit LV listing
not lvconvert --merge
lvconvert --merge $vg/$(snap_lv_name_ $lv1)
lvremove -f $vg/$lv1
# test that an actively merging snapshot may not be removed
setup_merge_ $vg $lv1
lvconvert -i+100 --mergesnapshot --background $vg/$(snap_lv_name_ $lv1)
lvconvert -i+100 --merge --background $vg/$(snap_lv_name_ $lv1)
not lvremove -f $vg/$(snap_lv_name_ $lv1)
lvremove -f $vg/$lv1
@@ -67,7 +67,7 @@ lvremove -f $vg/$lv1
# "onactivate merge" test
setup_merge_ $vg $lv1
mount "$(lvdev_ $vg $lv1)" test_mnt
lvconvert --mergesnapshot $vg/$(snap_lv_name_ $lv1)
lvconvert --merge $vg/$(snap_lv_name_ $lv1)
# -- refresh LV while FS is still mounted (merge must not start),
# verify 'snapshot-origin' target is still being used
lvchange --refresh $vg/$lv1

View File

@@ -102,7 +102,7 @@ lvcreate -s -n snap $vg/$lv1
lvcreate -s -L10 -n oldsnapof_${lv1} $vg/$lv1
not lvconvert --merge $vg/snap
$MKFS "$DM_DEV_DIR/$vg/oldsnapof_${lv1}"
lvconvert --mergesnapshot $vg/oldsnapof_${lv1}
lvconvert --merge $vg/oldsnapof_${lv1}
fsck -n "$DM_DEV_DIR/$vg/$lv1"
check lv_not_exists $vg oldsnapof_${lv1}
# Add old snapshot to thin snapshot

View File

@@ -118,7 +118,6 @@ arg(splitmirrors_ARG, '\0', "splitmirrors", number_VAL, 0, 0)
arg(splitsnapshot_ARG, '\0', "splitsnapshot", 0, 0, 0)
arg(showdeprecated_ARG, '\0', "showdeprecated", 0, 0, 0)
arg(showunsupported_ARG, '\0', "showunsupported", 0, 0, 0)
arg(startpoll_ARG, '\0', "startpoll", 0, 0, 0)
arg(stripes_long_ARG, '\0', "stripes", number_VAL, 0, 0)
arg(syncaction_ARG, '\0', "syncaction", syncaction_VAL, 0, 0)
arg(sysinit_ARG, '\0', "sysinit", 0, 0, 0)

View File

@@ -239,12 +239,8 @@ OO_LVCHANGE_META: --addtag Tag, --deltag Tag,
--minrecoveryrate SizeKB, --maxrecoveryrate SizeKB,
--writebehind Number, --writemostly WriteMostlyPV, --persistent n
# It's unfortunate that activate needs to be optionally allowed here;
# it should only be used explicitly, but it's been previously allowed
# in combination with unrelated metadata changes.
lvchange OO_LVCHANGE_META VG|LV|Tag|Select ...
OO: --activate Active, OO_LVCHANGE
OO: OO_LVCHANGE
ID: lvchange_properties
DESC: Change a general LV property.
RULE: all not lv_is_pvmove lv_is_mirror_log lv_is_mirror_image
@@ -260,11 +256,8 @@ RULE: --permission not lv_is_external_origin lv_is_raid_metadata lv_is_raid_imag
RULE: --alloc --contiguous --metadataprofile --permission --persistent --profile --readahead not lv_is_thick_origin
RULE: --alloc --discards --zero --cachemode --cachepolicy --cachesettings not lv_is_partial
# It's unfortunate that acativate needs to be optionally allowed here,
# like above, it was previouly allowed in combination.
lvchange --resync VG|LV_raid_mirror|Tag|Select ...
OO: --activate Activate, OO_LVCHANGE
OO: OO_LVCHANGE
ID: lvchange_resync
DESC: Resyncronize a mirror or raid LV.
RULE: all not lv_is_pvmove lv_is_locked
@@ -282,9 +275,10 @@ ID: lvchange_rebuild
DESC: Reconstruct data on specific PVs of a raid LV.
RULE: all not LV_raid0
# try removing the META change options from here?
lvchange --activate Active VG|LV|Tag|Select ...
OO: --activationmode ActivationMode, --partial, --ignoreactivationskip,
--ignorelockingfailure, --sysinit, OO_LVCHANGE
--ignorelockingfailure, --sysinit, OO_LVCHANGE_META, OO_LVCHANGE
ID: lvchange_activate
DESC: Activate or deactivate an LV.
@@ -525,32 +519,24 @@ lvconvert --splitsnapshot LV_snapshot
OO: OO_LVCONVERT
ID: lvconvert_split_cow_snapshot
DESC: Separate a COW snapshot from its origin LV.
RULE: all not lv_is_locked lv_is_pvmove lv_is_origin lv_is_external_origin lv_is_merging_cow
RULE: all not lv_is_locked lv_is_pvmove lv_is_origin lv_is_external_origin lv_is_merging_cow lv_is_vg_writable
---
# NB: an unsual use of position args here, the first pos arg
# (will become origin LV) is not passed to process_each,
# the second pos arg (will become cow LV) is given to
# process_each. Because the first pos LV is not handled
# by process_each_lv, it cannot be checked against this
# command def, so a specific LV type in the first pos
# will not be checked.
# NB: an unsual use of position args here
# alternate form of lvconvert --snapshot
lvconvert --type snapshot LV LV_linear
lvconvert --type snapshot LV_linear_striped_raid LV_snapshot
OO: --snapshot, --chunksize SizeKB, --zero Bool, OO_LVCONVERT
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.
DESC: Combine LV with a previously split snapshot LV.
FLAGS: SECONDARY_SYNTAX
RULE: all not lv_is_locked lv_is_pvmove
lvconvert --snapshot LV LV_linear
lvconvert --snapshot LV_linear_striped_raid LV_snapshot
OO: --type snapshot, --chunksize SizeKB, --zero Bool, OO_LVCONVERT
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.
DESC: Combine LV with a previously split snapshot LV.
RULE: all not lv_is_locked lv_is_pvmove
---
@@ -589,22 +575,13 @@ RULE: all not lv_is_locked lv_is_pvmove
---
# This command just (re)starts the polling process on the LV
# to continue a previous conversion.
# FIXME: add a new option defining this operation, e.g. --poll-mirror
# The purpose of this command is not entirely clear.
lvconvert --startpoll LV_mirror
OO: OO_LVCONVERT
ID: lvconvert_start_poll
DESC: Poll LV to continue conversion.
RULE: all and lv_is_converting
# alternate form of lvconvert --startpoll, this is only kept
# for compat since this was how it used to be done.
lvconvert LV_mirror
OO: OO_LVCONVERT
ID: lvconvert_start_poll
DESC: Poll LV to continue conversion.
RULE: all and lv_is_converting
ID: lvconvert_poll_start
DESC: Poll mirror LV to collapse resync layers.
FLAGS: SECONDARY_SYNTAX
---

View File

@@ -28,7 +28,5 @@ lvt(raid4_LVT, "raid4", NULL)
lvt(raid5_LVT, "raid5", NULL)
lvt(raid6_LVT, "raid6", NULL)
lvt(raid10_LVT, "raid10", NULL)
lvt(error_LVT, "error", NULL)
lvt(zero_LVT, "zero", NULL)
lvt(LVT_COUNT, "", NULL)

View File

@@ -1009,57 +1009,14 @@ static int _lvchange_properties_single(struct cmd_context *cmd,
return ECMD_PROCESSED;
}
static int _lvchange_properties_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_named_arg)
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 lvchange_properties_cmd(struct cmd_context *cmd, int argc, char **argv)
{
int ret;
/*
* A command def rule allows only some options when LV is partial,
* so handles_missing_pvs will only affect those.
*/
cmd->handles_missing_pvs = 1;
ret = process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE,
NULL, &_lvchange_properties_check, &_lvchange_properties_single);
if (ret != ECMD_PROCESSED)
return ret;
/*
* Unfortunately, lvchange has previously allowed changing an LV
* property and changing LV activation in a single command. This was
* not a good idea because the behavior/results are hard to predict and
* not possible to sensibly describe. It's also unnecessary. So, this
* is here for the sake of compatibility.
*
* This is extremely ugly; activation should always be done separately.
* This is not the full-featured lvchange capability, just the basic
* (the advanced activate options are not provided.)
*
* FIXME: wrap this in a config setting that we can disable by default
* to phase this out?
*/
if (arg_is_set(cmd, activate_ARG)) {
log_warn("WARNING: Combining activation change with other commands is not advised.");
ret = lvchange_activate_cmd(cmd, argc, argv);
}
return ret;
return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL, _lvchange_properties_single);
}
static int _lvchange_activate_single(struct cmd_context *cmd,
@@ -1116,22 +1073,6 @@ static int _lvchange_activate_single(struct cmd_context *cmd,
return ECMD_PROCESSED;
}
static int _lvchange_activate_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_named_arg)
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 lvchange_activate_cmd(struct cmd_context *cmd, int argc, char **argv)
{
cmd->handles_missing_pvs = 1;
@@ -1148,8 +1089,7 @@ int lvchange_activate_cmd(struct cmd_context *cmd, int argc, char **argv)
if (is_change_activating((activation_change_t)arg_uint_value(cmd, activate_ARG, CHANGE_AY)))
cmd->lockd_vg_enforce_sh = 1;
return process_each_lv(cmd, argc, argv, NULL, NULL, 0,
NULL, &_lvchange_activate_check, &_lvchange_activate_single);
return process_each_lv(cmd, argc, argv, NULL, NULL, 0, NULL, _lvchange_activate_single);
}
static int _lvchange_refresh_single(struct cmd_context *cmd,
@@ -1172,29 +1112,12 @@ static int _lvchange_refresh_single(struct cmd_context *cmd,
return ECMD_PROCESSED;
}
static int _lvchange_refresh_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_named_arg)
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 lvchange_refresh_cmd(struct cmd_context *cmd, int argc, char **argv)
{
cmd->handles_missing_pvs = 1;
cmd->lockd_vg_default_sh = 1;
return process_each_lv(cmd, argc, argv, NULL, NULL, 0,
NULL, &_lvchange_refresh_check, &_lvchange_refresh_single);
return process_each_lv(cmd, argc, argv, NULL, NULL, 0, NULL, _lvchange_refresh_single);
}
static int _lvchange_resync_single(struct cmd_context *cmd,
@@ -1207,45 +1130,9 @@ static int _lvchange_resync_single(struct cmd_context *cmd,
return ECMD_PROCESSED;
}
static int _lvchange_resync_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_named_arg)
return 1;
return 0;
}
return 1;
}
int lvchange_resync_cmd(struct cmd_context *cmd, int argc, char **argv)
{
int ret;
ret = process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE,
NULL, &_lvchange_resync_check, &_lvchange_resync_single);
if (ret != ECMD_PROCESSED)
return ret;
/*
* Unfortunately, lvchange has previously allowed resync and changing
* activation to be combined in one command. activate should be
* done separately, but this is here to avoid breaking commands that
* used this.
*
* FIXME: wrap this in a config setting that we can disable by default
* to phase this out?
*/
if (arg_is_set(cmd, activate_ARG)) {
log_warn("WARNING: Combining activation change with other commands is not advised.");
ret = lvchange_activate_cmd(cmd, argc, argv);
}
return ret;
return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL, _lvchange_resync_single);
}
static int _lvchange_syncaction_single(struct cmd_context *cmd,
@@ -1258,24 +1145,9 @@ static int _lvchange_syncaction_single(struct cmd_context *cmd,
return ECMD_PROCESSED;
}
static int _lvchange_syncaction_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_named_arg)
return 1;
return 0;
}
return 1;
}
int lvchange_syncaction_cmd(struct cmd_context *cmd, int argc, char **argv)
{
return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE,
NULL, &_lvchange_syncaction_check, &_lvchange_syncaction_single);
return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL, _lvchange_syncaction_single);
}
static int _lvchange_rebuild_single(struct cmd_context *cmd,
@@ -1288,24 +1160,9 @@ static int _lvchange_rebuild_single(struct cmd_context *cmd,
return ECMD_PROCESSED;
}
static int _lvchange_rebuild_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_named_arg)
return 1;
return 0;
}
return 1;
}
int lvchange_rebuild_cmd(struct cmd_context *cmd, int argc, char **argv)
{
return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE,
NULL, &_lvchange_rebuild_check, &_lvchange_rebuild_single);
return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL, _lvchange_rebuild_single);
}
static int _lvchange_monitor_poll_single(struct cmd_context *cmd,
@@ -1323,25 +1180,10 @@ static int _lvchange_monitor_poll_single(struct cmd_context *cmd,
return ECMD_PROCESSED;
}
static int _lvchange_monitor_poll_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_named_arg)
return 1;
return 0;
}
return 1;
}
int lvchange_monitor_poll_cmd(struct cmd_context *cmd, int argc, char **argv)
{
cmd->handles_missing_pvs = 1;
return process_each_lv(cmd, argc, argv, NULL, NULL, 0,
NULL, &_lvchange_monitor_poll_check, &_lvchange_monitor_poll_single);
return process_each_lv(cmd, argc, argv, NULL, NULL, 0, NULL, _lvchange_monitor_poll_single);
}
static int _lvchange_persistent_single(struct cmd_context *cmd,
@@ -1354,27 +1196,10 @@ static int _lvchange_persistent_single(struct cmd_context *cmd,
return ECMD_PROCESSED;
}
static int _lvchange_persistent_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_named_arg)
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 lvchange_persistent_cmd(struct cmd_context *cmd, int argc, char **argv)
{
cmd->handles_missing_pvs = 1;
return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE,
NULL, &_lvchange_persistent_check, &_lvchange_persistent_single);
return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL, _lvchange_persistent_single);
}
int lvchange(struct cmd_context *cmd, int argc, char **argv)

View File

@@ -2076,25 +2076,12 @@ static int _lvconvert_snapshot(struct cmd_context *cmd,
return_0;
/*
* check_lv_rules() checks cannot be done via command definition
* rules because this LV is not processed by process_each_lv.
* lv_is_prop checks here cannot be automated by command definition
* rules because they are not done on the LV being processed.
*/
if (lv_is_locked(org) || lv_is_pvmove(org)) {
log_error("Unable to use LV %s as snapshot origin: LV is %s.",
display_lvname(lv), lv_is_locked(org) ? "locked" : "pvmove");
return 0;
}
/*
* check_lv_types() checks cannot be done via command definition
* LV_foo specification because this LV is not processed by process_each_lv.
*/
if (lv_is_cache_type(org) ||
lv_is_thin_type(org) ||
lv_is_mirrored(org) ||
lv_is_cow(org)) {
log_error("Unable to use LV %s as snapshot origin: invald LV type.",
display_lvname(lv));
log_error("Unable to convert an LV into a snapshot of a %s LV.",
lv_is_locked(org) ? "locked" : "pvmove");
return 0;
}
@@ -3918,6 +3905,23 @@ 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);
/*
* FIXME: this is here to preserve old behavior, but an
* explicit option should be added to enable this case,
* rather than making it the result of an ambiguous
* "lvconvert vg/lv" command.
* Add 'lvconvert --poll-mirror vg/lv' for this case.
*
* Old behavior was described as:
* "Collapsing a stack of mirrors.
* If called with no argument, try collapsing the resync layers"
*/
log_debug("Checking if LV %s is converting.", display_lvname(lv));
if (lv_is_converting(lv)) {
lp->need_polling = 1;
return 1;
}
log_error("Operation not permitted on mirror LV %s.", display_lvname(lv));
log_error("Operations permitted on a mirror LV are:\n"
" --mirrors\n"
@@ -4318,7 +4322,7 @@ int lvconvert(struct cmd_context * cmd, int argc, char **argv)
if (lp.merge) {
ret = process_each_lv(cmd, argc, argv, NULL, NULL,
READ_FOR_UPDATE, handle, NULL, &_lvconvert_merge_single);
READ_FOR_UPDATE, handle, &_lvconvert_merge_single);
} else {
int saved_ignore_suspended_devices = ignore_suspended_devices();
@@ -4328,7 +4332,7 @@ int lvconvert(struct cmd_context * cmd, int argc, char **argv)
}
ret = process_each_lv(cmd, 0, NULL, lp.vg_name, lp.lv_name,
READ_FOR_UPDATE, handle, NULL, &_lvconvert_single);
READ_FOR_UPDATE, handle, &_lvconvert_single);
init_ignore_suspended_devices(saved_ignore_suspended_devices);
}
@@ -4374,36 +4378,6 @@ out:
*/
/*
* FIXME: it's very unlikely that the same !visible exceptions apply to every
* lvconvert command. Add specific !visible exceptions in command-specific
* check functions.
*/
static 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;
}
/*
* Data/results accumulated during processing.
*/
@@ -4608,8 +4582,8 @@ 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);
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE, handle,
&_lvconvert_repair_pvs_or_thinpool_single);
init_ignore_suspended_devices(saved_ignore_suspended_devices);
@@ -4685,8 +4659,8 @@ 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);
ret = process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE, handle,
&_lvconvert_replace_pv_single);
destroy_processing_handle(cmd, handle);
@@ -4724,20 +4698,6 @@ static 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;
@@ -4754,13 +4714,13 @@ 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);
ret = process_each_lv(cmd, cmd->position_argc, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE, handle,
_lvconvert_merge_snapshot_single);
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), 1, 0);
arg_is_set(cmd, background_ARG), 0, 0);
if (poll_ret > ret)
ret = poll_ret;
}
@@ -4790,48 +4750,13 @@ 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);
return process_each_lv(cmd, 1, cmd->position_argv, NULL, NULL, READ_FOR_UPDATE, NULL,
_lvconvert_split_snapshot_single);
}
/*
* Combine two LVs that were once an origin/cow pair of LVs, were then
* separated with --splitsnapshot, and now with this command are combined again
* into the origin/cow pair.
*
* This is an obscure command that has little to no real uses.
*
* The command has unusual handling of position args. The first position arg
* will become the origin LV, and is not processed by process_each_lv. The
* second position arg will become the cow LV and is processed by
* process_each_lv.
*
* The single function can grab the origin LV from position_argv[0].
*
* begin with an ordinary LV foo:
* lvcreate -n foo -L 1 vg
*
* create a cow snapshot of foo named foosnap:
* lvcreate -s -L 1 -n foosnap vg/foo
*
* now, foo is an "origin LV" and foosnap is a "cow LV"
* (foosnap matches LV_snapshot aka lv_is_cow)
*
* split the two LVs apart:
* lvconvert --splitsnapshot vg/foosnap
*
* now, foo is *not* an origin LV and foosnap is *not* a cow LV
* (foosnap does not match LV_snapshot)
*
* now, combine the two LVs again:
* lvconvert --snapshot vg/foo vg/foosnap
*
* after this, foosnap will match LV_snapshot again.
*
* FIXME: when splitsnapshot is run, the previous cow LV should be
* flagged in the metadata somehow, and then that flag should be
* required here. As it is now, the first and second args
* (origin and cow) can be swapped and nothing catches it.
* Combine an origin LV with a snapshot LV (cow) that was previously split from
* the origin using --splitsnapshot.
*/
static int _lvconvert_combine_split_snapshot_single(struct cmd_context *cmd,
@@ -4852,64 +4777,15 @@ 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);
}
static int _lvconvert_start_poll_single(struct cmd_context *cmd,
struct logical_volume *lv,
struct processing_handle *handle)
{
struct lvconvert_result *lr = (struct lvconvert_result *) handle->custom_handle;
struct convert_poll_id_list *idl;
if (!(idl = _convert_poll_id_list_create(cmd, lv)))
return_ECMD_FAILED;
dm_list_add(&lr->poll_idls, &idl->list);
lr->need_polling = 1;
return ECMD_PROCESSED;
}
int lvconvert_start_poll_cmd(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, NULL, &_lvconvert_start_poll_single);
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;
/*
* The command has unusual handling of position args. The first
* position arg is the origin name, and that LV is not processed by
* process_each_lv. The second position arg is the snapshot LV that's
* processed by process_each_lv. The single function can grab the
* origin LV from position_argv[0].
*/
return process_each_lv(cmd, 1, cmd->position_argv + 1, NULL, NULL, READ_FOR_UPDATE, NULL,
_lvconvert_combine_split_snapshot_single);
}

View File

@@ -58,5 +58,5 @@ int lvdisplay(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
return process_each_lv(cmd, argc, argv, NULL, NULL, 0, NULL, NULL, &_lvdisplay_single);
return process_each_lv(cmd, argc, argv, NULL, NULL, 0, NULL, &_lvdisplay_single);
}

View File

@@ -131,11 +131,7 @@ struct command_function command_functions[COMMAND_ID_COUNT] = {
{ lvconvert_split_cow_snapshot_CMD, lvconvert_split_snapshot_cmd },
{ lvconvert_merge_snapshot_CMD, lvconvert_merge_snapshot_cmd },
{ lvconvert_combine_split_snapshot_CMD, lvconvert_combine_split_snapshot_cmd },
/* lvconvert utility to trigger polling on an LV. */
{ lvconvert_start_poll_CMD, lvconvert_start_poll_cmd },
};
#if 0
/* all raid-related type conversions */
@@ -159,6 +155,8 @@ struct command_function command_functions[COMMAND_ID_COUNT] = {
/* other misc. */
{ lvconvert_merge_CMD, lvconvert_merge_fn },
{ lvconvert_poll_start_CMD, lvconvert_poll_start_fn },
#endif
/* Command line args */

View File

@@ -27,5 +27,5 @@ int lvremove(struct cmd_context *cmd, int argc, char **argv)
cmd->include_historical_lvs = 1;
return process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL,
NULL, &lvremove_single);
&lvremove_single);
}

View File

@@ -119,5 +119,5 @@ int lvscan(struct cmd_context *cmd, int argc, char **argv)
*/
}
return process_each_lv(cmd, argc, argv, NULL, NULL, 0, NULL, NULL, &lvscan_single);
return process_each_lv(cmd, argc, argv, NULL, NULL, 0, NULL, &lvscan_single);
}

View File

@@ -517,14 +517,14 @@ static int _report_all_in_vg(struct cmd_context *cmd, struct processing_handle *
r = _vgs_single(cmd, vg->name, vg, handle);
break;
case LVS:
r = process_each_lv_in_vg(cmd, vg, NULL, NULL, 0, handle, NULL,
r = process_each_lv_in_vg(cmd, vg, NULL, NULL, 0, handle,
do_lv_info && !do_lv_seg_status ? &_lvs_with_info_single :
!do_lv_info && do_lv_seg_status ? &_lvs_with_status_single :
do_lv_info && do_lv_seg_status ? &_lvs_with_info_and_status_single :
&_lvs_single);
break;
case SEGS:
r = process_each_lv_in_vg(cmd, vg, NULL, NULL, 0, handle, NULL,
r = process_each_lv_in_vg(cmd, vg, NULL, NULL, 0, handle,
do_lv_info && !do_lv_seg_status ? &_lvsegs_with_info_single :
!do_lv_info && do_lv_seg_status ? &_lvsegs_with_status_single :
do_lv_info && do_lv_seg_status ? &_lvsegs_with_info_and_status_single :
@@ -1099,7 +1099,7 @@ static int _do_report(struct cmd_context *cmd, struct processing_handle *handle,
if (args->full_report_vg)
r = _report_all_in_vg(cmd, handle, args->full_report_vg, LVS, lv_info_needed, lv_segment_status_needed);
else
r = process_each_lv(cmd, args->argc, args->argv, NULL, NULL, 0, handle, NULL,
r = process_each_lv(cmd, args->argc, args->argv, NULL, NULL, 0, handle,
lv_info_needed && !lv_segment_status_needed ? &_lvs_with_info_single :
!lv_info_needed && lv_segment_status_needed ? &_lvs_with_status_single :
lv_info_needed && lv_segment_status_needed ? &_lvs_with_info_and_status_single :
@@ -1133,7 +1133,7 @@ static int _do_report(struct cmd_context *cmd, struct processing_handle *handle,
if (args->full_report_vg)
r = _report_all_in_vg(cmd, handle, args->full_report_vg, SEGS, lv_info_needed, lv_segment_status_needed);
else
r = process_each_lv(cmd, args->argc, args->argv, NULL, NULL, 0, handle, NULL,
r = process_each_lv(cmd, args->argc, args->argv, NULL, NULL, 0, handle,
lv_info_needed && !lv_segment_status_needed ? &_lvsegs_with_info_single :
!lv_info_needed && lv_segment_status_needed ? &_lvsegs_with_status_single :
lv_info_needed && lv_segment_status_needed ? &_lvsegs_with_info_and_status_single :

View File

@@ -2529,10 +2529,6 @@ static int _lv_is_type(struct cmd_context *cmd, struct logical_volume *lv, int l
#endif
case raid10_LVT:
return seg_is_raid10(seg);
case error_LVT:
return !strcmp(seg->segtype->name, SEG_TYPE_NAME_ERROR);
case zero_LVT:
return !strcmp(seg->segtype->name, SEG_TYPE_NAME_ZERO);
default:
log_error(INTERNAL_ERROR "unknown lv type value lvt_enum %d", lvt_enum);
}
@@ -2577,11 +2573,7 @@ static int _get_lvt_enum(struct logical_volume *lv)
if (seg_is_raid10(seg))
return raid10_LVT;
if (!strcmp(seg->segtype->name, SEG_TYPE_NAME_ERROR))
return error_LVT;
if (!strcmp(seg->segtype->name, SEG_TYPE_NAME_ZERO))
return zero_LVT;
log_error(INTERNAL_ERROR "unknown lv type for %s", display_lvname(lv));
return 0;
}
@@ -2677,29 +2669,35 @@ static int _lv_props_match(struct cmd_context *cmd, struct logical_volume *lv, u
return !found_a_mismatch;
}
static int _check_lv_types(struct cmd_context *cmd, struct logical_volume *lv, int pos)
/*
* If the command definition specifies one required positional
* LV (possibly repeatable), and specifies accepted LV types,
* then verify that the LV being processed matches one of those
* types.
*
* process_each_lv() can only be used for commands that have
* one positional LV arg (optionally repeating, where each is
* processed independently.) It cannot work for commands that
* have different required LVs in designated positions, like
* 'lvrename LV1 LV2', where each LV is not processed
* independently. That means that this LV type check only
* needs to check the lv_type of the first positional arg.
*/
static int _check_lv_types(struct cmd_context *cmd, struct logical_volume *lv)
{
int ret = 1;
if (!pos)
return 1;
if (!cmd->command->required_pos_args[pos-1].def.lvt_bits)
return 1;
if (!val_bit_is_set(cmd->command->required_pos_args[pos-1].def.val_bits, lv_VAL)) {
log_error(INTERNAL_ERROR "Command (%s %d) arg position %d does not permit an LV (%llx)",
cmd->command->command_line_id, cmd->command->command_line_enum,
pos, (unsigned long long)cmd->command->required_pos_args[pos-1].def.val_bits);
return 0;
}
ret = _lv_types_match(cmd, lv, cmd->command->required_pos_args[pos-1].def.lvt_bits, NULL, NULL);
if (!ret) {
int lvt_enum = _get_lvt_enum(lv);
struct lv_types *type = get_lv_type(lvt_enum);
log_warn("Operation on LV %s which has invalid type %s.",
display_lvname(lv), type ? type->name : "unknown");
if ((cmd->command->rp_count == 1) &&
val_bit_is_set(cmd->command->required_pos_args[0].def.val_bits, lv_VAL) &&
cmd->command->required_pos_args[0].def.lvt_bits) {
ret = _lv_types_match(cmd, lv, cmd->command->required_pos_args[0].def.lvt_bits, NULL, NULL);
if (!ret) {
int lvt_enum = _get_lvt_enum(lv);
struct lv_types *type = get_lv_type(lvt_enum);
log_warn("Operation on LV %s which has invalid type %s.",
display_lvname(lv), type ? type->name : "unknown");
}
}
return ret;
@@ -2863,64 +2861,10 @@ static int _check_lv_rules(struct cmd_context *cmd, struct logical_volume *lv)
return ret;
}
/*
* Return which arg position the given LV is at,
* where 1 represents the first position arg.
* When the first position arg is repeatable,
* return 1 for all.
*
* Return 0 when the command has no required
* position args. (optional position args are
* not considered.)
*/
static int _find_lv_arg_position(struct cmd_context *cmd, struct logical_volume *lv)
{
const char *sep, *lvname;
int i;
if (cmd->command->rp_count == 0)
return 0;
if (cmd->command->rp_count == 1)
return 1;
for (i = 0; i < cmd->position_argc; i++) {
if (i == cmd->command->rp_count)
break;
if (!val_bit_is_set(cmd->command->required_pos_args[i].def.val_bits, lv_VAL))
continue;
if ((sep = strstr(cmd->position_argv[i], "/")))
lvname = sep + 1;
else
lvname = cmd->position_argv[i];
if (!strcmp(lvname, lv->name))
return i + 1;
}
/*
* If the last position arg is an LV and this
* arg is beyond that position, then the last
* LV position arg is repeatable, so return
* that position.
*/
if (i == cmd->command->rp_count) {
int last_pos = cmd->command->rp_count;
if (val_bit_is_set(cmd->command->required_pos_args[last_pos-1].def.val_bits, lv_VAL))
return last_pos;
}
return 0;
}
int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
struct dm_list *arg_lvnames, const struct dm_list *tags_in,
int stop_on_error,
struct processing_handle *handle,
check_single_lv_fn_t check_single_lv,
process_single_lv_fn_t process_single_lv)
{
log_report_t saved_log_report_state = log_get_report_state();
@@ -2930,12 +2874,10 @@ 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_arg_pos;
struct lv_list *lvl;
struct dm_str_list *sl;
struct dm_list final_lvs;
@@ -3093,40 +3035,42 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
if (lv_is_removed(lvl->lv))
continue;
lv_is_named_arg = str_list_match_item(&found_arg_lvnames, lvl->lv->name);
lv_arg_pos = _find_lv_arg_position(cmd, lvl->lv);
/*
* The command definition may include restrictions on the
* types and properties of LVs that can be processed.
*/
if (!_check_lv_types(cmd, lvl->lv, lv_arg_pos)) {
if (!_check_lv_types(cmd, lvl->lv)) {
/* FIXME: include this result in report log? */
if (lv_is_named_arg) {
/* FIXME: avoid duplicating message for each level */
if (str_list_match_item(&found_arg_lvnames, lvl->lv->name)) {
log_error("Operation not permitted (%s %d) on LV %s.",
cmd->command->command_line_id, cmd->command->command_line_enum,
display_lvname(lvl->lv));
ret_max = ECMD_FAILED;
} else {
log_warn("Operation not permitted (%s %d) on LV %s.",
cmd->command->command_line_id, cmd->command->command_line_enum,
display_lvname(lvl->lv));
}
continue;
}
if (!_check_lv_rules(cmd, lvl->lv)) {
/* FIXME: include this result in report log? */
if (lv_is_named_arg) {
/* FIXME: avoid duplicating message for each level */
if (str_list_match_item(&found_arg_lvnames, lvl->lv->name)) {
log_error("Operation not permitted (%s %d) on LV %s.",
cmd->command->command_line_id, cmd->command->command_line_enum,
display_lvname(lvl->lv));
ret_max = ECMD_FAILED;
}
continue;
}
if (check_single_lv && !check_single_lv(cmd, lvl->lv, handle, lv_is_named_arg)) {
if (lv_is_named_arg)
ret_max = ECMD_FAILED;
} else {
log_warn("Operation not permitted (%s %d) on LV %s.",
cmd->command->command_line_id, cmd->command->command_line_enum,
display_lvname(lvl->lv));
}
continue;
}
@@ -3366,7 +3310,6 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t read_flag
struct dm_list *arg_lvnames,
struct dm_list *arg_tags,
struct processing_handle *handle,
check_single_lv_fn_t check_single_lv,
process_single_lv_fn_t process_single_lv)
{
log_report_t saved_log_report_state = log_get_report_state();
@@ -3459,7 +3402,7 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t read_flag
goto endvg;
ret = process_each_lv_in_vg(cmd, vg, &lvnames, tags_arg, 0,
handle, check_single_lv, process_single_lv);
handle, process_single_lv);
if (ret != ECMD_PROCESSED)
stack;
report_log_ret_code(ret);
@@ -3490,7 +3433,6 @@ int process_each_lv(struct cmd_context *cmd,
const char *one_vgname, const char *one_lvname,
uint32_t read_flags,
struct processing_handle *handle,
check_single_lv_fn_t check_single_lv,
process_single_lv_fn_t process_single_lv)
{
log_report_t saved_log_report_state = log_get_report_state();
@@ -3606,7 +3548,7 @@ int process_each_lv(struct cmd_context *cmd,
_choose_vgs_to_process(cmd, &arg_vgnames, &vgnameids_on_system, &vgnameids_to_process);
ret = _process_lv_vgnameid_list(cmd, read_flags, &vgnameids_to_process, &arg_vgnames, &arg_lvnames,
&arg_tags, handle, check_single_lv, process_single_lv);
&arg_tags, handle, process_single_lv);
if (ret > ret_max)
ret_max = ret;

View File

@@ -98,18 +98,6 @@ typedef int (*process_single_pvseg_fn_t) (struct cmd_context * cmd,
struct pv_segment * pvseg,
struct processing_handle *handle);
/*
* Called prior to process_single_lv() to decide if the LV should be
* processed. If this returns 0, the LV is not processed.
*
* This can evaluate the combination of command definition and
* the LV object to decide if the combination is allowed.
*/
typedef int (*check_single_lv_fn_t) (struct cmd_context *cmd,
struct logical_volume *lv,
struct processing_handle *handle,
int lv_is_named_arg);
int process_each_vg(struct cmd_context *cmd,
int argc, char **argv,
const char *one_vgname,
@@ -137,7 +125,6 @@ int process_each_segment_in_pv(struct cmd_context *cmd,
int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
const char *one_vgname, const char *one_lvname,
uint32_t flags, struct processing_handle *handle,
check_single_lv_fn_t check_single_lv,
process_single_lv_fn_t process_single_lv);
@@ -154,7 +141,6 @@ int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
struct dm_list *arg_lvnames, const struct dm_list *tagsl,
int stop_on_error, struct processing_handle *handle,
check_single_lv_fn_t check_single_lv,
process_single_lv_fn_t process_single_lv);
struct processing_handle *init_processing_handle(struct cmd_context *cmd, struct processing_handle *parent_handle);

View File

@@ -257,6 +257,4 @@ int lvconvert_merge_snapshot_cmd(struct cmd_context *cmd, int argc, char **argv)
int lvconvert_split_snapshot_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvconvert_combine_split_snapshot_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvconvert_start_poll_cmd(struct cmd_context *cmd, int argc, char **argv);
#endif

View File

@@ -38,7 +38,7 @@ static int vgdisplay_single(struct cmd_context *cmd, const char *vg_name,
vgdisplay_extents(vg);
process_each_lv_in_vg(cmd, vg, NULL, NULL, 0, NULL,
NULL, (process_single_lv_fn_t)lvdisplay_full);
(process_single_lv_fn_t)lvdisplay_full);
log_print("--- Physical volumes ---");
process_each_pv_in_vg(cmd, vg, NULL,

View File

@@ -33,5 +33,5 @@ int vgmknodes(struct cmd_context *cmd, int argc, char **argv)
if (!lv_mknodes(cmd, NULL))
return_ECMD_FAILED;
return process_each_lv(cmd, argc, argv, NULL, NULL, LCK_VG_READ, NULL, NULL, &_vgmknodes_single);
return process_each_lv(cmd, argc, argv, NULL, NULL, LCK_VG_READ, NULL, &_vgmknodes_single);
}

View File

@@ -62,7 +62,7 @@ static int vgremove_single(struct cmd_context *cmd, const char *vg_name,
}
if ((ret = process_each_lv_in_vg(cmd, vg, NULL, NULL, 1, &void_handle,
NULL, (process_single_lv_fn_t)lvremove_single)) != ECMD_PROCESSED) {
(process_single_lv_fn_t)lvremove_single)) != ECMD_PROCESSED) {
stack;
return ret;
}