1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-10-03 01:44:19 +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
30 changed files with 1550 additions and 1863 deletions

View File

@@ -61,7 +61,7 @@ check lv_field $vg/$lv2 cache_settings "random_threshold=56,sequential_threshold
# Check swap of cache pool metadata
lvconvert --yes --type cache-pool --poolmetadata $lv4 $vg/$lv3
UUID=$(get lv_field $vg/$lv5 uuid)
lvconvert --yes --swapmetadata --poolmetadata $lv5 $vg/$lv3
lvconvert --yes --cachepool $vg/$lv3 --poolmetadata $lv5
check lv_field $vg/${lv3}_cmeta uuid "$UUID"
@@ -109,30 +109,30 @@ lvcreate -an -Zn -L 8 -n $lv4 $vg
invalid lvconvert --type cache --poolmetadata $vg/$lv2 $vg/$lv1
# Cannot mix with thins
not lvconvert --type cache --poolmetadata $vg/$lv2 --thinpool $vg/$lv1
not lvconvert --type cache --thin --poolmetadata $vg/$lv2 $vg/$lv1
invalid lvconvert --type cache --poolmetadata $vg/$lv2 --thinpool $vg/$lv1
invalid lvconvert --type cache --thin --poolmetadata $vg/$lv2 $vg/$lv1
# Undefined cached volume
not lvconvert --type cache --cachepool $vg/$lv1
not lvconvert --cache --cachepool $vg/$lv1
invalid lvconvert --type cache --cachepool $vg/$lv1
invalid lvconvert --cache --cachepool $vg/$lv1
# Single vg is required
not lvconvert --type cache --cachepool $vg/$lv1 --poolmetadata $vg1/$lv2 $vg/$lv3
not lvconvert --type cache --cachepool $vg/$lv1 --poolmetadata $lv2 $vg1/$lv3
not lvconvert --type cache --cachepool $vg1/$lv1 --poolmetadata $vg2/$lv2 $vg/$lv3
not lvconvert --type cache-pool --poolmetadata $vg2/$lv2 $vg1/$lv1
invalid lvconvert --type cache --cachepool $vg/$lv1 --poolmetadata $vg1/$lv2 $vg/$lv3
invalid lvconvert --type cache --cachepool $vg/$lv1 --poolmetadata $lv2 $vg1/$lv3
invalid lvconvert --type cache --cachepool $vg1/$lv1 --poolmetadata $vg2/$lv2 $vg/$lv3
invalid lvconvert --type cache-pool --poolmetadata $vg2/$lv2 $vg1/$lv1
not lvconvert --cachepool $vg1/$lv1 --poolmetadata $vg2/$lv2
invalid lvconvert --cachepool $vg1/$lv1 --poolmetadata $vg2/$lv2
# Invalid syntax, vg is unknown
not lvconvert --yes --cachepool $lv3 --poolmetadata $lv4
invalid lvconvert --yes --cachepool $lv3 --poolmetadata $lv4
# Invalid chunk size is <32KiB >1GiB
not lvconvert --type cache-pool --chunksize 16 --poolmetadata $lv2 $vg/$lv1
not lvconvert --type cache-pool --chunksize 2G --poolmetadata $lv2 $vg/$lv1
invalid lvconvert --type cache-pool --chunksize 16 --poolmetadata $lv2 $vg/$lv1
invalid lvconvert --type cache-pool --chunksize 2G --poolmetadata $lv2 $vg/$lv1
# Invalid chunk size is bigger then data size, needs to open VG
not lvconvert --yes --type cache-pool --chunksize 16M --poolmetadata $lv2 $vg/$lv1
fail lvconvert --yes --type cache-pool --chunksize 16M --poolmetadata $lv2 $vg/$lv1
lvremove -f $vg
@@ -143,7 +143,7 @@ lvcreate --type cache-pool -an -v -L 2 -n cpool $vg
lvcreate -H -L 4 -n corigin --cachepool $vg/cpool
# unsupported yet
not lvconvert --repair $vg/cpool 2>&1 | tee out
fail lvconvert --repair $vg/cpool 2>&1 | tee out
#grep "Cannot convert internal LV" out
lvremove -f $vg
@@ -155,13 +155,13 @@ lvcreate --type cache-pool -L10 $vg/$lv1
lvcreate --cache -L20 $vg/$lv1
lvcreate -L10 -n $lv2 $vg
not lvconvert --yes --type cache $vg/$lv2 --cachepool $vg/$lv1
not lvconvert --yes --type cache $vg/$lv1 --cachepool $vg/$lv2
not lvconvert --yes --type cache-pool $vg/$lv1
not lvconvert --yes --type mirror -m1 $vg/$lv1
fail lvconvert --yes --type cache $vg/$lv2 --cachepool $vg/$lv1
fail lvconvert --yes --type cache $vg/$lv1 --cachepool $vg/$lv2
fail lvconvert --yes --type cache-pool $vg/$lv1
fail lvconvert --yes --type mirror -m1 $vg/$lv1
not aux have_raid 1 0 0 || fail lvconvert --yes --type raid1 -m1 $vg/$lv1
not lvconvert --yes --type snapshot $vg/$lv1 $vg/$lv2
not lvconvert --yes --type snapshot $vg/$lv2 $vg/$lv1
fail lvconvert --yes --type snapshot $vg/$lv1 $vg/$lv2
fail lvconvert --yes --type snapshot $vg/$lv2 $vg/$lv1
not aux have_thin 1 0 0 || fail lvconvert --yes -T --thinpool $vg/$lv2 $vg/$lv1
lvremove -f $vg

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

