1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-10-08 19:33:19 +03:00

Compare commits

..

1 Commits

Author SHA1 Message Date
David Teigland
4e80c29bf3 commands: new method for defining commands
. Define a prototype for every lvm command.
. Verify every user command matches one.
. 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, --test, --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,
--test
ID: lvresize_by_pv
DESC: Resize an LV by a specified PV.

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

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

$ lvresize --help
  lvresize - Resize a logical volume

  Resize an LV by a specified size.
  lvresize --size Number[m|unit] LV
  	[ --alloc contiguous|cling|normal|anywhere|inherit,
	  --autobackup y|n,
	  --nofsck,
	  --nosync,
	  --reportformat String,
	  --resizefs,
	  --stripes Number,
	  --stripesize Number[k|unit],
	  --poolmetadatasize Number[m|unit] ]
  	[ PV ... ]

  Resize an LV by a specified PV.
  lvresize LV PV ...
  	[ --alloc contiguous|cling|normal|anywhere|inherit,
	  --autobackup y|n,
	  --nofsck,
	  --nosync,
	  --reportformat String,
	  --resizefs,
	  --stripes Number,
	  --stripesize Number[k|unit] ]

  Resize the metadata SubLV of a pool LV.
  lvresize --poolmetadatasize Number[m|unit] LV_thinpool
  	[ --alloc contiguous|cling|normal|anywhere|inherit,
	  --autobackup y|n,
	  --nofsck,
	  --nosync,
	  --reportformat String,
	  --stripes Number,
	  --stripesize Number[k|unit] ]
  	[ PV ... ]

  Common options:
  	[ --commandprofile String,
	  --config String,
	  --debug,
	  --driverloaded y|n,
	  --help,
	  --profile String,
	  --quiet,
	  --verbose,
	  --version,
	  --yes,
	  --force,
	  --test,
	  --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

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 implementation.

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-10-19 13:37:22 -05:00
8 changed files with 9188 additions and 611 deletions

View File

@@ -113,16 +113,8 @@
# could use differnet IDs, in which case the implementation would
# know where to look for each parameter.
#
# DESC: A description of the command. The "DESC:" tags will be
# included in the text as indicators of new lines when printing
# the descriptions for help/man output.
# DESC: A description of the command.
#
# Note that one the most difficult aspect of these definitions is
# the variants of --thin / --type thin / --type thin-pool,
# --cache / --type cache / --type cache-pool.
# There are no consistent rules to follow and the behaviors are
# unpredictable; each possible variation and combination needs
# to be tested individually to see what it means.
#
# For efficiency, sets of options can be defined and reused
@@ -210,20 +202,17 @@ OO: OO_LVCHANGE
ID: lvchange_properties
DESC: Change a general LV property.
lvchange --resync VG|LV_raid_mirror|Tag|Select ...
lvchange --resync VG|LV|Tag|Select ...
OO: OO_LVCHANGE
ID: lvchange_resync
DESC: Resyncronize a mirror or raid LV.
lvchange --syncaction String VG|LV_raid|Tag|Select ...
lvchange --syncaction String VG|LV|Tag|Select ...
OO: OO_LVCHANGE
ID: lvchange_syncaction
DESC: Resynchronize or check a raid LV.
lvchange --rebuild PV VG|LV_raid|Tag|Select ...
lvchange --rebuild PV VG|LV|Tag|Select ...
OO: OO_LVCHANGE
ID: lvchange_rebuild
DESC: Reconstruct data on specific PVs of a raid LV.
lvchange --activate Active VG|LV|Tag|Select ...
OO: --activationmode ActivationMode, --partial, --ignoreactivationskip, OO_LVCHANGE_META, OO_LVCHANGE
@@ -231,24 +220,21 @@ ID: lvchange_activate
DESC: Activate or deactivate an LV.
lvchange --refresh VG|LV|Tag|Select ...
OO: --partial, OO_LVCHANGE
OO: OO_LVCHANGE
ID: lvchange_refresh
DESC: Reactivate an LV using the latest metadata.
lvchange --monitor Bool VG|LV|Tag|Select ...
OO: --poll Bool, OO_LVCHANGE
ID: lvchange_monitor
DESC: Start or stop monitoring an LV from dmeventd.
DESC: Monitor or unmonitor an LV.
lvchange --poll Bool VG|LV|Tag|Select ...
OO: --monitor Bool, OO_LVCHANGE
ID: lvchange_poll
DESC: Start or stop processing an LV conversion.
lvchange --persistent Bool VG|LV|Tag|Select ...
OO: --minor Number, --major Number, OO_LVCHANGE
ID: lvchange_persistent
DESC: Make the minor device number persistent for an LV.
---
@@ -288,7 +274,7 @@ OO_LVCONVERT: --alloc Alloc, --background, --force, --noudevsync,
# current LV type.
lvconvert --merge LV_linear_striped_raid_thin_snapshot|VG|Tag ...
OO: --background, --interval Number, OO_LVCONVERT
OO: --background, --interval Number
ID: lvconvert_merge
DESC: Merge LV that was previously split from a mirror.
DESC: Merge thin LV into its origin LV.
@@ -302,13 +288,13 @@ DESC: Merge COW snapshot LV into its origin.
# and adjusts argv/argc so it's not seen by process_each.
lvconvert --type snapshot LV_linear_striped_raid LV_snapshot
OO: --snapshot, --chunksize SizeKB, --zero Bool, OO_LVCONVERT
OO: --chunksize SizeKB, --zero Bool, OO_LVCONVERT
ID: lvconvert_combine_split_snapshot
DESC: Combine LV with a previously split snapshot LV.
# alternate form of lvconvert --type snapshot
lvconvert --snapshot LV_linear_striped_raid LV_snapshot
OO: --type snapshot, --chunksize SizeKB, --zero Bool, OO_LVCONVERT
OO: --chunksize SizeKB, --zero Bool, OO_LVCONVERT
ID: lvconvert_combine_split_snapshot
DESC: Combine LV with a previously split snapshot LV
DESC: (variant, infers --type snapshot).
@@ -363,7 +349,7 @@ DESC: Convert LV to type thin-pool.
# alternate form of lvconvert --type thin-pool
# deprecated because of non-standard syntax (missing positional arg)
lvconvert --thinpool LV_linear_striped_raid_cache
OO: --type thin-pool, --stripes_long Number, --stripesize SizeKB,
OO: --stripes_long Number, --stripesize SizeKB,
--discards Discards, --zero Bool, OO_LVCONVERT_POOL, OO_LVCONVERT
ID: lvconvert_to_thinpool
DESC: Convert LV to type thin-pool (variant, use --type thin-pool).
@@ -394,12 +380,6 @@ DESC: Convert LV to type cache-pool (variant, use --type cache-pool).
# LV types, but there are some dubious commands in the test suite that
# fail without it (the tests should be cleaned up to avoid using commands
# that don't make sense.)
#
# FIXME: it would be nice to remove LV_raid1 from the list of accepted
# LV types and let raid1 be covered by just the second definition, but
# unfortunatley lvconvert --type mirror --mirrors N LV_raid1 will
# match the first definition since the LV type cannot be used when
# choosing a matching command definition.
lvconvert --type mirror --mirrors SNumber LV_linear_striped_raid1_mirror
OO: --mirrorlog MirrorLog, OO_LVCONVERT_RAID, OO_LVCONVERT
@@ -407,12 +387,6 @@ OP: PV ...
ID: lvconvert_to_mirror
DESC: Convert LV to type mirror.
lvconvert --type mirror LV_raid1
OO: --mirrors SNumber, OO_LVCONVERT_RAID, OO_LVCONVERT
OP: PV ...
ID: lvconvert_to_mirror
DESC: Convert LV from type raid1 to type mirror.
---
# FIXME: by using specific raid levels, e.g. raid1, we could
@@ -420,7 +394,7 @@ DESC: Convert LV from type raid1 to type mirror.
# help the second fixme...
#
# FIXME: there are two different operations here, and it would
# be nice to split them into two unambiguous command lines:
# be nice to split them into to unambiguous command lines:
#
# 1. lvconvert --type raid LV_linear_striped_mirror
# DESC: Convert LV to type raid.
@@ -433,7 +407,7 @@ OO: OO_LVCONVERT_RAID, OO_LVCONVERT
OP: PV ...
ID: lvconvert_general_to_raid
DESC: Convert LV to type raid.
DESC: Change LV between raid types.
DESC: Change LV raid type.
---
@@ -482,13 +456,12 @@ OO: OO_LVCONVERT
ID: lvconvert_raid_or_mirror_to_linear
DESC: Convert LV to type linear.
# FIXME: the 'mirrors 0' trick as an alias for linear
# is used inconsistently, confusing things and making
# definitions difficult.
# FIXME: this is another trick that gets mixed up with
# the already overloaded lvconvert --mirrors definition.
# alternate form of lvconvert --type linear
lvconvert --mirrors 0 LV_raid_mirror
OO: --type linear, --type mirror, OO_LVCONVERT
OO: --type linear, OO_LVCONVERT
ID: lvconvert_raid_or_mirror_to_linear
DESC: Convert LV to type linear (variant, infers --type linear).
@@ -542,21 +515,21 @@ lvconvert --mirrorlog MirrorLog LV_mirror
OO: OO_LVCONVERT
OP: PV ...
ID: lvconvert_change_mirrorlog
DESC: Change the type of mirror log used by a mirror LV.
DESC: Change the type of log used by LV.
---
lvconvert --splitcache LV_cachepool_cache_thinpool
OO: OO_LVCONVERT
ID: lvconvert_split_and_keep_cachepool
DESC: Separate and keep the cache pool from a cache LV.
DESC: Separate and preserve a cache pool from a cache LV.
---
lvconvert --uncache LV_cache_thinpool
OO: OO_LVCONVERT
ID: lvconvert_split_and_delete_cachepool
DESC: Separate and delete the cache pool from a cache LV.
DESC: Separate and remove a cache pool from a cache LV.
---
@@ -571,16 +544,14 @@ DESC: Separate a COW snapshot from its origin LV.
# The purpose of this command is not entirely clear.
lvconvert LV_mirror
OO: OO_LVCONVERT
ID: lvconvert_poll_mirror
DESC: Poll mirror LV to collapse resync layers.
DESC: Poll LV to collapse resync layers.
---
# 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 (temporary command).
@@ -602,7 +573,8 @@ OO_LVCREATE_POOL: --poolmetadatasize SizeMB, --poolmetadataspare Bool, --chunksi
# FIXME: it's silly to include --mirrors 0 here. Fix the tests to not use
# --mirrors 0 in commands that do not accept any non-zero --mirrors
# option, and then remove this. Accepting an option, only so that the
# option's value can invalidate the use of the option is not advisable.
# option's value can invalidate the use of the option is not general
# practice.
OO_LVCREATE_THIN: --discards Discards, --errorwhenfull Bool, --mirrors 0
@@ -627,9 +599,7 @@ DESC: Create an LV that returns zeros when read.
# FIXME: consider removing the --mirrors 0, --stripes 1 options
# and just reporting an error (or ignoring) if mirrors or stripes
# options are given. Same reasoning as above: it's confusing to
# advertise an option when the only value accepted for the option
# makes the option do nothing.
# options are given.
lvcreate --type linear --size SizeMB VG
OO: --mirrors 0, --stripes 1, OO_LVCREATE
@@ -637,15 +607,11 @@ OP: PV ...
ID: lvcreate_linear
DESC: Create a linear LV.
# This is the one place we mention the optional --name
# because it's the most common case and may be confusing
# to people to not see the name parameter.
lvcreate --size SizeMB VG
OO: --type linear, --mirrors 0, --stripes 1, OO_LVCREATE
OP: PV ...
ID: lvcreate_linear
DESC: Create a linear LV (default --type linear).
DESC: Create a linear LV (default --type linear).
DESC: When --name is omitted, the name is generated.
---
@@ -668,21 +634,17 @@ lvcreate --type mirror --size SizeMB VG
OO: --mirrors SNumber, --mirrorlog MirrorLog, --regionsize SizeMB, --stripes Number, OO_LVCREATE
OP: PV ...
ID: lvcreate_mirror
DESC: Create a mirror LV (also see --type raid1).
DESC: Create a mirror LV.
# alternate form of lvcreate --type raid1|mirror
lvcreate --mirrors SNumber --size SizeMB VG
OO: --type raid1, --type mirror, --mirrorlog MirrorLog, --stripes Number, OO_LVCREATE_RAID, OO_LVCREATE
OP: PV ...
ID: lvcreate_mirror_or_raid1
ID: lvcreate_mirror
DESC: Create a raid1 or mirror LV (variant, infers --type raid1|mirror).
---
# FIXME: we should probably expand this from raid* to
# various specific raid levels, then narrow the range
# of options applicable to each.
lvcreate --type raid --size SizeMB VG
OO: OO_LVCREATE_RAID, OO_LVCREATE
OP: PV ...
@@ -695,16 +657,9 @@ DESC: Create a raid LV (a specific raid level must be used, e.g. raid1.)
# not snapshot as specified by the command. If LVs never have type
# snapshot, perhaps "snapshot" should not be considered an LV type, but
# another new LV property?
#
# Or, perhaps we should not promote --type snapshot, and
# prefer --snapshot as the primary syntax, since the type
# is not really snapshot (which makes it different from
# all the other cases of using --type, where the resulting
# LV does have the specified type.)
lvcreate --type snapshot --size SizeMB LV
OO: --snapshot, --stripes Number, --stripesize SizeKB,
--chunksize SizeKB, OO_LVCREATE
OO: --snapshot, --chunksize SizeKB, OO_LVCREATE
OP: PV ...
ID: lvcreate_cow_snapshot
DESC: Create a COW snapshot LV from an origin LV.
@@ -718,6 +673,28 @@ ID: lvcreate_cow_snapshot
DESC: Create a COW snapshot LV from an origin LV
DESC: (infers --type snapshot).
# If this snapshot+striped command was merged with lvcreate_cow_snapshot
# by adding --stripes in OO, then this command would be difficult to
# distiguish from lvcreate_striped based on required options. But, it may
# work if command matching used optional options to score matches rather
# than only using required options.
lvcreate --type snapshot --stripes Number --size SizeMB LV
OO: --snapshot, --stripes Number, --stripesize SizeKB,
--chunksize SizeKB, OO_LVCREATE
OP: PV ...
ID: lvcreate_striped_cow_snapshot
DESC: Create a striped COW snapshot LV from an origin LV.
# alternate form of lvcreate --type snapshot --stripes
lvcreate --snapshot --stripes Number --size SizeMB LV
OO: --type snapshot, --stripes Number, --stripesize SizeKB,
--chunksize SizeKB, OO_LVCREATE
OP: PV ...
ID: lvcreate_striped_cow_snapshot
DESC: Create a striped COW snapshot LV from an origin LV
DESC: (infers --type snapshot).
---
lvcreate --type snapshot --size SizeMB --virtualsize SizeMB VG
@@ -762,20 +739,22 @@ DESC: (variant, infers --type thin-pool).
---
# NB. there are no alternate forms of these commands that
# use --cache in place of --type cache-pool, but --cache
# still needs to be listed as an optional addition to
# --type cache-pool.
lvcreate --type cache-pool --size SizeMB VG
OO: --cache, OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE
OO: OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE
OP: PV ...
ID: lvcreate_cachepool
DESC: Create a cache pool.
# alternate form of lvcreate --type cache-pool
lvcreate --cache --size SizeMB VG
OO: --type cache-pool, OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE
OP: PV ...
ID: lvcreate_cachepool
DESC: Create a cache pool (variant, infers --type cache-pool).
# alternate form of lvcreate --type cache-pool
lvcreate --type cache-pool --size SizeMB --cachepool LV_new VG
OO: --cache, OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE
OO: OO_LVCREATE_POOL, OO_LVCREATE_CACHE, OO_LVCREATE
OP: PV ...
ID: lvcreate_cachepool
DESC: Create a cache pool named by the --cachepool arg
@@ -783,8 +762,9 @@ DESC: (variant, uses --cachepool in place of --name).
---
lvcreate --type thin --virtualsize SizeMB --thinpool LV_thinpool VG
lvcreate --type thin --virtualsize SizeMB --thinpool LV_thinpool
OO: --thin, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
OP: VG
ID: lvcreate_thin_vol
DESC: Create a thin LV in a thin pool.
@@ -792,15 +772,13 @@ DESC: Create a thin LV in a thin pool.
lvcreate --type thin --virtualsize SizeMB LV_thinpool
OO: --thin, OO_LVCREATE_THIN, OO_LVCREATE
ID: lvcreate_thin_vol
DESC: Create a thin LV in a thin pool named in the first arg
DESC: (variant, also see --thinpool for naming pool).
# NB. this is the variant which can substitute
# --thin for --type thin, even though --thin is in OO.
DESC: Create a thin LV in a thin pool named in arg pos 1
DESC: (variant, also see --thinpool).
# alternate form of lvcreate --type thin
lvcreate --virtualsize SizeMB --thinpool LV_thinpool VG
lvcreate --virtualsize SizeMB --thinpool LV_thinpool
OO: --type thin, --thin, OO_LVCREATE_THIN, OO_LVCREATE
OP: VG
ID: lvcreate_thin_vol
DESC: Create a thin LV in a thin pool (variant, infers --type thin).
@@ -808,12 +786,17 @@ DESC: Create a thin LV in a thin pool (variant, infers --type thin).
lvcreate --virtualsize SizeMB LV_thinpool
OO: --type thin, --thin, OO_LVCREATE_THIN, OO_LVCREATE
ID: lvcreate_thin_vol
DESC: Create a thin LV in the thin pool named in the first arg
DESC: (variant, infers --type thin, also see --thinpool for
DESC: naming pool.)
DESC: Create a thin LV in the thin pool named in arg pos 1
DESC: (variant, infers --type thin, also see --thinpool).
---
# FIXME: in addition to confusing and unpredictable,
# this jumble of variations of the same thing is inconsistent:
# lvcreate --thin LV_thin and lvcreate --snapshot LV_thin
# are the same command, both creating a thin snapshot,
# but lvcreate --thin --snapshot LV_thin does not.
lvcreate --type thin LV_thin
OO: --thin, OO_LVCREATE_THIN, OO_LVCREATE
ID: lvcreate_thin_snapshot
@@ -826,7 +809,7 @@ ID: lvcreate_thin_snapshot
DESC: Create a thin LV that is a snapshot of an existing thin LV
DESC: (infers --type thin).
# alternate form of lvcreate --type thin
# alternate form of lvcreate --type thin LV_thin
lvcreate --snapshot LV_thin
OO: --type thin, OO_LVCREATE_THIN, OO_LVCREATE
ID: lvcreate_thin_snapshot
@@ -834,7 +817,7 @@ DESC: Create a thin LV that is a snapshot of an existing thin LV
DESC: (infers --type thin).
lvcreate --type thin --thinpool LV_thinpool LV
OO: --thin, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE
ID: lvcreate_thin_snapshot_of_external
DESC: Create a thin LV that is a snapshot of an external origin LV.
@@ -851,23 +834,11 @@ DESC: (infers --type thin).
# but here it applies to creating the new thin pool that
# is used for the thin LV
# FIXME: there are commands here that differ only in that
# one takes LV_new in arg pos 1, and the other takes a VG name
# in arg pos 1. The commands that take LV_new use that
# name as the new name of the pool, but the commands that
# take a VG automatically generate the LV name. The problem
# is that currently the command matching function cannot
# distinguish between an LV name and a VG name being used
# in arg pos 1, so a user-entered command would just match
# the first it finds and not necessarily the correct
# definition. Note that when LV_new is used in arg pos 1,
# it needs to include a VG name, i.e. VG/LV_new
lvcreate --type thin --virtualsize SizeMB --size SizeMB --thinpool LV_new
OO: --thin, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE,
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE,
--stripes Number, --stripesize SizeKB
OP: PV ...
ID: lvcreate_thin_vol_and_thinpool
ID: lvcreate_thin_vol_with_thinpool
DESC: Create a thin LV, first creating a thin pool for it,
DESC: where the new thin pool is named by the --thinpool arg.
@@ -876,32 +847,34 @@ lvcreate --thin --virtualsize SizeMB --size SizeMB --thinpool LV_new
OO: --type thin, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE,
--stripes Number, --stripesize SizeKB
OP: PV ...
ID: lvcreate_thin_vol_and_thinpool
ID: lvcreate_thin_vol_with_thinpool
DESC: Create a thin LV, first creating a thin pool for it,
DESC: where the new thin pool is named by the --thinpool arg
DESC: where the new thin pool is named by the --thinpool arg,
DESC: (variant, infers --type thin).
# alternate form of lvcreate --type thin
lvcreate --type thin --virtualsize SizeMB --size SizeMB LV_new|VG
OO: --thin, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE,
lvcreate --type thin --virtualsize SizeMB --size SizeMB LV_new
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE,
--stripes Number, --stripesize SizeKB
OP: PV ...
ID: lvcreate_thin_vol_and_thinpool
ID: lvcreate_thin_vol_with_thinpool
DESC: Create a thin LV, first creating a thin pool for it,
DESC: where the new thin pool is named in the first arg,
DESC: or the new thin pool name is generated when the first
DESC: arg is a VG name.
DESC: where the new thin pool is named in arg pos 1.
# alternate form of lvcreate --type thin
lvcreate --thin --virtualsize SizeMB --size SizeMB LV_new|VG
lvcreate --thin --virtualsize SizeMB --size SizeMB LV_new
OO: --type thin, OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE,
--stripes Number, --stripesize SizeKB
OP: PV ...
ID: lvcreate_thin_vol_and_thinpool
ID: lvcreate_thin_vol_with_thinpool
DESC: Create a thin LV, first creating a thin pool for it,
DESC: where the new thin pool is named in the first arg,
DESC: or the new thin pool name is generated when the first
DESC: arg is a VG name (variant, infers --type thin).
DESC: where the new thin pool is named in arg pos 1,
DESC: (variant, infers --type thin).
lvcreate --type thin --virtualsize SizeMB --size SizeMB VG
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE,
--stripes Number, --stripesize SizeKB
OP: PV ...
ID: lvcreate_thin_vol_with_thinpool
DESC: Create a thin LV, first creating a thin pool for it.
---
@@ -914,8 +887,8 @@ DESC: Create a thin LV, first creating a thin pool for it
DESC: (infers --type thin).
DESC: Create a sparse snapshot of a virtual origin LV
DESC: (infers --type snapshot).
DESC: Chooses --type thin or --type snapshot according to
DESC: config setting sparse_segtype_default.
DESC: Infers --type thin or --type snapshot according to
DESC: confing setting sparse_segtype_default.
---
@@ -950,7 +923,7 @@ OP: PV ...
ID: lvcreate_cache_vol_with_new_origin
DESC: Create a cache LV, first creating a new origin LV,
DESC: then combining it with the existing cache pool named
DESC: in the first arg (variant, also use --cachepool).
DESC: by in arg pos 1 (variant, also use --cachepool).
# This is a ridiculously crazy command which nobody could
# understand. It should be be eliminated. It does two different
@@ -958,7 +931,7 @@ DESC: in the first arg (variant, also use --cachepool).
# or not. Both variations are unnecessary.
#
# 1. If LV is a cachepool, then it's an alternate form of
# an already complicated command above.
# an already crazy command above:
#
# # alternate form for lvcreate_cache_vol_with_new_origin
# lvcreate --cache --size SizeMB LV_cachepool
@@ -967,10 +940,10 @@ DESC: in the first arg (variant, also use --cachepool).
# ID: lvcreate_cache_vol_with_new_origin
# DESC: Create a cache LV, first creating a new origin LV,
# DESC: then combining it with the existing cache pool named
# DESC: in the first arg (variant, infers --type cache,
# DESC: in arg pos 1 (variant, infers --type cache,
# DESC: also use --cachepool).
#
# 2. If LV is not a cachepool, then it's a disguised lvconvert.
# If LV is not a cachepool, then it's a disguised lvconvert:
#
# # FIXME: this should be done by lvconvert, and this command removed
# lvcreate --type cache --size SizeMB LV
@@ -985,19 +958,17 @@ DESC: in the first arg (variant, also use --cachepool).
# the LV type is known.
#
# So, to define this syntax we have to combine both of
# those variants, each crazy on it's own, into one
# ridiculous command.
# those variants, each crazy on it's own, into one.
# def1: alternate form of lvcreate --type cache, or
# def2: it should be done by lvconvert.
# def2: FIXME: it should be done by lvconvert.
lvcreate --cache --size SizeMB LV
OO: OO_LVCREATE_CACHE, OO_LVCREATE_POOL, OO_LVCREATE,
--stripes Number, --stripesize SizeKB
OO: OO_LVCREATE_CACHE, OO_LVCREATE, --stripes Number, --stripesize SizeKB
OP: PV ...
ID: lvcreate_cache_vol_with_new_origin_or_convert_to_cache_vol_with_cachepool
DESC: When LV is a cache pool, create a cache LV,
DESC: first creating a new origin LV, then combining it with
DESC: the existing cache pool named in the first arg
DESC: the existing cache pool named in arg pos 1
DESC: (variant, infers --type cache, also use --cachepool).
DESC: When LV is not a cache pool, convert the specified LV
DESC: to type cache after creating a new cache pool LV to use
@@ -1025,7 +996,6 @@ OO: --alloc Alloc, --autobackup Bool, --force, --mirrors SNumber,
--stripes Number, --stripesize SizeKB, --test, --poolmetadatasize SizeMB
OP: PV ...
ID: lvextend_by_size
DESC: Extend an LV by a specified size.
lvextend LV PV ...
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors SNumber,
@@ -1033,7 +1003,6 @@ OO: --alloc Alloc, --autobackup Bool, --force, --mirrors SNumber,
--reportformat String, --resizefs, --stripes Number, --stripesize SizeKB,
--test
ID: lvextend_by_pv
DESC: Extend an LV by a specified PV.
lvextend --poolmetadatasize SizeMB LV_thinpool
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors SNumber,
@@ -1042,7 +1011,6 @@ OO: --alloc Alloc, --autobackup Bool, --force, --mirrors SNumber,
--test
OP: PV ...
ID: lvextend_pool_metadata_by_size
DESC: Extend a pool metadata SubLV by a specified size.
lvextend --usepolicies LV_thinpool_snapshot
OO: --alloc Alloc, --autobackup Bool, --force, --mirrors SNumber,
@@ -1050,7 +1018,6 @@ OO: --alloc Alloc, --autobackup Bool, --force, --mirrors SNumber,
--reportformat String, --resizefs,
--test
ID: lvextend_by_policy
DESC: Extend an LV according to a predefined policy.
---
@@ -1107,7 +1074,7 @@ OO: --alloc Alloc, --autobackup Bool, --force,
--test
OP: PV ...
ID: lvresize_pool_metadata_by_size
DESC: Resize a pool metadata SubLV by a specified size.
DESC: Resize the metadata SubLV of a pool LV.
---
@@ -1136,12 +1103,10 @@ OO_PVCHANGE_META: --allocatable Bool, --addtag Tag, --deltag Tag,
pvchange OO_PVCHANGE_META --all
OO: OO_PVCHANGE
ID: pvchange_properties_all
DESC: Change properties of all PVs.
pvchange OO_PVCHANGE_META PV|Select ...
OO: --select String, OO_PVCHANGE
ID: pvchange_properties_some
DESC: Change properties of specified PVs.
---
@@ -1186,12 +1151,10 @@ OO: --abort, --alloc Alloc, --atomic, --autobackup Bool, --background,
--interval Number, --name LV, --noudevsync, --reportformat String, --test
OP: PV ...
ID: pvmove_one
DESC: Move PV extents.
pvmove
OO: --abort, --background, --test
ID: pvmove_any
DESC: Continue or abort existing pvmove operations.
---
@@ -1212,14 +1175,12 @@ pvscan
OO: --ignorelockingfailure, --reportformat String, --exported, --novolumegroup,
--short, --uuid
ID: pvscan_show
DESC: Display PV information.
pvscan --cache_long
OO: --ignorelockingfailure, --reportformat String, --background,
--activate Active, --major Number, --minor Number,
OP: PV|String ...
ID: pvscan_cache
DESC: Populate the lvmetad cache by scanning PVs.
---
@@ -1259,44 +1220,37 @@ vgchange OO_VGCHANGE_META
OO: OO_VGCHANGE
OP: VG|Tag ...
ID: vgchange_properties
DESC: Change a general VG property.
vgchange --monitor Bool
OO: --sysinit, --ignorelockingfailure, --poll Bool, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
ID: vgchange_monitor
DESC: Start or stop monitoring LVs from dmeventd.
vgchange --poll Bool
OO: --ignorelockingfailure, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
ID: vgchange_poll
DESC: Start or stop processing LV conversions.
vgchange --activate Active
OO: --activationmode ActivationMode, --ignoreactivationskip, --partial, --sysinit,
--ignorelockingfailure, --monitor Bool, --poll Bool, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
ID: vgchange_activate
DESC: Activate or deactivate LVs.
vgchange --refresh
OO: --sysinit, --ignorelockingfailure, --monitor Bool, --poll Bool, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
ID: vgchange_refresh
DESC: Reactivate LVs using the latest metadata.
vgchange --lockstart
OO: --lockopt String, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
ID: vgchange_lockstart
DESC: Start the lockspace of a shared VG in lvmlockd.
vgchange --lockstop
OO: --lockopt String, OO_VGCHANGE_META, OO_VGCHANGE
OP: VG|Tag ...
ID: vgchange_lockstop
DESC: Stop the lockspace of a shared VG in lvmlockd.
---
@@ -1342,12 +1296,10 @@ OO_VGEXPORT: --reportformat String, --test
vgexport VG|Tag|Select ...
OO: --select String, OO_VGEXPORT
ID: vgexport_some
DESC: Export specified VGs.
vgexport --all
OO: OO_VGEXPORT
ID: vgexport_all
DESC: Export all VGs.
---
@@ -1366,12 +1318,10 @@ OO_VGIMPORT: --force, --reportformat String, --test
vgimport VG|Tag|Select ...
OO: --select String, OO_VGIMPORT
ID: vgimport_some
DESC: Import specified VGs.
vgimport --all
OO: OO_VGIMPORT
ID: vgimport_all
DESC: Import all VGs.
---
@@ -1399,17 +1349,14 @@ OO_VGREDUCE: --autobackup Bool, --force, --reportformat String, --test
vgreduce VG PV ...
OO: OO_VGREDUCE
ID: vgreduce_by_pv
DESC: Remove a PV from a VG.
vgreduce --all VG
OO: OO_VGREDUCE
ID: vgreduce_all
DESC: Remove all unused PVs from a VG.
vgreduce --removemissing VG
OO: --mirrorsonly, OO_VGREDUCE
ID: vgreduce_missing
DESC: Remove all missing PVs from a VG.
---
@@ -1422,12 +1369,10 @@ ID: vgremove_general
vgrename VG VG_new
OO: --autobackup Bool, --force, --reportformat String, --test
ID: vgrename_by_name
DESC: Rename a VG.
vgrename String VG_new
OO: --autobackup Bool, --force, --reportformat String, --test
ID: vgrename_by_uuid
DESC: Rename a VG by specifying the VG UUID.
---
@@ -1477,12 +1422,10 @@ OO_VGSPLIT_NEW: --alloc Alloc, --clustered Bool,
vgsplit VG VG PV ...
OO: OO_VGSPLIT, OO_VGSPLIT_NEW
ID: vgsplit_by_pv
DESC: Split a VG by specified PVs.
vgsplit --name LV VG VG
OO: OO_VGSPLIT, OO_VGSPLIT_NEW
ID: vgsplit_by_lv
DESC: Split a VG by PVs in a specified LV.
---

View File

@@ -108,8 +108,6 @@ static struct opt_name opt_names[ARG_COUNT + 1] = {
struct cmd_name {
const char *name;
const char *desc;
int variants;
int common_options[ARG_COUNT + 1];
};
/* create table of command names, e.g. vgcreate */
@@ -135,7 +133,7 @@ struct oo_line {
int cmd_count;
struct command cmd_array[MAX_CMDS];
struct command lvm_all; /* for printing common options for all lvm commands */
struct command common_options; /* for printing common usage */
#define MAX_OO_LINES 256
int oo_line_count;
@@ -501,19 +499,6 @@ static const char *cmd_name_desc(const char *name)
return NULL;
}
static struct cmd_name *find_command_name(const char *str)
{
int i;
for (i = 0; i < MAX_CMD_NAMES; i++) {
if (!cmd_names[i].name)
break;
if (!strcmp(cmd_names[i].name, str))
return &cmd_names[i];
}
return NULL;
}
static int is_opt_name(char *str)
{
if (!strncmp(str, "--", 2))
@@ -992,7 +977,7 @@ static void print_def(struct arg_def *def, int usage)
printf("%s", def->str);
else if (val_enum == constnum_VAL)
printf("%llu", (unsigned long long)def->num);
printf("ll%u", (unsigned long long)def->num);
else {
if (sep) printf("|");
@@ -1188,156 +1173,35 @@ void print_command_count(void)
printf("};\n");
}
static int is_lvm_all_opt(int opt)
static int is_common_opt(int opt)
{
int oo;
for (oo = 0; oo < lvm_all.oo_count; oo++) {
if (lvm_all.optional_opt_args[oo].opt == opt)
for (oo = 0; oo < common_options.oo_count; oo++) {
if (common_options.optional_opt_args[oo].opt == opt)
return 1;
}
return 0;
}
static void factor_common_options(void)
/*
* For certain commands (esp commands like lvcreate with many variants), common
* options should not be printed for every variation, but once for all. The
* list of commands this applies to is fixed for now but could be encoded in
* command-lines.in.
*
* The common options are defined in OO_USAGE_COMMON. Those options
* are skipped when creating the usage strings for each variation of
* these commands. Instead they are set in the usage_common string.
*/
void print_usage(struct command *cmd, int skip_required)
{
int cn, opt_enum, ci, oo, found;
struct command *cmd;
for (cn = 0; cn < MAX_CMD_NAMES; cn++) {
if (!cmd_names[cn].name)
break;
for (ci = 0; ci < cmd_count; ci++) {
cmd = &cmd_array[ci];
if (strcmp(cmd->name, cmd_names[cn].name))
continue;
cmd_names[cn].variants++;
}
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
for (ci = 0; ci < cmd_count; ci++) {
cmd = &cmd_array[ci];
if (strcmp(cmd->name, cmd_names[cn].name))
continue;
found = 0;
for (oo = 0; oo < cmd->oo_count; oo++) {
if (cmd->optional_opt_args[oo].opt == opt_enum) {
found = 1;
break;
}
}
if (!found)
goto next_opt;
}
/* all commands starting with this name use this option */
cmd_names[cn].common_options[opt_enum] = 1;
next_opt:
;
}
}
/*
for (cn = 0; cn < MAX_CMD_NAMES; cn++) {
if (!cmd_names[cn].name)
break;
printf("%s (%d)\n", cmd_names[cn].name, cmd_names[cn].variants);
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
if (cmd_names[cn].common_options[opt_enum])
printf(" %s\n", opt_names[opt_enum].long_opt);
}
}
*/
}
void print_usage_common(struct command *cmd)
{
struct cmd_name *cname;
int i, sep, ro, rp, oo, op, opt_enum;
if (!(cname = find_command_name(cmd->name)))
return;
sep = 0;
/*
* when there's more than one variant, options that
* are common to all commands with a common name.
*/
if (cname->variants < 2)
goto all;
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
if (!cname->common_options[opt_enum])
continue;
if (is_lvm_all_opt(opt_enum))
continue;
if (!sep) {
printf("\n");
printf("\" [");
} else {
printf(",");
}
for (oo = 0; oo < cmd->oo_count; oo++) {
if (cmd->optional_opt_args[oo].opt != opt_enum)
continue;
printf(" %s", opt_names[opt_enum].long_opt);
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
print_def(&cmd->optional_opt_args[oo].def, 1);
}
sep = 1;
break;
}
}
all:
/* options that are common to all lvm commands */
for (oo = 0; oo < lvm_all.oo_count; oo++) {
opt_enum = lvm_all.optional_opt_args[oo].opt;
if (!sep) {
printf("\n");
printf("\" [");
} else {
printf(",");
}
printf(" %s", opt_names[opt_enum].long_opt);
if (lvm_all.optional_opt_args[oo].def.val_bits) {
printf(" ");
print_def(&lvm_all.optional_opt_args[oo].def, 1);
}
sep = 1;
}
printf(" ]\"");
printf(";\n");
}
void print_usage(struct command *cmd)
{
struct cmd_name *cname;
int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
int i, sep, ro, rp, oo, op, opt_enum;
int i, sep, ro, rp, oo, op;
if (!(cname = find_command_name(cmd->name)))
return;
if (skip_required)
goto oo_count;
printf("\"%s", cmd->name);
@@ -1376,41 +1240,31 @@ void print_usage(struct command *cmd)
sep = 0;
if (cmd->oo_count) {
printf("\n");
printf("\" [");
for (oo = 0; oo < cmd->oo_count; oo++) {
opt_enum = cmd->optional_opt_args[oo].opt;
/*
* Skip common opts which are in the usage_common string.
* The common opts are those in lvm_all and in
* cname->common_options.
*/
if (is_lvm_all_opt(opt_enum))
/* skip common opts which are in the usage_common string */
if ((cmd != &common_options) && is_common_opt(cmd->optional_opt_args[oo].opt))
continue;
if ((cname->variants > 1) && cname->common_options[opt_enum])
continue;
if (!sep) {
printf("\n");
printf("\" [");
}
if (sep)
printf(",");
printf(" %s", opt_names[opt_enum].long_opt);
printf(" %s", opt_names[cmd->optional_opt_args[oo].opt].long_opt);
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
print_def(&cmd->optional_opt_args[oo].def, 1);
}
sep = 1;
}
if (sep)
printf(",");
printf(" COMMON_OPTIONS");
printf(" ]\"");
}
if (sep)
printf(" ]\"");
op_count:
if (!cmd->op_count)
goto done;
@@ -1498,7 +1352,7 @@ static void print_def_man(struct arg_def *def, int usage)
else if (val_enum == constnum_VAL) {
printf("\\fB");
printf("%llu", (unsigned long long)def->num);
printf("ll%u", (unsigned long long)def->num);
printf("\\fP");
}
@@ -1539,14 +1393,13 @@ static void print_def_man(struct arg_def *def, int usage)
printf(" ...");
}
void print_man_usage(struct command *cmd)
void print_cmd_man(struct command *cmd, int skip_required)
{
struct cmd_name *cname;
int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
int i, sep, ro, rp, oo, op, opt_enum;
int i, sep, ro, rp, oo, op;
if (!(cname = find_command_name(cmd->name)))
return;
if (skip_required)
goto oo_count;
printf("\\fB%s\\fP", cmd->name);
@@ -1571,7 +1424,6 @@ void print_man_usage(struct command *cmd)
sep = 0;
/* print required options with a short opt */
for (ro = 0; ro < cmd->ro_count; ro++) {
if (!opt_names[cmd->required_opt_args[ro].opt].short_opt)
continue;
@@ -1599,7 +1451,6 @@ void print_man_usage(struct command *cmd)
sep = 1;
}
/* print required options without a short opt */
for (ro = 0; ro < cmd->ro_count; ro++) {
if (opt_names[cmd->required_opt_args[ro].opt].short_opt)
continue;
@@ -1625,7 +1476,6 @@ void print_man_usage(struct command *cmd)
printf(".RE\n");
}
/* print required positional args on a new line after the onereq set */
if (cmd->rp_count) {
printf(".RS 4\n");
for (rp = 0; rp < cmd->rp_count; rp++) {
@@ -1648,7 +1498,7 @@ void print_man_usage(struct command *cmd)
/*
* all are required options, print as:
* -a|--aaa <val> -b|--bbb <val>
* -a|--a, -b|--b
*/
if (cmd->ro_count) {
@@ -1668,7 +1518,6 @@ void print_man_usage(struct command *cmd)
}
}
/* print required positional args on the same line as the required options */
if (cmd->rp_count) {
for (rp = 0; rp < cmd->rp_count; rp++) {
if (cmd->required_pos_args[rp].def.val_bits) {
@@ -1690,29 +1539,22 @@ void print_man_usage(struct command *cmd)
sep = 0;
if (cmd->oo_count) {
printf(".RS 4\n");
printf("[");
printf(".br\n");
/* print optional options with short opts */
if (cmd->oo_count) {
for (oo = 0; oo < cmd->oo_count; oo++) {
opt_enum = cmd->optional_opt_args[oo].opt;
if (!opt_names[opt_enum].short_opt)
/* skip common opts which are in the usage_common string */
if ((cmd != &common_options) && is_common_opt(cmd->optional_opt_args[oo].opt))
continue;
/*
* Skip common opts which are in the usage_common string.
* The common opts are those in lvm_all and in
* cname->common_options.
*/
if (is_lvm_all_opt(opt_enum))
if (!opt_names[cmd->optional_opt_args[oo].opt].short_opt)
continue;
if ((cname->variants > 1) && cname->common_options[opt_enum])
continue;
if (!sep) {
printf(".RS 4\n");
printf("[");
}
if (sep) {
printf(",");
@@ -1721,8 +1563,8 @@ void print_man_usage(struct command *cmd)
}
printf(" \\fB-%c\\fP|\\fB%s\\fP",
opt_names[opt_enum].short_opt,
opt_names[opt_enum].long_opt);
opt_names[cmd->optional_opt_args[oo].opt].short_opt,
opt_names[cmd->optional_opt_args[oo].opt].long_opt);
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
@@ -1731,25 +1573,18 @@ void print_man_usage(struct command *cmd)
sep = 1;
}
/* print optional options without short opts */
for (oo = 0; oo < cmd->oo_count; oo++) {
opt_enum = cmd->optional_opt_args[oo].opt;
if (opt_names[opt_enum].short_opt)
/* skip common opts which are in the usage_common string */
if ((cmd != &common_options) && is_common_opt(cmd->optional_opt_args[oo].opt))
continue;
/*
* Skip common opts which are in the usage_common string.
* The common opts are those in lvm_all and in
* cname->common_options.
*/
if (is_lvm_all_opt(opt_enum))
if (opt_names[cmd->optional_opt_args[oo].opt].short_opt)
continue;
if ((cname->variants > 1) && cname->common_options[opt_enum])
continue;
if (!sep) {
printf(".RS 4\n");
printf("[");
}
if (sep) {
printf(",");
@@ -1760,7 +1595,7 @@ void print_man_usage(struct command *cmd)
/* space alignment without short opt */
printf(" ");
printf(" \\fB%s\\fP", opt_names[opt_enum].long_opt);
printf(" \\fB%s\\fP", opt_names[cmd->optional_opt_args[oo].opt].long_opt);
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
@@ -1768,15 +1603,9 @@ void print_man_usage(struct command *cmd)
}
sep = 1;
}
}
if (sep) {
printf(",");
printf("\n.br\n");
printf(" ");
/* space alignment without short opt */
printf(" ");
}
printf(" COMMON_OPTIONS");
if (sep) {
printf(" ]\n");
printf(".RE\n");
printf(".br\n");
@@ -1805,151 +1634,6 @@ void print_man_usage(struct command *cmd)
printf("\n");
}
void print_man_usage_common(struct command *cmd)
{
struct cmd_name *cname;
int i, sep, ro, rp, oo, op, opt_enum;
if (!(cname = find_command_name(cmd->name)))
return;
sep = 0;
printf(".RS 4\n");
printf("[");
/*
* when there's more than one variant, options that
* are common to all commands with a common name.
*/
if (cname->variants < 2)
goto all;
/* print those with short opts */
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
if (!cname->common_options[opt_enum])
continue;
if (!opt_names[opt_enum].short_opt)
continue;
if (is_lvm_all_opt(opt_enum))
continue;
if (sep) {
printf(",");
printf("\n.br\n");
printf(" ");
}
for (oo = 0; oo < cmd->oo_count; oo++) {
if (cmd->optional_opt_args[oo].opt != opt_enum)
continue;
printf(" \\fB-%c\\fP|\\fB%s\\fP",
opt_names[opt_enum].short_opt,
opt_names[opt_enum].long_opt);
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
print_def_man(&cmd->optional_opt_args[oo].def, 1);
}
sep = 1;
break;
}
}
/* print those without short opts */
for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
if (!cname->common_options[opt_enum])
continue;
if (opt_names[opt_enum].short_opt)
continue;
if (is_lvm_all_opt(opt_enum))
continue;
if (sep) {
printf(",");
printf("\n.br\n");
printf(" ");
}
for (oo = 0; oo < cmd->oo_count; oo++) {
if (cmd->optional_opt_args[oo].opt != opt_enum)
continue;
/* space alignment without short opt */
printf(" ");
printf(" \\fB%s\\fP", opt_names[opt_enum].long_opt);
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
print_def_man(&cmd->optional_opt_args[oo].def, 1);
}
sep = 1;
break;
}
}
all:
/* options that are common to all lvm commands */
/* those with short opts */
for (oo = 0; oo < lvm_all.oo_count; oo++) {
opt_enum = lvm_all.optional_opt_args[oo].opt;
if (!opt_names[opt_enum].short_opt)
continue;
if (sep) {
printf(",");
printf("\n.br\n");
printf(" ");
}
printf(" \\fB-%c\\fP|\\fB%s\\fP",
opt_names[opt_enum].short_opt,
opt_names[opt_enum].long_opt);
if (lvm_all.optional_opt_args[oo].def.val_bits) {
printf(" ");
print_def(&lvm_all.optional_opt_args[oo].def, 1);
}
sep = 1;
}
/* those without short opts */
for (oo = 0; oo < lvm_all.oo_count; oo++) {
opt_enum = lvm_all.optional_opt_args[oo].opt;
if (opt_names[opt_enum].short_opt)
continue;
if (sep) {
printf(",");
printf("\n.br\n");
printf(" ");
}
/* space alignment without short opt */
printf(" ");
printf(" \\fB%s\\fP", opt_names[opt_enum].long_opt);
if (lvm_all.optional_opt_args[oo].def.val_bits) {
printf(" ");
print_def(&lvm_all.optional_opt_args[oo].def, 1);
}
sep = 1;
}
printf(" ]\"");
printf(";\n");
}
#define DESC_LINE 256
void print_desc_man(const char *desc)
@@ -1990,16 +1674,16 @@ void print_desc_man(const char *desc)
}
}
void print_man_command(void)
void print_command_man(void)
{
struct command *cmd;
const char *last_cmd_name = NULL;
const char *desc;
int i, j, ro, rp, oo, op;
include_optional_opt_args(&lvm_all, "OO_USAGE_COMMON");
include_optional_opt_args(&common_options, "OO_USAGE_COMMON");
printf(".TH LVM_COMMANDS 8\n");
printf(".TH LVM_ALL 8\n");
for (i = 0; i < cmd_count; i++) {
@@ -2027,12 +1711,12 @@ void print_man_command(void)
printf(".P\n");
}
print_man_usage(cmd);
print_cmd_man(cmd, 0);
if ((i == (cmd_count - 1)) || strcmp(cmd->name, cmd_array[i+1].name)) {
printf("Common options:\n");
printf(".\n");
print_man_usage_common(cmd);
print_cmd_man(&common_options, 1);
}
printf("\n");
@@ -2045,7 +1729,7 @@ void print_command_struct(int only_usage)
struct command *cmd;
int i, j, ro, rp, oo, op;
include_optional_opt_args(&lvm_all, "OO_USAGE_COMMON");
include_optional_opt_args(&common_options, "OO_USAGE_COMMON");
printf("/* Do not edit. This file is generated by scripts/create-commands */\n");
printf("/* using command definitions from scripts/command-lines.in */\n");
@@ -2055,8 +1739,8 @@ void print_command_struct(int only_usage)
cmd = &cmd_array[i];
if (only_usage) {
print_usage(cmd);
print_usage_common(cmd);
print_usage(cmd, 0);
print_usage(&common_options, 1);
printf("\n");
continue;
}
@@ -2075,11 +1759,11 @@ void print_command_struct(int only_usage)
printf("commands[%d].desc = \"%s\";\n", i, cmd->desc ?: "");
printf("commands[%d].usage = ", i);
print_usage(cmd);
print_usage(cmd, 0);
if (cmd->oo_count) {
printf("commands[%d].usage_common = ", i);
print_usage_common(cmd);
print_usage(&common_options, 1);
} else {
printf("commands[%d].usage_common = \"NULL\";\n", i);
}
@@ -2248,8 +1932,8 @@ static void print_ambiguous(void)
}
printf("Ambiguous commands %d and %d:\n", i, j);
print_usage(cmd);
print_usage(dup);
print_usage(cmd, 0);
print_usage(dup, 0);
printf("\n");
dups[found].i = i;
@@ -2289,11 +1973,11 @@ static void print_help(int argc, char *argv[])
{
printf("%s --output struct|count|usage|expanded <filename>\n", argv[0]);
printf("\n");
printf("struct: print C structures for command-lines.h\n");
printf("count: print defines and enums for command-lines-count.h\n");
printf("ambiguous: print commands differing only by LV types\n");
printf("struct: print C structures.\n");
printf("usage: print usage format.\n");
printf("expanded: print expanded input format.\n");
printf("count: print #define COMMAND_COUNT <Number>\n");
printf("ambiguous: print commands differing only by LV types\n");
}
int main(int argc, char *argv[])
@@ -2398,11 +2082,9 @@ int main(int argc, char *argv[])
if (is_desc_line(line_argv[0])) {
char *desc = strdup(line_orig);
if (cmd->desc) {
int newlen = strlen(cmd->desc) + strlen(desc) + 2;
char *newdesc = malloc(newlen);
memset(newdesc, 0, newlen);
snprintf(newdesc, newlen, "%s %s", cmd->desc, desc);
cmd->desc = newdesc;
cmd->desc = realloc((char *)cmd->desc, strlen(cmd->desc) + strlen(desc) + 2);
strcat((char *)cmd->desc, " ");
strcat((char *)cmd->desc, desc);
free(desc);
} else
cmd->desc = desc;
@@ -2461,14 +2143,10 @@ int main(int argc, char *argv[])
fclose(file);
factor_common_options();
if (!outputformat)
print_command_struct(1);
else if (!strcmp(outputformat, "struct")) {
else if (!strcmp(outputformat, "struct"))
print_command_struct(0);
print_ambiguous();
}
else if (!strcmp(outputformat, "count"))
print_command_count();
else if (!strcmp(outputformat, "usage"))
@@ -2478,10 +2156,8 @@ int main(int argc, char *argv[])
else if (!strcmp(outputformat, "ambiguous"))
print_ambiguous();
else if (!strcmp(outputformat, "man"))
print_man_command();
print_command_man();
else
print_help(argc, argv);
return 0;
}

