1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-24 21:44:22 +03:00

Compare commits

..

1 Commits

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

  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,
          --commandprofile String,
          --config String,
          --driverloaded y|n,
          --nosync,
          --noudevsync,
          --profile String,
          --reportformat String,
          --version,
          --autobackup y|n,
          --debug,
          --force,
          --help,
          --stripes Number,
          --stripesize Number[k|unit],
          --nofsck,
          --quiet,
          --test,
          --verbose,
          --yes,
          --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 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-10-21 14:19:36 -05:00
7 changed files with 518 additions and 9209 deletions

View File

@@ -76,6 +76,7 @@ SOURCES2 =\
TARGETS =\
.commands \
command-lines.h \
liblvm2cmd.a \
lvm
@@ -99,7 +100,8 @@ 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
$(LDDEPS) .exported_symbols_generated \
ccmd command-lines.h command-lines-count.h
ifeq ("@CMDLIB@", "yes")
TARGETS += liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION)
@@ -171,6 +173,13 @@ 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

View File

@@ -1,130 +0,0 @@
/* Do not edit. This file is generated by scripts/create-commands */
/* using command definitions from scripts/command-lines.in */
#define COMMAND_COUNT 153
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_raid1_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,
};

File diff suppressed because it is too large Load Diff

View File