@@ -45,7 +45,7 @@ lvchange -an $vg/$lv2 $vg/$lv1 $vg/pool $vg/repair
# Manual repair steps:
# Test swapping - swap out thin-pool's metadata with our repair volume
lvconvert -y -f --swapmetadata --poolmetadata $vg/repair $vg/pool
lvconvert -y -f --poolmetadata $vg/repair --thinpool $vg/pool
lvchange -ay $vg/repair
@@ -74,7 +74,7 @@ not "$LVM_TEST_THIN_DUMP_CMD" "$DM_DEV_DIR/$vg/repair" | tee dump
lvchange -an $vg
# Swap repaired metadata back
lvconvert -y -f --swapmetadata --poolmetadata $vg/fixed $vg/pool
lvconvert -y -f --poolmetadata $vg/fixed --thinpool $vg/pool
# Check pool still preserves its original settings
check lv_field $vg/pool chunksize "128.00k"
@@ -87,7 +87,7 @@ vgchange -ay $vg
vgchange -an $vg
# Put back 'broken' metadata
lvconvert -y -f --swapmetadata --poolmetadata $vg/repair $vg/pool
lvconvert -y -f --poolmetadata $vg/repair --thinpool $vg/pool
# Check --repair usage
lvconvert -v --repair $vg/pool
@@ -98,7 +98,7 @@ lvchange -ay $vg/pool
vgchange -an $vg
# Restore damaged metadata
lvconvert -y -f --swapmetadata --poolmetadata $vg/pool_meta0 $vg/pool
lvconvert -y -f --poolmetadata $vg/pool_meta0 --thinpool $vg/pool
# Check lvremove -ff works even with damaged pool
lvremove -ff $vg

View File

@@ -30,8 +30,8 @@ aux wait_for_sync $vg $lv2
lvchange -an $vg/$lv1
# conversion fails for internal volumes
not lvconvert --thinpool $vg/${lv1}_rimage_0
not lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/${lv2}_rimage_0
invalid lvconvert --thinpool $vg/${lv1}_rimage_0
invalid lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/${lv2}_rimage_0
lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv2

View File