View File

@@ -81,8 +81,7 @@ lvcreate -l1 -s -n inval $vg/$lv3
lvcreate -l4 -I4 -i2 -n stripe $vg
# Invalidate snapshot
not dd if=/dev/zero of="$DM_DEV_DIR/$vg/inval" bs=4K
# ignores unused positional arg dev1
lvscan "$dev1"
invalid lvscan "$dev1"
lvdisplay --maps
lvscan --all
@@ -109,16 +108,13 @@ vgmknodes --refresh
lvscan
lvmdiskscan
# ignores unused arg
pvscan "$dev1"
invalid pvscan "$dev1"
invalid pvscan -aay
invalid pvscan --major 254
invalid pvscan --minor 0
invalid pvscan --novolumegroup -e
# ignores unsed arg
vgscan $vg
# ignroes unused arg
lvscan $vg
invalid vgscan $vg
invalid lvscan $vg
if aux have_readline; then
cat <<EOF | lvm

View File

@@ -76,7 +76,6 @@ SOURCES2 =\
TARGETS =\
.commands \
command-lines.h \
liblvm2cmd.a \
lvm
@@ -100,8 +99,7 @@ LIB_VERSION = $(LIB_VERSION_LVM)
CLEAN_TARGETS = liblvm2cmd.$(LIB_SUFFIX) $(TARGETS_DM) \
liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION) lvm-static.o \
liblvm2cmd-static.a dmsetup.static lvm.static \
$(LDDEPS) .exported_symbols_generated \
ccmd command-lines.h command-lines-count.h
$(LDDEPS) .exported_symbols_generated
ifeq ("@CMDLIB@", "yes")
TARGETS += liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION)
@@ -173,13 +171,6 @@ liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION): liblvm2cmd.$(LIB_SUFFIX)
$(CC) -E -P $(srcdir)/cmdnames.h 2> /dev/null | \
egrep -v '^ *(|#.*|config|devtypes|dumpconfig|formats|fullreport|help|lastlog|lvpoll|pvdata|segtypes|systemid|tags|version) *$$' > .commands
ccmd: create-commands.c
$(CC) create-commands.c -o ccmd
command-lines.h: ccmd
./ccmd --output struct command-lines.in > command-lines.h
./ccmd --output count command-lines.in > command-lines-count.h
ifneq ("$(CFLOW_CMD)", "")
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
-include $(top_builddir)/libdm/libdevmapper.cflow