@@ -202,17 +202,20 @@ OO: OO_LVCHANGE
ID: lvchange_properties
DESC: Change a general LV property.
lvchange --resync VG|LV|Tag|Select ...
lvchange --resync VG|LV_raid_mirror|Tag|Select ...
OO: OO_LVCHANGE
ID: lvchange_resync
DESC: Resyncronize a mirror or raid LV.
lvchange --syncaction String VG|LV|Tag|Select ...
lvchange --syncaction String VG|LV_raid|Tag|Select ...
OO: OO_LVCHANGE
ID: lvchange_syncaction
DESC: Resynchronize or check a raid LV.
lvchange --rebuild PV VG|LV|Tag|Select ...
lvchange --rebuild PV VG|LV_raid|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
@@ -222,19 +225,22 @@ DESC: Activate or deactivate an LV.
lvchange --refresh VG|LV|Tag|Select ...
OO: --partial, 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: Monitor or unmonitor an LV.
DESC: Start or stop monitoring an LV from dmeventd.
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.
---
@@ -274,7 +280,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: --background, --interval Number, OO_LVCONVERT
ID: lvconvert_merge
DESC: Merge LV that was previously split from a mirror.
DESC: Merge thin LV into its origin LV.
@@ -384,8 +390,8 @@ DESC: Convert LV to type cache-pool (variant, use --type cache-pool).
# 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 LV type cannot be used when
# matching command definitions.
# 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
@@ -396,7 +402,7 @@ DESC: Convert LV to type mirror.
lvconvert --type mirror LV_raid1
OO: --mirrors SNumber, OO_LVCONVERT_RAID, OO_LVCONVERT
OP: PV ...
ID: lvconvert_raid1_to_mirror
ID: lvconvert_to_mirror
DESC: Convert LV from type raid1 to type mirror.
---
@@ -406,7 +412,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 to unambiguous command lines:
# be nice to split them into two unambiguous command lines:
#
# 1. lvconvert --type raid LV_linear_striped_mirror
# DESC: Convert LV to type raid.
@@ -419,7 +425,7 @@ OO: OO_LVCONVERT_RAID, OO_LVCONVERT
OP: PV ...
ID: lvconvert_general_to_raid
DESC: Convert LV to type raid.
DESC: Change LV raid type.
DESC: Change LV between raid types.
---
@@ -528,21 +534,21 @@ lvconvert --mirrorlog MirrorLog LV_mirror
OO: OO_LVCONVERT
OP: PV ...
ID: lvconvert_change_mirrorlog
DESC: Change the type of log used by LV.
DESC: Change the type of mirror log used by a mirror LV.
---
lvconvert --splitcache LV_cachepool_cache_thinpool
OO: OO_LVCONVERT
ID: lvconvert_split_and_keep_cachepool
DESC: Separate and preserve a cache pool from a cache LV.
DESC: Separate and keep the cache pool from a cache LV.
---
lvconvert --uncache LV_cache_thinpool
OO: OO_LVCONVERT
ID: lvconvert_split_and_delete_cachepool
DESC: Separate and remove a cache pool from a cache LV.
DESC: Separate and delete the cache pool from a cache LV.
---
@@ -557,14 +563,16 @@ 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 LV to collapse resync layers.
DESC: Poll mirror 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).
@@ -586,8 +594,7 @@ 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 general
# practice.
# option's value can invalidate the use of the option is not advisable.
OO_LVCREATE_THIN: --discards Discards, --errorwhenfull Bool, --mirrors 0
@@ -612,7 +619,9 @@ 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.
# 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.
lvcreate --type linear --size SizeMB VG
OO: --mirrors 0, --stripes 1, OO_LVCREATE
@@ -620,11 +629,15 @@ 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.
---
@@ -647,17 +660,21 @@ 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.
DESC: Create a mirror LV (also see --type raid1).
# 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
ID: lvcreate_mirror_or_raid1
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 ...
@@ -670,9 +687,16 @@ 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, --chunksize SizeKB, OO_LVCREATE
OO: --snapshot, --stripes Number, --stripesize SizeKB,
--chunksize SizeKB, OO_LVCREATE
OP: PV ...
ID: lvcreate_cow_snapshot
DESC: Create a COW snapshot LV from an origin LV.
@@ -686,28 +710,6 @@ 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
@@ -775,9 +777,8 @@ DESC: (variant, uses --cachepool in place of --name).
---
lvcreate --type thin --virtualsize SizeMB --thinpool LV_thinpool
lvcreate --type thin --virtualsize SizeMB --thinpool LV_thinpool VG
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.
@@ -785,8 +786,8 @@ 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 arg pos 1
DESC: (variant, also see --thinpool).
DESC: Create a thin LV in a thin pool named in the first arg
DESC: (variant, also see --thinpool for naming pool).
# alternate form of lvcreate --type thin
lvcreate --virtualsize SizeMB --thinpool LV_thinpool
@@ -799,17 +800,12 @@ 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 arg pos 1
DESC: (variant, infers --type thin, also see --thinpool).
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.)
---
# 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
@@ -822,7 +818,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 LV_thin
# alternate form of lvcreate --type thin
lvcreate --snapshot LV_thin
OO: --type thin, OO_LVCREATE_THIN, OO_LVCREATE
ID: lvcreate_thin_snapshot
@@ -851,7 +847,7 @@ lvcreate --type thin --virtualsize SizeMB --size SizeMB --thinpool LV_new
OO: OO_LVCREATE_POOL, OO_LVCREATE_THIN, OO_LVCREATE,
--stripes Number, --stripesize SizeKB
OP: PV ...
ID: lvcreate_thin_vol_with_thinpool
ID: lvcreate_thin_vol_and_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.
@@ -860,34 +856,35 @@ 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_with_thinpool
ID: lvcreate_thin_vol_and_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).
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_with_thinpool
ID: lvcreate_thin_vol_and_thinpool
DESC: Create a thin LV, first creating a thin pool for it,
DESC: where the new thin pool is named in arg pos 1.
DESC: where the new thin pool is named in the first arg.
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_with_thinpool
ID: lvcreate_thin_vol_and_thinpool
DESC: Create a thin LV, first creating a thin pool for it,
DESC: where the new thin pool is named in arg pos 1,
DESC: where the new thin pool is named in the first arg
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.
ID: lvcreate_thin_vol_and_thinpool
DESC: Create a thin LV, first creating a thin pool for it,
DESC: where the new thin pool name is generated automatically.
---
@@ -900,8 +897,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: Infers --type thin or --type snapshot according to
DESC: confing setting sparse_segtype_default.
DESC: Chooses --type thin or --type snapshot according to
DESC: config setting sparse_segtype_default.
---
@@ -936,7 +933,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: by in arg pos 1 (variant, also use --cachepool).
DESC: in the first arg (variant, also use --cachepool).
# This is a ridiculously crazy command which nobody could
# understand. It should be be eliminated. It does two different
@@ -944,7 +941,7 @@ DESC: by in arg pos 1 (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 crazy command above:
# an already complicated command above.
#
# # alternate form for lvcreate_cache_vol_with_new_origin
# lvcreate --cache --size SizeMB LV_cachepool
@@ -953,10 +950,10 @@ DESC: by in arg pos 1 (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 arg pos 1 (variant, infers --type cache,
# DESC: in the first arg (variant, infers --type cache,
# DESC: also use --cachepool).
#
# If LV is not a cachepool, then it's a disguised lvconvert:
# 2. 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
@@ -971,17 +968,18 @@ DESC: by in arg pos 1 (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.
# those variants, each crazy on it's own, into one
# ridiculous command.
# def1: alternate form of lvcreate --type cache, or
# def2: FIXME: it should be done by lvconvert.
# def2: it should be done by lvconvert.
lvcreate --cache --size SizeMB LV
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 arg pos 1
DESC: the existing cache pool named in the first arg
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
@@ -1009,6 +1007,7 @@ 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,
@@ -1016,6 +1015,7 @@ 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,
@@ -1024,6 +1024,7 @@ 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,
@@ -1031,6 +1032,7 @@ 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.
---
@@ -1087,7 +1089,7 @@ OO: --alloc Alloc, --autobackup Bool, --force,
--test
OP: PV ...
ID: lvresize_pool_metadata_by_size
DESC: Resize the metadata SubLV of a pool LV.
DESC: Resize a pool metadata SubLV by a specified size.
---
@@ -1116,10 +1118,12 @@ 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.
---
@@ -1164,10 +1168,12 @@ 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.
---
@@ -1188,12 +1194,14 @@ 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.
---
@@ -1233,37 +1241,44 @@ 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.
---
@@ -1309,10 +1324,12 @@ 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.
---
@@ -1331,10 +1348,12 @@ 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.
---
@@ -1362,14 +1381,17 @@ 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.
---
@@ -1382,10 +1404,12 @@ 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.
---
@@ -1435,10 +1459,12 @@ 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,6 +108,8 @@ 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 */
@@ -133,7 +135,7 @@ struct oo_line {
int cmd_count;
struct command cmd_array[MAX_CMDS];
struct command common_options; /* for printing common usage */
struct command lvm_all; /* for printing common options for all lvm commands */
#define MAX_OO_LINES 256
int oo_line_count;
@@ -499,6 +501,19 @@ 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))
@@ -977,7 +992,7 @@ static void print_def(struct arg_def *def, int usage)
printf("%s", def->str);
else if (val_enum == constnum_VAL)
printf("ll%u", (unsigned long long)def->num);
printf("%llu", (unsigned long long)def->num);
else {
if (sep) printf("|");
@@ -1173,35 +1188,156 @@ void print_command_count(void)
printf("};\n");
}
static int is_common_opt(int opt)
static int is_lvm_all_opt(int opt)
{
int oo;
for (oo = 0; oo < common_options.oo_count; oo++) {
if (common_options.optional_opt_args[oo].opt == opt)
for (oo = 0; oo < lvm_all.oo_count; oo++) {
if (lvm_all.optional_opt_args[oo].opt == opt)
return 1;
}
return 0;
}
/*
* 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)
static void factor_common_options(void)
{
int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
int i, sep, ro, rp, oo, op;
int cn, opt_enum, ci, oo, found;
struct command *cmd;
if (skip_required)
goto oo_count;
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;
if (!(cname = find_command_name(cmd->name)))
return;
printf("\"%s", cmd->name);
@@ -1240,30 +1376,40 @@ void print_usage(struct command *cmd, int skip_required)
sep = 0;
if (cmd->oo_count) {
printf("\n");
printf("\" [");
for (oo = 0; oo < cmd->oo_count; oo++) {
/* skip common opts which are in the usage_common string */
if ((cmd != &common_options) && is_common_opt(cmd->optional_opt_args[oo].opt))
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))
continue;
if (!sep) {
printf("\n");
printf("\" [");
}
if ((cname->variants > 1) && cname->common_options[opt_enum])
continue;
if (sep)
printf(",");
printf(" %s", opt_names[cmd->optional_opt_args[oo].opt].long_opt);
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;
}
}
if (sep)
if (sep)
printf(",");
printf(" COMMON_OPTIONS");
printf(" ]\"");
}
op_count:
if (!cmd->op_count)
@@ -1352,7 +1498,7 @@ static void print_def_man(struct arg_def *def, int usage)
else if (val_enum == constnum_VAL) {
printf("\\fB");
printf("ll%u", (unsigned long long)def->num);
printf("%llu", (unsigned long long)def->num);
printf("\\fP");
}
@@ -1393,13 +1539,14 @@ static void print_def_man(struct arg_def *def, int usage)
printf(" ...");
}
void print_cmd_man(struct command *cmd, int skip_required)
void print_man_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;
int i, sep, ro, rp, oo, op, opt_enum;
if (skip_required)
goto oo_count;
if (!(cname = find_command_name(cmd->name)))
return;
printf("\\fB%s\\fP", cmd->name);
@@ -1424,6 +1571,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
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;
@@ -1451,6 +1599,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
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;
@@ -1476,6 +1625,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
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++) {
@@ -1498,7 +1648,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
/*
* all are required options, print as:
* -a|--a, -b|--b
* -a|--aaa <val> -b|--bbb <val>
*/
if (cmd->ro_count) {
@@ -1518,6 +1668,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
}
}
/* 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) {
@@ -1539,22 +1690,29 @@ void print_cmd_man(struct command *cmd, int skip_required)
sep = 0;
printf(".br\n");
if (cmd->oo_count) {
printf(".RS 4\n");
printf("[");
/* print optional options with short opts */
for (oo = 0; oo < cmd->oo_count; oo++) {
/* skip common opts which are in the usage_common string */
if ((cmd != &common_options) && is_common_opt(cmd->optional_opt_args[oo].opt))
opt_enum = cmd->optional_opt_args[oo].opt;
if (!opt_names[opt_enum].short_opt)
continue;
if (!opt_names[cmd->optional_opt_args[oo].opt].short_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))
continue;
if (!sep) {
printf(".RS 4\n");
printf("[");
}
if ((cname->variants > 1) && cname->common_options[opt_enum])
continue;
if (sep) {
printf(",");
@@ -1563,8 +1721,8 @@ void print_cmd_man(struct command *cmd, int skip_required)
}
printf(" \\fB-%c\\fP|\\fB%s\\fP",
opt_names[cmd->optional_opt_args[oo].opt].short_opt,
opt_names[cmd->optional_opt_args[oo].opt].long_opt);
opt_names[opt_enum].short_opt,
opt_names[opt_enum].long_opt);
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
@@ -1573,18 +1731,25 @@ void print_cmd_man(struct command *cmd, int skip_required)
sep = 1;
}
/* print optional options without short opts */
for (oo = 0; oo < cmd->oo_count; oo++) {
/* skip common opts which are in the usage_common string */
if ((cmd != &common_options) && is_common_opt(cmd->optional_opt_args[oo].opt))
opt_enum = cmd->optional_opt_args[oo].opt;
if (opt_names[opt_enum].short_opt)
continue;
if (opt_names[cmd->optional_opt_args[oo].opt].short_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))
continue;
if (!sep) {
printf(".RS 4\n");
printf("[");
}
if ((cname->variants > 1) && cname->common_options[opt_enum])
continue;
if (sep) {
printf(",");
@@ -1595,7 +1760,7 @@ void print_cmd_man(struct command *cmd, int skip_required)
/* space alignment without short opt */
printf(" ");
printf(" \\fB%s\\fP", opt_names[cmd->optional_opt_args[oo].opt].long_opt);
printf(" \\fB%s\\fP", opt_names[opt_enum].long_opt);
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
@@ -1603,9 +1768,15 @@ void print_cmd_man(struct command *cmd, int skip_required)
}
sep = 1;
}
}
if (sep) {
if (sep) {
printf(",");
printf("\n.br\n");
printf(" ");
/* space alignment without short opt */
printf(" ");
}
printf(" COMMON_OPTIONS");
printf(" ]\n");
printf(".RE\n");
printf(".br\n");
@@ -1634,6 +1805,151 @@ void print_cmd_man(struct command *cmd, int skip_required)
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)
@@ -1674,16 +1990,16 @@ void print_desc_man(const char *desc)
}
}
void print_command_man(void)
void print_man_command(void)
{
struct command *cmd;
const char *last_cmd_name = NULL;
const char *desc;
int i, j, ro, rp, oo, op;
include_optional_opt_args(&common_options, "OO_USAGE_COMMON");
include_optional_opt_args(&lvm_all, "OO_USAGE_COMMON");
printf(".TH LVM_ALL 8\n");
printf(".TH LVM_COMMANDS 8\n");
for (i = 0; i < cmd_count; i++) {
@@ -1711,12 +2027,12 @@ void print_command_man(void)
printf(".P\n");
}
print_cmd_man(cmd, 0);
print_man_usage(cmd);
if ((i == (cmd_count - 1)) || strcmp(cmd->name, cmd_array[i+1].name)) {
printf("Common options:\n");
printf(".\n");
print_cmd_man(&common_options, 1);
print_man_usage_common(cmd);
}
printf("\n");
@@ -1729,7 +2045,7 @@ void print_command_struct(int only_usage)
struct command *cmd;
int i, j, ro, rp, oo, op;
include_optional_opt_args(&common_options, "OO_USAGE_COMMON");
include_optional_opt_args(&lvm_all, "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");
@@ -1739,8 +2055,8 @@ void print_command_struct(int only_usage)
cmd = &cmd_array[i];
if (only_usage) {
print_usage(cmd, 0);
print_usage(&common_options, 1);
print_usage(cmd);
print_usage_common(cmd);
printf("\n");
continue;
}
@@ -1759,11 +2075,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, 0);
print_usage(cmd);
if (cmd->oo_count) {
printf("commands[%d].usage_common = ", i);
print_usage(&common_options, 1);
print_usage_common(cmd);
} else {
printf("commands[%d].usage_common = \"NULL\";\n", i);
}
@@ -1932,8 +2248,8 @@ static void print_ambiguous(void)
}
printf("Ambiguous commands %d and %d:\n", i, j);
print_usage(cmd, 0);
print_usage(dup, 0);
print_usage(cmd);
print_usage(dup);
printf("\n");
dups[found].i = i;
@@ -1973,11 +2289,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.\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("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[])
@@ -2082,9 +2398,11 @@ int main(int argc, char *argv[])
if (is_desc_line(line_argv[0])) {
char *desc = strdup(line_orig);
if (cmd->desc) {
cmd->desc = realloc((char *)cmd->desc, strlen(cmd->desc) + strlen(desc) + 2);
strcat((char *)cmd->desc, " ");
strcat((char *)cmd->desc, 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;
free(desc);
} else
cmd->desc = desc;
@@ -2143,10 +2461,14 @@ 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"))
@@ -2156,8 +2478,10 @@ int main(int argc, char *argv[])
else if (!strcmp(outputformat, "ambiguous"))
print_ambiguous();
else if (!strcmp(outputformat, "man"))
print_command_man();
print_man_command();
else
print_help(argc, argv);
return 0;
}

View File

@@ -1237,17 +1237,14 @@ 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;
}
@@ -1261,8 +1258,10 @@ static void _print_description(int ci)
break;
}
if (bi)
if (bi) {
buf[bi] = '\0';
log_print("%s", buf);
}
}
/*

View File

@@ -116,8 +116,7 @@ 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")
/* 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(alloc_VAL, alloc_arg, "Alloc", "contiguous|cling|cling_by_tags|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")