@@ -58,13 +58,13 @@ lvchange -an $vg/$lv1
# conversion fails for mirror segment type
fail lvconvert --thinpool $vg/$lv1
# cannot use same LV
not lvconvert --yes --thinpool $vg/$lv2 --poolmetadata $vg/$lv2
invalid lvconvert --yes --thinpool $vg/$lv2 --poolmetadata $vg/$lv2
prepare_lvs
# conversion fails for internal volumes
# can't use --readahead with --poolmetadata
not lvconvert --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 --readahead 512
invalid lvconvert --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 --readahead 512
lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $vg/$lv2
prepare_lvs
@@ -81,9 +81,9 @@ grep "Pool zeroing and large" err
UUID=$(get lv_field $vg/$lv2 uuid)
# Fail is pool is active
# TODO maybe detect inactive pool and deactivate
fail lvconvert --swapmetadata --yes --poolmetadata $lv2 $vg/$lv1
fail lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $lv2
lvchange -an $vg
lvconvert --swapmetadata --yes --poolmetadata $lv2 $vg/$lv1
lvconvert --yes --thinpool $vg/$lv1 --poolmetadata $lv2
check lv_field $vg/${lv1}_tmeta uuid "$UUID"
lvremove -f $vg
@@ -96,20 +96,20 @@ lvcreate -L1M -n $lv3 $vg
# chunk size is bigger then size of thin pool data
fail lvconvert --yes -c 1G --thinpool $vg/$lv3
# stripes can't be used with poolmetadata
not lvconvert --stripes 2 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2
invalid lvconvert --stripes 2 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2
# too small metadata (<2M)
fail lvconvert --yes -c 64 --thinpool $vg/$lv1 --poolmetadata $vg/$lv3
# too small chunk size fails
not lvconvert -c 4 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2
invalid lvconvert -c 4 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2
# too big chunk size fails
not lvconvert -c 2G --thinpool $vg/$lv1 --poolmetadata $vg/$lv2
invalid lvconvert -c 2G --thinpool $vg/$lv1 --poolmetadata $vg/$lv2
# negative chunk size fails
not lvconvert -c -256 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2
invalid lvconvert -c -256 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2
# non multiple of 64KiB fails
not lvconvert -c 88 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2
invalid lvconvert -c 88 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2
# cannot use same LV for pool and convertion
not lvconvert --yes --thinpool $vg/$lv3 -T $vg/$lv3
invalid lvconvert --yes --thinpool $vg/$lv3 -T $vg/$lv3
# Warning about smaller then suggested
lvconvert --yes -c 256 --thinpool $vg/$lv1 --poolmetadata $vg/$lv2 2>&1 | tee err
@@ -129,7 +129,7 @@ if test "$TSIZE" = 64T; then
lvcreate -L24T -n $lv1 $vg
# Warning about bigger then needed (24T data and 16G -> 128K chunk)
lvconvert --yes -c 64 --thinpool $vg/$lv1 2>&1 | tee err
grep "too small" err
grep "WARNING: Chunk size is too small" err
lvremove -f $vg
fi

View File

@@ -40,7 +40,7 @@ lvchange -an $vg
lvcreate -L2M -n $lv1 $vg
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
lvconvert -y --swapmetadata --poolmetadata $vg/$lv1 $vg/pool
lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1
# Cannot resize if set to 0%
not lvextend --use-policies --config 'activation{thin_pool_autoextend_percent = 0}' $vg/pool 2>&1 | tee err

View File

@@ -78,7 +78,7 @@ fake_metadata_ 400 2 >data
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
# Swap volume with restored fake metadata
lvconvert -y --chunksize 64k --swapmetadata --poolmetadata $vg/$lv1 $vg/pool
lvconvert -y --chunksize 64k --thinpool $vg/pool --poolmetadata $vg/$lv1
# Not alllowed when thin-pool metadata free space is <75% for 2M meta
fail lvcreate -V20 $vg/pool
@@ -91,7 +91,7 @@ lvchange -an $vg/pool
fake_metadata_ 7400 2 >data
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv2"
# Swap volume with restored fake metadata
lvconvert -y --chunksize 64k --swapmetadata --poolmetadata $vg/$lv2 $vg/pool
lvconvert -y --chunksize 64k --thinpool $vg/pool --poolmetadata $vg/$lv2
lvchange -ay $vg/pool
# Check generated metadata consume more then 88%
test "$(meta_percent_)" -gt "88"
@@ -138,7 +138,7 @@ lvchange -an $vg/thin $vg/thin2 $vg/pool
# Transaction_id is lower by 1 and there are no messages -> ERROR
fake_metadata_ 10 0 >data
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
lvconvert -y --swapmetadata --poolmetadata $vg/$lv1 $vg/pool
lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1
not vgchange -ay $vg 2>&1 | tee out
grep expected out
@@ -147,7 +147,7 @@ check inactive $vg pool_tmeta
# Transaction_id is higher by 1
fake_metadata_ 10 3 >data
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
lvconvert -y --swapmetadata --poolmetadata $vg/$lv1 $vg/pool
lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1
not vgchange -ay $vg 2>&1 | tee out
grep expected out
@@ -158,7 +158,7 @@ fake_metadata_ 400 2 >data
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
# Swap volume with restored fake metadata
lvconvert -y --chunksize 64k --swapmetadata --poolmetadata $vg/$lv1 $vg/pool
lvconvert -y --chunksize 64k --thinpool $vg/pool --poolmetadata $vg/$lv1
vgchange -ay $vg
@@ -173,7 +173,7 @@ fake_metadata_ 350 2 >data
lvchange -ay $vg/$lv1
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
lvconvert -y --chunksize 64k --swapmetadata --poolmetadata $vg/$lv1 $vg/pool
lvconvert -y --chunksize 64k --thinpool $vg/pool --poolmetadata $vg/$lv1
lvchange -ay $vg/pool $vg/$lv1
lvs -a $vg

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