129
tools/command-lines-count.h Normal file
View File

@@ -0,0 +1,129 @@
/* Do not edit. This file is generated by scripts/create-commands */
/* using command definitions from scripts/command-lines.in */
#define COMMAND_COUNT 152
enum {
no_CMD,
lvchange_properties_CMD,
lvchange_resync_CMD,
lvchange_syncaction_CMD,
lvchange_rebuild_CMD,
lvchange_activate_CMD,
lvchange_refresh_CMD,
lvchange_monitor_CMD,
lvchange_poll_CMD,
lvchange_persistent_CMD,
lvconvert_merge_CMD,
lvconvert_combine_split_snapshot_CMD,
lvconvert_to_thin_with_external_CMD,
lvconvert_to_cache_vol_CMD,
lvconvert_to_thinpool_CMD,
lvconvert_to_cachepool_CMD,
lvconvert_to_mirror_CMD,
lvconvert_general_to_raid_CMD,
lvconvert_to_mirrored_or_change_image_count_CMD,
lvconvert_raid_to_striped_CMD,
lvconvert_raid_or_mirror_to_linear_CMD,
lvconvert_split_mirror_images_to_new_CMD,
lvconvert_split_mirror_images_and_track_CMD,
lvconvert_repair_pvs_or_thinpool_CMD,
lvconvert_replace_pv_CMD,
lvconvert_change_mirrorlog_CMD,
lvconvert_split_and_keep_cachepool_CMD,
lvconvert_split_and_delete_cachepool_CMD,
lvconvert_split_cow_snapshot_CMD,
lvconvert_poll_mirror_CMD,
lvconvert_swap_pool_metadata_CMD,
lvcreate_error_vol_CMD,
lvcreate_zero_vol_CMD,
lvcreate_linear_CMD,
lvcreate_striped_CMD,
lvcreate_mirror_CMD,
lvcreate_raid_any_CMD,
lvcreate_cow_snapshot_CMD,
lvcreate_striped_cow_snapshot_CMD,
lvcreate_cow_snapshot_with_virtual_origin_CMD,
lvcreate_thinpool_CMD,
lvcreate_cachepool_CMD,
lvcreate_thin_vol_CMD,
lvcreate_thin_snapshot_CMD,
lvcreate_thin_snapshot_of_external_CMD,
lvcreate_thin_vol_with_thinpool_CMD,
lvcreate_thin_vol_with_thinpool_or_sparse_snapshot_CMD,
lvcreate_cache_vol_with_new_origin_CMD,
lvcreate_cache_vol_with_new_origin_or_convert_to_cache_vol_with_cachepool_CMD,
lvdisplay_general_CMD,
lvextend_by_size_CMD,
lvextend_by_pv_CMD,
lvextend_pool_metadata_by_size_CMD,
lvextend_by_policy_CMD,
lvmconfig_general_CMD,
lvreduce_general_CMD,
lvremove_general_CMD,
lvrename_vg_lv_lv_CMD,
lvrename_lv_lv_CMD,
lvresize_by_size_CMD,
lvresize_by_pv_CMD,
lvresize_pool_metadata_by_size_CMD,
lvs_general_CMD,
lvscan_general_CMD,
pvchange_properties_all_CMD,
pvchange_properties_some_CMD,
pvresize_general_CMD,
pvck_general_CMD,
pvcreate_general_CMD,
pvdisplay_general_CMD,
pvmove_one_CMD,
pvmove_any_CMD,
pvremove_general_CMD,
pvs_general_CMD,
pvscan_show_CMD,
pvscan_cache_CMD,
vgcfgbackup_general_CMD,
vgcfgrestore_by_vg_CMD,
vgcfgrestore_by_file_CMD,
vgchange_properties_CMD,
vgchange_monitor_CMD,
vgchange_poll_CMD,
vgchange_activate_CMD,
vgchange_refresh_CMD,
vgchange_lockstart_CMD,
vgchange_lockstop_CMD,
vgck_general_CMD,
vgconvert_general_CMD,
vgcreate_general_CMD,
vgdisplay_general_CMD,
vgexport_some_CMD,
vgexport_all_CMD,
vgextend_general_CMD,
vgimport_some_CMD,
vgimport_all_CMD,
vgimportclone_general_CMD,
vgmerge_general_CMD,
vgmknodes_general_CMD,
vgreduce_by_pv_CMD,
vgreduce_all_CMD,
vgreduce_missing_CMD,
vgremove_general_CMD,
vgrename_by_name_CMD,
vgrename_by_uuid_CMD,
vgs_general_CMD,
vgscan_general_CMD,
vgsplit_by_pv_CMD,
vgsplit_by_lv_CMD,
devtypes_general_CMD,
fullreport_general_CMD,
lastlog_general_CMD,
lvpoll_general_CMD,
formats_general_CMD,
help_general_CMD,
version_general_CMD,
pvdata_general_CMD,
segtypes_general_CMD,
systemid_general_CMD,
tags_general_CMD,
lvmchange_general_CMD,
lvmdiskscan_general_CMD,
lvmsadc_general_CMD,
lvmsar_general_CMD,
COMMAND_ID_COUNT,
};

8857
tools/command-lines.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1022,8 +1022,6 @@ check_val:
static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp, char **argv)
{
const char *name;
/*
* rp is the index in required_pos_args[] of the required positional arg.
* The pos values begin with 1, so the first positional arg has
@@ -1045,33 +1043,20 @@ static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp
/*
* For an lvcreate command with VG as the first required positional arg,
* the VG position is allowed to be empty if --name VG/LV is used, or if the
* the VG position is allowed to be empty if --name is used, or if the
* LVM_VG_NAME env var is set.
*
* --thinpool VG/LV and --cachepool VG/LV can also function like --name
* to provide the VG name in place of the positional arg.
* to hold the VG name making pos 1 optional.
*
* FIXME: verify that the --name/--thinpool/--cachepool value has the form
* of VG/LV, or that getenv("LVM_VG_NAME") and --name LV is used?
*/
if (!strcmp(cmd->name, "lvcreate") &&
(rp == 0) &&
val_bit_is_set(commands[ci].required_pos_args[rp].def.val_bits, vg_VAL) &&
(arg_is_set(cmd, name_ARG) || arg_is_set(cmd, thinpool_ARG) || arg_is_set(cmd, cachepool_ARG))) {
if ((name = arg_str_value(cmd, name_ARG, NULL))) {
if (strstr(name, "/") || getenv("LVM_VG_NAME"))
return 1;
}
/* FIXME: does LVM_VG_NAME also work with --thinpool/--cachepool ? */
if ((name = arg_str_value(cmd, thinpool_ARG, NULL))) {
if (strstr(name, "/"))
return 1;
}
if ((name = arg_str_value(cmd, cachepool_ARG, NULL))) {
if (strstr(name, "/"))
return 1;
}
}
(arg_is_set(cmd, name_ARG) || arg_is_set(cmd, thinpool_ARG) || arg_is_set(cmd, cachepool_ARG)))
return 1;
return 0;
}
@@ -1237,14 +1222,17 @@ static void _print_description(int ci)
int bi = 0;
for (di = 0; di < strlen(desc); di++) {
if (desc[di] == '\0')
break;
if (desc[di] == '\n')
continue;
if (!strncmp(&desc[di], "DESC:", 5)) {
if (bi) {
buf[bi] = '\0';
log_print("%s", buf);
memset(buf, 0, sizeof(buf));
bi = 0;
}
/* skip DESC: */
di += 5;
continue;
}
@@ -1258,10 +1246,8 @@ static void _print_description(int ci)
break;
}
if (bi) {
buf[bi] = '\0';
if (bi)
log_print("%s", buf);
}
}
/*
@@ -1577,8 +1563,6 @@ static int _usage(const char *name, int help_count)
log_print(". --size Number can be replaced with --extents NumberExtents.");
log_print(". When --name is omitted from lvcreate, a new LV name is");
log_print(" generated with the \"lvol\" prefix and a unique numeral suffix.");
log_print(". The required VG parameter in lvcreate may be omitted when");
log_print(" the VG name is included in another option, e.g. --name VG/LV.");
log_print(". For required options listed in parentheses, e.g. (--A, --B),");
log_print(" any one is required, after which the others are optional.");
log_print(". The _new suffix indicates the VG or LV must not yet exist.");

View File

@@ -116,7 +116,8 @@ val(permission_VAL, permission_arg, "Permission", "rw|r")
val(metadatatype_VAL, metadatatype_arg, "MetadataType", "lvm2|lvm1")
val(units_VAL, string_arg, "Units", "hHbBsSkKmMgGtTpPeE")
val(segtype_VAL, segtype_arg, "SegType", "linear|striped|snapshot|mirror|raid*|thin|cache|thin-pool|cache-pool")
val(alloc_VAL, alloc_arg, "Alloc", "contiguous|cling|cling_by_tags|normal|anywhere|inherit")
/* FIXME: cling_by_tags is left out of help text because it makes the line wrap */
val(alloc_VAL, alloc_arg, "Alloc", "contiguous|cling|normal|anywhere|inherit")
val(locktype_VAL, locktype_arg, "LockType", "sanlock|dlm|none")
val(readahead_VAL, readahead_arg, "Readahead", "auto|none|NumberSectors")
val(metadatacopies_VAL, metadatacopies_arg, "MetadataCopies", "all|unmanaged|Number")
@@ -125,8 +126,8 @@ val(metadatacopies_VAL, metadatacopies_arg, "MetadataCopies", "all|unmanaged|Num
val(VAL_COUNT, NULL, NULL, NULL)
/*
* FIXME: I suspect many of the following are good candidates for a custom VAL
* enum for the benefit of custom parsing, or custom usage, or both:
* I suspect many of the following are good candidates for a custom VAL enum
* for the benefit of custom parsing, or custom usage, or both:
*
* configreport_ARG, configtype_ARG, polloperation_ARG, raidrebuild_ARG,
* raidsyncaction_ARG, raidwritemostly_ARG, reportformat_ARG, syncaction_ARG,