@@ -71,7 +71,7 @@ aux prepare_thin_metadata 490 1 | tee data
"$LVM_TEST_THIN_RESTORE_CMD" -i data -o "$DM_DEV_DIR/mapper/$vg-$lv1"
# Swap volume with restored fake metadata
lvconvert -y --swapmetadata --poolmetadata $vg/$lv1 $vg/pool
lvconvert -y --thinpool $vg/pool --poolmetadata $vg/$lv1
lvchange -ay $vg

View File

@@ -44,7 +44,7 @@ touch mntsnap/test_snap
lvs -o+tags,thin_id $vg
lvconvert --mergethin $vg/snap
lvconvert --merge $vg/snap
umount mnt
@@ -102,12 +102,12 @@ 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
lvcreate -s -L10 -n oldsnapof_snap $vg/snap
lvconvert --mergethin $vg/snap
lvconvert --merge $vg/snap
lvremove -f $vg/oldsnapof_snap
vgremove -ff $vg

View File

@@ -34,7 +34,7 @@ mount "$DM_DEV_DIR/$vg/$lv1" mnt
lvcreate -s -n snap $vg/$lv1
check lv_field $vg/snap thin_id "3"
lvconvert --mergethin $vg/snap
lvconvert --merge $vg/snap
umount mnt
vgchange -an $vg

View File

@@ -60,9 +60,7 @@ arg(locktype_ARG, '\0', "locktype", locktype_VAL, 0, 0)
arg(logonly_ARG, '\0', "logonly", 0, 0, 0)
arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", sizekb_VAL, 0, 0)
arg(merge_ARG, '\0', "merge", 0, 0, 0)
arg(mergemirrors_ARG, '\0', "mergemirrors", 0, 0, 0)
arg(mergesnapshot_ARG, '\0', "mergesnapshot", 0, 0, 0)
arg(mergethin_ARG, '\0', "mergethin", 0, 0, 0)
arg(mergedconfig_ARG, '\0', "mergedconfig", 0, 0, 0)
arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_VAL, 0, 0)
arg(metadataignore_ARG, '\0', "metadataignore", bool_VAL, 0, 0)
@@ -120,9 +118,7 @@ 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(swapmetadata_ARG, '\0', "swapmetadata", 0, 0, 0)
arg(syncaction_ARG, '\0', "syncaction", syncaction_VAL, 0, 0)
arg(sysinit_ARG, '\0', "sysinit", 0, 0, 0)
arg(systemid_ARG, '\0', "systemid", string_VAL, 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.
@@ -373,12 +367,6 @@ OP: PV ...
ID: lvconvert_split_mirror_images
DESC: Split images from a raid1 LV and track changes to origin.
lvconvert --mergemirrors LV_linear_raid|VG|Tag ...
OO: OO_LVCONVERT
ID: lvconvert_merge_mirror_images
DESC: Merge LV images that were split from a raid1 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
lvconvert --mirrorlog MirrorLog LV_mirror
OO: OO_LVCONVERT
OP: PV ...
@@ -394,8 +382,6 @@ lvconvert --type thin --thinpool LV LV_linear_striped_raid
OO: --thin, --originname LV_new, --zero Bool, OO_LVCONVERT_POOL, OO_LVCONVERT
ID: lvconvert_to_thin_with_external
DESC: Convert LV to type thin with an external origin.
RULE: all and lv_is_visible
RULE: all not lv_is_locked
# alternate form of lvconvert --type thin
lvconvert --thin --thinpool LV LV_linear_striped_raid
@@ -404,8 +390,6 @@ ID: lvconvert_to_thin_with_external
DESC: Convert LV to type thin with an external origin
DESC: (variant, infers --type thin).
FLAGS: SECONDARY_SYNTAX
RULE: all and lv_is_visible
RULE: all not lv_is_locked
---
@@ -414,7 +398,6 @@ OO: --cache, --cachemode CacheMode, --cachepolicy String,
--cachesettings String, --zero Bool, OO_LVCONVERT_POOL, OO_LVCONVERT
ID: lvconvert_to_cache_vol
DESC: Convert LV to type cache.
RULE: all and lv_is_visible
# alternate form of lvconvert --type cache
lvconvert --cache --cachepool LV LV_linear_striped_raid_thinpool
@@ -423,7 +406,6 @@ OO: --type cache, --cachemode CacheMode, --cachepolicy String,
ID: lvconvert_to_cache_vol
DESC: Convert LV to type cache (variant, infers --type cache).
FLAGS: SECONDARY_SYNTAX
RULE: all and lv_is_visible
---
@@ -433,18 +415,14 @@ OO: --stripes_long Number, --stripesize SizeKB,
OP: PV ...
ID: lvconvert_to_thinpool
DESC: Convert LV to type thin-pool.
RULE: all and lv_is_visible
RULE: all not lv_is_locked lv_is_origin lv_is_merging_origin lv_is_external_origin lv_is_virtual
# alternate form of lvconvert --type thin-pool
# deprecated because of non-standard syntax (missing positional arg)
# Commands in this form are converted to standard form so that
# the validation of LV types and rules specified above will apply.
lvconvert --thinpool LV_linear_striped_raid_cache
OO: --type thin-pool, --stripes_long Number, --stripesize SizeKB,
--discards Discards, --zero Bool, OO_LVCONVERT_POOL, OO_LVCONVERT
OP: PV ...
ID: lvconvert_to_thinpool_noarg
ID: lvconvert_to_thinpool
DESC: Convert LV to type thin-pool (variant, use --type thin-pool).
FLAGS: SECONDARY_SYNTAX
@@ -459,13 +437,10 @@ DESC: Convert LV to type cache-pool.
# alternate form of lvconvert --type cache-pool
# deprecated because of non-standard syntax (missing positional arg)
# Commands in this form are converted to standard form so that
# the validation of LV types and rules specified above will apply.
lvconvert --cachepool LV_linear_striped_raid
OO: --type cache-pool, OO_LVCONVERT_POOL, OO_LVCONVERT,
--cachemode CacheMode, --cachepolicy String, --cachesettings String
OP: PV ...
ID: lvconvert_to_cachepool_noarg
ID: lvconvert_to_cachepool
DESC: Convert LV to type cache-pool (variant, use --type cache-pool).
FLAGS: SECONDARY_SYNTAX
@@ -480,33 +455,52 @@ DESC: Separate and keep the cache pool from a cache LV.
lvconvert --uncache LV_cache_thinpool
OO: OO_LVCONVERT
ID: lvconvert_split_and_remove_cachepool
ID: lvconvert_split_and_delete_cachepool
DESC: Separate and delete the cache pool from a cache LV.
---
lvconvert --swapmetadata --poolmetadata LV LV_thinpool_cachepool
OO: --chunksize SizeKB, OO_LVCONVERT
# FIXME: add a new option defining this operation, e.g. --swapmetadata
lvconvert --poolmetadata LV LV_thinpool_cachepool
OO: OO_LVCONVERT
ID: lvconvert_swap_pool_metadata
DESC: Swap metadata LV in a thin pool or cache pool (for repair only).
DESC: Swap metadata LV in a thin pool or cache pool (temporary command).
FLAGS: SECONDARY_SYNTAX
---
# lvconvert --merge is an extremely ambiguous command.
# FIXME: lvconvert --merge is an extremely ambiguous command.
# It can do very different operations, but which one depends
# on knowing the LV type. So, the command doesn't know what
# it's actually doing until quite late, when processing a
# single LV. When passed a VG or tag, it will do different
# operations on each LV it finds, depending on the current LV type.
# single LV.
#
# Use different option names for different merge operations
# so that we can have different command definitions,
# different behaviors, different optional options, etc:
#
# lvconvert --merge-mirror LV_linear_striped_raid ...
# DESC: Merge LV that was previously split from a mirror.
#
# lvconvert --merge-thin LV_thin
# DESC: Merge thin LV into its origin LV.
#
# lvconvert --merge-snapshot LV_snapshot
# DESC: Merge COW snapshot LV into its origin.
#
# Then we could add VG|Tag to --merge-mirror arg pos 1, because
# "lvconvert --merge VG|Tag" is a terrible command. It will do
# different operations on each LV it finds, depending on the
# current LV type.
lvconvert --merge LV_linear_striped_raid_thin_snapshot|VG|Tag ...
OO: --background, --interval Number, OO_LVCONVERT
ID: lvconvert_merge
DESC: Merge LV that was split from a mirror (variant, use --mergemirrors).
DESC: Merge thin LV into its origin LV (variant, use --mergethin).
DESC: Merge COW snapshot LV into its origin (variant, use --mergesnapshot).
DESC: Merge LV that was previously split from a mirror.
DESC: Merge thin LV into its origin LV.
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
FLAGS: SECONDARY_SYNTAX
---
@@ -516,7 +510,7 @@ FLAGS: SECONDARY_SYNTAX
lvconvert --mergesnapshot LV_snapshot ...
OO: --background, --interval Number, OO_LVCONVERT
ID: lvconvert_merge_snapshot
DESC: Merge COW snapshot LV into its origin.
DESC: Merge LV that was previously split from a mirror.
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
---
@@ -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
---
@@ -873,14 +850,6 @@ DESC: (infers --type thin).
---
lvconvert --mergethin LV_thin ...
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
---
# stripes option is not intuitive when creating a thin LV,
# but here it applies to creating the new thin pool that
# is used for the thin LV

View File

@@ -47,7 +47,7 @@ xx(lvchange,
xx(lvconvert,
"Change logical volume layout",
GET_VGNAME_FROM_OPTIONS)
0)
xx(lvcreate,
"Create a logical volume",

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)

File diff suppressed because it is too large Load Diff

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,38 +131,33 @@ 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 },
/* lvconvert utilities for creating/maintaining thin and cache objects. */
{ lvconvert_to_thinpool_CMD, lvconvert_to_pool_cmd },
{ lvconvert_to_thinpool_noarg_CMD, lvconvert_to_pool_noarg_cmd },
{ lvconvert_to_cachepool_CMD, lvconvert_to_pool_cmd },
{ lvconvert_to_cachepool_noarg_CMD, lvconvert_to_pool_noarg_cmd },
{ lvconvert_to_thin_with_external_CMD, lvconvert_to_thin_with_external_cmd },
{ lvconvert_to_cache_vol_CMD, lvconvert_to_cache_vol_cmd },
{ lvconvert_swap_pool_metadata_CMD, lvconvert_swap_pool_metadata_cmd },
{ lvconvert_merge_thin_CMD, lvconvert_merge_thin_cmd },
{ lvconvert_split_and_keep_cachepool_CMD, lvconvert_split_cachepool_cmd },
{ lvconvert_split_and_remove_cachepool_CMD, lvconvert_split_cachepool_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_change_mirrorlog_CMD, lvconvert_change_mirrorlog_cmd },
#endif
/* 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
};
{ lvconvert_raid_types_CMD, lvconvert_raid_types_fn },
/* raid-related utilities (move into lvconvert_raid_types?) */
{ lvconvert_split_mirror_images_CMD, lvconvert_split_mirror_images_fn },
{ lvconvert_change_mirrorlog_CMD, lvconvert_change_mirrorlog_fn },
/* utilities for creating/maintaining thin and cache objects. */
{ lvconvert_to_thin_with_external_CMD, lvconvert_to_thin_with_external_fn },
{ lvconvert_to_cache_vol_CMD, lvconvert_to_cache_vol_fn },
{ lvconvert_to_thinpool_CMD, lvconvert_to_thinpool_fn },
{ lvconvert_to_cachepool_CMD, lvconvert_to_cachepool_fn },
{ lvconvert_split_and_keep_cachepool_CMD, lvconvert_split_and_keep_cachepool_fn },
{ lvconvert_split_and_delete_cachepool_CMD, lvconvert_split_and_delete_cachepool_fn },
{ lvconvert_swap_pool_metadata_CMD, lvconvert_swap_pool_metadata_fn },
/* other misc. */
{ lvconvert_merge_CMD, lvconvert_merge_fn },
{ lvconvert_poll_start_CMD, lvconvert_poll_start_fn },
#endif
/* Command line args */
unsigned arg_count(const struct cmd_context *cmd, int a)
@@ -1131,18 +1126,6 @@ struct lv_types *get_lv_type(int lvt_enum)
return &_lv_types[lvt_enum];
}
struct command *get_command(int cmd_enum)
{
int i;
for (i = 0; i < COMMAND_COUNT; i++) {
if (commands[i].command_line_enum == cmd_enum)
return &commands[i];
}
return NULL;
}
/*
* Also see merge_synonym(). The command definitions
* are written using just one variation of the option

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

@@ -2498,9 +2498,9 @@ static int _lv_is_type(struct cmd_context *cmd, struct logical_volume *lv, int l
switch (lvt_enum) {
case striped_LVT:
return seg_is_striped(seg) && !lv_is_cow(lv);
return seg_is_striped(seg);
case linear_LVT:
return seg_is_linear(seg) && !lv_is_cow(lv);
return seg_is_linear(seg);
case snapshot_LVT:
return lv_is_cow(lv);
case thin_LVT:
@@ -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);
}
@@ -2540,21 +2536,16 @@ static int _lv_is_type(struct cmd_context *cmd, struct logical_volume *lv, int l
return 0;
}
int get_lvt_enum(struct logical_volume *lv)
static int _get_lvt_enum(struct logical_volume *lv)
{
struct lv_segment *seg = first_seg(lv);
/*
* The order these are checked is important, because a snapshot LV has
* a linear seg type.
*/
if (lv_is_cow(lv))
return snapshot_LVT;
if (seg_is_linear(seg))
return linear_LVT;
if (seg_is_striped(seg))
return striped_LVT;
if (seg_is_linear(seg))
return linear_LVT;
if (lv_is_cow(lv))
return snapshot_LVT;
if (lv_is_thin_volume(lv))
return thin_LVT;
if (lv_is_thin_pool(lv))
@@ -2582,11 +2573,7 @@ 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;
}
@@ -2682,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;
@@ -2724,7 +2717,7 @@ static int _check_lv_rules(struct cmd_context *cmd, struct logical_volume *lv)
int ret = 1;
int i;
lvt_enum = get_lvt_enum(lv);
lvt_enum = _get_lvt_enum(lv);
if (lvt_enum)
lvtype = get_lv_type(lvt_enum);
@@ -2868,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();
@@ -2935,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;
@@ -3098,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;
}
@@ -3365,164 +3304,12 @@ static int _get_arg_lvnames(struct cmd_context *cmd,
return ret_max;
}
/*
* This is a non-standard way of finding vgname/lvname to process. It exists
* because an earlier form of lvconvert did not follow the standard form, and
* came up with its own inconsistent approach.
*
* In this case, when the position arg is a single name, it is treated as an LV
* name (not a VG name). This leaves the VG unknown. So, other option values
* must be searched for a VG name. If one of those option values contains a
* vgname/lvname value, then the VG name is extracted and used for the LV
* position arg.
*
* Other option values that are searched for a VG name are:
* --thinpool, --cachepool.
*
* . command vg/lv1
* . add vg to arg_vgnames
* . add vg/lv1 to arg_lvnames
*
* command lv1
* . error: no vg name
*
* command --option vg/lv1 vg/lv2
* . verify both vg names match
* . add vg to arg_vgnames
* . add vg/lv2 to arg_lvnames
*
* command --option lv1 lv2
* . error: no vg name
*
* command --option vg/lv1 lv2
* . add vg to arg_vgnames
* . add vg/lv2 to arg_lvnames
*
* command --option lv1 vg/lv2
* . add vg to arg_vgnames
* . add vg/lv2 to arg_lvnames
*/
static int _get_arg_lvnames_using_options(struct cmd_context *cmd,
int argc, char **argv,
struct dm_list *arg_vgnames,
struct dm_list *arg_lvnames,
struct dm_list *arg_tags)
{
const char *pos_name = NULL;
const char *arg_name = NULL;
const char *pos_vgname = NULL;
const char *opt_vgname = NULL;
const char *pos_lvname = NULL;
const char *use_vgname = NULL;
char *tmp_name;
char *split;
char *vglv;
size_t vglv_sz;
if (argc != 1) {
log_error("One LV position arg is required.");
return ECMD_FAILED;
}
if (!(pos_name = dm_pool_strdup(cmd->mem, argv[0]))) {
log_error("string alloc failed.");
return ECMD_FAILED;
}
if (*pos_name == '@') {
if (!validate_tag(pos_name + 1)) {
log_error("Skipping invalid tag %s.", pos_name);
return ECMD_FAILED;
}
if (!str_list_add(cmd->mem, arg_tags,
dm_pool_strdup(cmd->mem, pos_name + 1))) {
log_error("strlist allocation failed.");
return ECMD_FAILED;
}
return ECMD_PROCESSED;
}
if ((split = strchr(pos_name, '/'))) {
pos_vgname = pos_name;
pos_lvname = split + 1;
*split = '\0';
} else {
pos_lvname = pos_name;
pos_vgname = NULL;
}
if (arg_is_set(cmd, thinpool_ARG))
arg_name = arg_str_value(cmd, thinpool_ARG, NULL);
else if (arg_is_set(cmd, cachepool_ARG))
arg_name = arg_str_value(cmd, cachepool_ARG, NULL);
if (!pos_vgname && !arg_name) {
log_error("Cannot find VG name for LV %s.", pos_lvname);
return ECMD_FAILED;
}
if (arg_name && (split = strchr(arg_name, '/'))) {
/* combined VG/LV */
if (!(tmp_name = dm_pool_strdup(cmd->mem, arg_name))) {
log_error("string alloc failed.");
return ECMD_FAILED;
}
if (!(split = strchr(tmp_name, '/')))
return ECMD_FAILED;
opt_vgname = tmp_name;
/* Don't care about opt lvname. */
/* opt_lvname = split + 1; */
*split = '\0';
} else {
/* Don't care about opt lvname. */
/* opt_lvname = arg_name; */
opt_vgname = NULL;
}
if (!pos_vgname && !opt_vgname) {
log_error("Cannot find VG name for LV %s.", pos_lvname);
return ECMD_FAILED;
}
if (pos_vgname && opt_vgname && strcmp(pos_vgname, opt_vgname)) {
log_error("VG name mismatch from position arg (%s) and option arg (%s).",
pos_vgname, opt_vgname);
return ECMD_FAILED;
}
use_vgname = pos_vgname ? pos_vgname : opt_vgname;
if (!str_list_add(cmd->mem, arg_vgnames, dm_pool_strdup(cmd->mem, use_vgname))) {
log_error("strlist allocation failed.");
return ECMD_FAILED;
}
vglv_sz = strlen(use_vgname) + strlen(pos_lvname) + 2;
if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) ||
dm_snprintf(vglv, vglv_sz, "%s/%s", use_vgname, pos_lvname) < 0) {
log_error("vg/lv string alloc failed.");
return ECMD_FAILED;
}
if (!str_list_add(cmd->mem, arg_lvnames, vglv)) {
log_error("strlist allocation failed.");
return ECMD_FAILED;
}
return ECMD_PROCESSED;
}
static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t read_flags,
struct dm_list *vgnameids_to_process,
struct dm_list *arg_vgnames,
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();
@@ -3615,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);
@@ -3646,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();
@@ -3675,12 +3461,7 @@ int process_each_lv(struct cmd_context *cmd,
/*
* Find any LVs, VGs or tags explicitly provided on the command line.
*/
if (cmd->command->flags & GET_VGNAME_FROM_OPTIONS)
ret = _get_arg_lvnames_using_options(cmd, argc, argv, &arg_vgnames, &arg_lvnames, &arg_tags);
else
ret = _get_arg_lvnames(cmd, argc, argv, one_vgname, one_lvname, &arg_vgnames, &arg_lvnames, &arg_tags);
if (ret != ECMD_PROCESSED) {
if ((ret = _get_arg_lvnames(cmd, argc, argv, one_vgname, one_lvname, &arg_vgnames, &arg_lvnames, &arg_tags) != ECMD_PROCESSED)) {
ret_max = ret;
goto_out;
}
@@ -3767,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);
@@ -240,6 +226,4 @@ int validate_restricted_lvname_param(struct cmd_context *cmd, const char **vg_na
int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
struct processing_handle *handle __attribute__((unused)));
int get_lvt_enum(struct logical_volume *lv);
#endif

View File

@@ -162,8 +162,6 @@ struct lv_types {
#define ENABLE_DUPLICATE_DEVS 0x00000400
/* Command does not accept tags as args. */
#define DISALLOW_TAG_ARGS 0x00000800
/* Command may need to find VG name in an option value. */
#define GET_VGNAME_FROM_OPTIONS 0x00001000
void usage(const char *name);
@@ -242,7 +240,6 @@ int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg
struct lv_props *get_lv_prop(int lvp_enum);
struct lv_types *get_lv_type(int lvt_enum);
struct command *get_command(int cmd_enum);
int lvchange_properties_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvchange_activate_cmd(struct cmd_context *cmd, int argc, char **argv);
@@ -260,18 +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);
int lvconvert_to_pool_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvconvert_to_pool_noarg_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvconvert_to_cache_vol_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvconvert_to_thin_with_external_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvconvert_swap_pool_metadata_cmd(struct cmd_context *cmd, int argc, char **argv);
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_merge_mirror_images_cmd(struct cmd_context *cmd, int argc, char **argv);
int lvconvert_merge_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;
}