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

Compare commits

..

38 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
Peter Rajnoha
5c55c4ac18 spec: move dmeventd -R from post to posttrans script for device-mapper-event package
See also https://bugzilla.redhat.com/show_bug.cgi?id=1382688.
2016-10-12 13:52:13 +02:00
Zdenek Kabelac
900e899739 lvconvert: still use strcmp for now
Keep for now function logic making its decision on string content.
We need bigger patch converting all things to bit-checks later.
This needs however bigger refactoring.
So this commit reverts some changes from:
c8b6c13015
2016-10-12 11:18:23 +02:00
Heinz Mauelshagen
8859d4508a lvconvert: fix RAID SubLV --splitmirror regression
Commit 088b3d036a allowed repair on cache origin RAID LVs
and restricted lvconvert actions on RAID SubLVs to change number of mirrors, repair,
replace and type changes in order to avoid unsuitable coversions on them.

This introduced a regression prohibiting --splitmirrors on any RAID SubLVs
(e.g. of cache or thin LVs; lvconvert-{cache,thin}-raid.sh tests failing).

Fix allows split mirrors again.

Fix some indenting whilst on it.
2016-10-12 00:24:57 +02:00
Tony Asleson
e57fd9d963 lvmdbustest.py: ws fixes 2016-10-11 13:16:57 -05:00
Tony Asleson
9c56902365 lvmdbustest.py: Add $PREFIX support
Use the env variable PREFIX for vg & lv names
2016-10-11 13:16:57 -05:00
Tony Asleson
595af62ebd lvmdbustest.py: Use more compatible syntax 2016-10-11 13:16:57 -05:00
Tony Asleson
4fab833920 lvmdbusd: Remove log ouput when ec=0 & stderr != 0 bytes
lvm likes to log to stderr virtually all the time, this isn't
helpful.
2016-10-11 13:16:57 -05:00
Tony Asleson
2830f72288 lvmdbusd: Disable lvm abort on too much log output
The commit:
https://git.fedorahosted.org/cgit/lvm2.git/commit/?id=34c55d98eefd88f85476c0f62f0649c706bde6f0

introduced an abort if lvm logs too much.  In the case of utilizing
lvm shell this is a pretty normal occurance, so we will disable
when we use lvm shell.
2016-10-11 13:16:57 -05:00
Zdenek Kabelac
fe437a6e7d tests: notify dbus only for dbus test 2016-10-11 13:37:44 +02:00
Zdenek Kabelac
8f30069160 cleanup: indent 2016-10-11 13:37:43 +02:00
Zdenek Kabelac
6f576483a8 cleanup: lvconvert drop unused variable 2016-10-11 13:37:43 +02:00
Zdenek Kabelac
c8b6c13015 cleanup: use already set values
When we have already decoded arg_is_set into a local var
or already set  segment type - already use these
values instead of repeating calls and string checks.
2016-10-11 13:37:43 +02:00
Zdenek Kabelac
f4ae43934a cleanup: reorder code
Move some arg test into a single place with sort of alphabetic order
when possible to make reading easier.
2016-10-11 13:37:43 +02:00
Zdenek Kabelac
706d3ddf90 lvconvert: use _read_conversion_type
Code reodering and using same pattern for reading and validating arg
(--type in this case).
2016-10-11 13:36:51 +02:00
Zdenek Kabelac
1186cf2ad4 lvconvert: fix error value
Seems some error path where not converted to 'new' ECMD return value.
Fix them to always 'goto out'.
Also drop unneeded   'ret = 0' when ret already is 0.
2016-10-11 13:36:29 +02:00
Tony Asleson
20e74313cd lvmdbustest.py: Add profile and path for lvm binary 2016-10-10 16:33:42 -05:00
Tony Asleson
be06fa695e lvmdbustest.py: Skip test_job_handling_timer on loopback
This test never passes on loop back, so we will skip unless the
pv devices are real devices which contain `/dev/sd`.

We always fail because we need lvm to run slow to get a timer to
pop, and loopback are too fast.
2016-10-10 16:31:00 -05:00
Tony Asleson
3e45285b40 lvmdbustest.py: Denote failure if set_execution fails 2016-10-10 16:31:00 -05:00
Tony Asleson
0c51f369a4 lvmdbustest.py: Print to stderr
It's easier to follow if we print to stderr, so that our print messages
are in the lvm error log in the correct position to other printed
messages.
2016-10-10 16:31:00 -05:00
Tony Asleson
cb4e26dcb3 lvmdbustest.py: Ensure we exit non-zero on fail
If you run multiple runs of unittest.main, unless you don't pass exit=true
the test case always ends with a 0 exit code.  Add ability to store the
result of each invocation of the test and exit with a non-zero exit code
if anyone of them fail.
2016-10-10 16:31:00 -05:00
Tony Asleson
9f0195ec1e lvmdbusd: Ensure tmp dir gets cleaned up
Regardless of the outcome of starting up the lvm shell process, lets
ensure we clean up the temp directory and pipe.
2016-10-10 16:31:00 -05:00
Tony Asleson
2e941beb44 lvmdbusd: Ensure lvm shell still exists 2016-10-10 16:31:00 -05:00
Heinz Mauelshagen
088b3d036a lvconvert: certain repair of cache raid volumes fails "Cannot convert internal LV"
In case a RAID orig LV is being cached and fails, repair is impossible because
"lvconvert --repair" gets rejected.

Fix by allowing repair on cache orig RAID LVs and
"lvconvert --replace/--mirrors/--type {raid*|mirror|striped|linear}" as well.

Allow the same lvconvert actions on any cache pool and metadata RAID SubLVs.

Resolves: rhbz1380532
2016-10-10 17:31:29 +02:00
Tony Asleson
a8bb8dfb08 lvmdbusd: Add LvCommon.DataPercent 2016-10-05 15:55:41 -05:00
Tony Asleson
d54ffcfcd1 lvmdbusd: Add LvCommon.MovePv
Needed for feature parity for lvm2app.
2016-10-05 15:28:42 -05:00
Tony Asleson
a3f24aaf5c lvmdbusd: Add properties to LvCommon
The following LvCommon properties were added so that the API
would have the same functionality as lvm2app has.

LvCommon.MetaDataSizeBytes
LvCommon.Attr
LvCommon.MetaDataPercent
LvCommon.CopyPercent
LvCommon.SnapPercent
LvCommon.SyncPercent
2016-10-05 13:59:38 -05:00
David Teigland
bf5d0a2651 toollib: clean up coverity issue
in processing duplicate pvs.
2016-10-04 16:25:32 -05:00
Alasdair G Kergon
c900cf7ed4 Revert "cleanup: simplier assign of cmd vars"
This reverts commit cea441f4d1.

cmd->default_values is configurable and this code should not make
any assumptions about values it holds.
2016-10-03 18:14:17 +01:00
Zdenek Kabelac
9e33781d95 tests: proper wait usage
Fix missing wait so we have paired waiting.
Also 'wait' for precise PID to get 'exit' code.

Test for 'error' replacing only with newer snapshot targets.
The old one will wait for resume.

Note: 'wait -n' is not always available so can't be used..
2016-10-03 17:49:56 +02:00
Zdenek Kabelac
43662fa081 cleanup :drop unneeded header file
Not needed  (Coverity).
2016-10-03 17:49:56 +02:00
Zdenek Kabelac
77ffd39dfb cleanup: drop test for NULL
Since lp->segtype has been already checked for not-being NULL,
drop this test so Coverity is not later confused it 'can be a NULL'.
2016-10-03 17:49:56 +02:00
Zdenek Kabelac
9fe4f2337b cleanup: drop assign before use
Drop unneeded assigns singe vars are set later in code before
their first use (Coverity).
2016-10-03 17:49:55 +02:00
Zdenek Kabelac
cea441f4d1 cleanup: simplier assign of cmd vars
Directly assign queried args as they provide matching values for
a setting.
2016-10-03 17:49:55 +02:00
Zdenek Kabelac
00f883a4aa dmeventd: pthread_sigmask in single function
Integrate back _unblock_sigalrm() and check for error code of
pthread_sigmask() function so we do not use uninitialized
sigmask_t on error path (Coverity).
2016-10-03 17:47:28 +02:00
Zdenek Kabelac
d70f112762 libdm: check for mem when _canonicalize_field_ids
Add missing check for dm_pool_strdup() call (Coverity).
2016-10-03 17:46:26 +02:00
Zdenek Kabelac
ee04f1fcfd raid: dmeventd plugin use 64bit arithmetic
Coverity suggested to used 64bit unsigned ints instead of signed 32b int.
Assuming there is no user of >31legs raid array.
2016-10-03 17:44:25 +02:00
Bryn M. Reeves
e95a252974 libdm: convert FIEMAP buffer allocation from stack to dm_zalloc 2016-10-03 15:14:33 +01:00
39 changed files with 6498 additions and 2120 deletions

View File

@@ -1,5 +1,6 @@
Version 2.02.167 -
======================================
Fix a few unconverted return code values for some lvconvert error path.
Disable lvconvert of thin pool to raid while active.
Disable systemd service start rate limiting for lvm2-pvscan@.service.

View File

@@ -1,5 +1,8 @@
Version 1.02.136 -
======================================
Check and report pthread_sigmask() failure in dmeventd.
Check mem alloc fail in _canonicalize_field_ids().
Use unsigned math when checking more then 31 legs of raid.
Fix 'dmstats delete' with dmsetup older than v1.02.129
Fix stats walk segfault with dmsetup older than v1.02.129

View File

@@ -829,17 +829,6 @@ static void _print_sigset(const char *prefix, const sigset_t *sigset)
}
#endif
static sigset_t _unblock_sigalrm(void)
{
sigset_t set, old;
sigemptyset(&set);
sigaddset(&set, SIGALRM);
pthread_sigmask(SIG_UNBLOCK, &set, &old);
return old;
}
enum {
DM_WAIT_RETRY,
DM_WAIT_INTR,
@@ -849,7 +838,7 @@ enum {
/* Wait on a device until an event occurs. */
static int _event_wait(struct thread_status *thread)
{
sigset_t set;
sigset_t set, old;
int ret = DM_WAIT_RETRY;
struct dm_info info;
@@ -859,7 +848,12 @@ static int _event_wait(struct thread_status *thread)
* This is so that you can break out of waiting on an event,
* either for a timeout event, or to cancel the thread.
*/
set = _unblock_sigalrm();
sigemptyset(&set);
sigaddset(&set, SIGALRM);
if (pthread_sigmask(SIG_UNBLOCK, &set, &old) != 0) {
log_sys_error("pthread_sigmask", "unblock alarm");
return ret; /* What better */
}
if (dm_task_run(thread->wait_task)) {
thread->current_events |= DM_EVENT_DEVICE_ERROR;
@@ -883,10 +877,11 @@ static int _event_wait(struct thread_status *thread)
}
}
pthread_sigmask(SIG_SETMASK, &set, NULL);
if (pthread_sigmask(SIG_SETMASK, &old, NULL) != 0)
log_sys_error("pthread_sigmask", "block alarm");
#ifdef DEBUG_SIGNALS
_print_sigset("dmeventd blocking ", &set);
_print_sigset("dmeventd blocking ", &old);
#endif
DEBUGLOG("Completed waitevent task for %s.", thread->device.name);

View File

@@ -48,11 +48,11 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
while ((d = strchr(d, 'D'))) {
uint32_t dev = (uint32_t)(d - status->dev_health);
if (!(state->raid_devs[dev / 64] & (1 << (dev % 64))))
if (!(state->raid_devs[dev / 64] & (UINT64_C(1) << (dev % 64))))
log_error("Device #%u of %s array, %s, has failed.",
dev, status->raid_type, device);
state->raid_devs[dev / 64] |= (1 << (dev % 64));
state->raid_devs[dev / 64] |= (UINT64_C(1) << (dev % 64));
d++;
dead = 1;
}

View File

@@ -108,12 +108,6 @@ def call_lvm(command, debug=False):
if debug or process.returncode != 0:
_debug_c(command, process.returncode, (stdout_text, stderr_text))
if process.returncode == 0:
if cfg.args and cfg.args.debug and out[1] and len(out[1]) and \
'help' not in command:
log_error('WARNING: lvm is out-putting text to STDERR on success!')
_debug_c(command, process.returncode, (stdout_text, stderr_text))
return process.returncode, stdout_text, stderr_text
# The actual method which gets called to invoke the lvm command, can vary
@@ -485,7 +479,9 @@ def lvm_full_report_json():
'vg_name', 'pool_lv_uuid', 'pool_lv', 'origin_uuid',
'origin', 'data_percent',
'lv_attr', 'lv_tags', 'vg_uuid', 'lv_active', 'data_lv',
'metadata_lv', 'lv_parent', 'lv_role', 'lv_layout']
'metadata_lv', 'lv_parent', 'lv_role', 'lv_layout',
'snap_percent', 'metadata_percent', 'copy_percent',
'sync_percent', 'lv_metadata_size', 'move_pv', 'move_pv_uuid']
lv_seg_columns = ['seg_pe_ranges', 'segtype', 'lv_uuid']
@@ -735,7 +731,9 @@ def lv_retrieve_with_segments():
'origin', 'data_percent',
'lv_attr', 'lv_tags', 'vg_uuid', 'lv_active', 'data_lv',
'metadata_lv', 'seg_pe_ranges', 'segtype', 'lv_parent',
'lv_role', 'lv_layout']
'lv_role', 'lv_layout',
'snap_percent', 'metadata_percent', 'copy_percent',
'sync_percent', 'lv_metadata_size', 'move_pv', 'move_pv_uuid']
cmd = _dc('lvs', ['-a', '-o', ','.join(columns)])
rc, out, err = call(cmd)

View File

@@ -81,7 +81,14 @@ def lvs_state_retrieve(selection, cache_refresh=True):
n32(l['data_percent']), l['lv_attr'],
l['lv_tags'], l['lv_active'], l['data_lv'],
l['metadata_lv'], l['segtype'], l['lv_role'],
l['lv_layout']))
l['lv_layout'],
n32(l['snap_percent']),
n32(l['metadata_percent']),
n32(l['copy_percent']),
n32(l['sync_percent']),
n(l['lv_metadata_size']),
l['move_pv'],
l['move_pv_uuid']))
return rc
@@ -138,7 +145,9 @@ class LvState(State):
def __init__(self, Uuid, Name, Path, SizeBytes,
vg_name, vg_uuid, pool_lv_uuid, PoolLv,
origin_uuid, OriginLv, DataPercent, Attr, Tags, active,
data_lv, metadata_lv, segtypes, role, layout):
data_lv, metadata_lv, segtypes, role, layout, SnapPercent,
MetaDataPercent, CopyPercent, SyncPercent, MetaDataSizeBytes,
move_pv, move_pv_uuid):
utils.init_class_from_arguments(self)
# The segtypes is possibly an array with potentially dupes or a single
@@ -214,13 +223,20 @@ class LvState(State):
@utils.dbus_property(LV_COMMON_INTERFACE, 'Name', 's')
@utils.dbus_property(LV_COMMON_INTERFACE, 'Path', 's')
@utils.dbus_property(LV_COMMON_INTERFACE, 'SizeBytes', 't')
@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'SegType', 'as')
@utils.dbus_property(LV_COMMON_INTERFACE, 'Vg', 'o')
@utils.dbus_property(LV_COMMON_INTERFACE, 'OriginLv', 'o')
@utils.dbus_property(LV_COMMON_INTERFACE, 'PoolLv', 'o')
@utils.dbus_property(LV_COMMON_INTERFACE, 'Devices', "a(oa(tts))")
@utils.dbus_property(LV_COMMON_INTERFACE, 'HiddenLvs', "ao")
@utils.dbus_property(LV_COMMON_INTERFACE, 'Attr', 's')
@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'SnapPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'DataPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'MetaDataPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'CopyPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'SyncPercent', 'u')
@utils.dbus_property(LV_COMMON_INTERFACE, 'MetaDataSizeBytes', 't')
class LvCommon(AutomatedProperties):
_Tags_meta = ("as", LV_COMMON_INTERFACE)
_Roles_meta = ("as", LV_COMMON_INTERFACE)
@@ -236,12 +252,25 @@ class LvCommon(AutomatedProperties):
_FixedMinor_meta = ('b', LV_COMMON_INTERFACE)
_ZeroBlocks_meta = ('b', LV_COMMON_INTERFACE)
_SkipActivation_meta = ('b', LV_COMMON_INTERFACE)
_MovePv_meta = ('o', LV_COMMON_INTERFACE)
def _get_move_pv(self):
path = None
# It's likely that the move_pv is empty
if self.state.move_pv_uuid and self.state.move_pv:
path = cfg.om.get_object_path_by_uuid_lvm_id(
self.state.move_pv_uuid, self.state.move_pv)
if not path:
path = '/'
return path
# noinspection PyUnusedLocal,PyPep8Naming
def __init__(self, object_path, object_state):
super(LvCommon, self).__init__(object_path, lvs_state_retrieve)
self.set_interface(LV_COMMON_INTERFACE)
self.state = object_state
self._move_pv = self._get_move_pv()
@property
def VolumeType(self):
@@ -351,6 +380,10 @@ class LvCommon(AutomatedProperties):
def Active(self):
return dbus.Boolean(self.state.active == "active")
@property
def MovePv(self):
return dbus.ObjectPath(self._move_pv)
# noinspection PyPep8Naming
class Lv(LvCommon):

View File

@@ -75,6 +75,8 @@ class LVMShellProxy(object):
report += tmp.decode("utf-8")
if len(tmp) != 16384:
break
else:
break
elif r == self.lvm_shell.stderr.fileno():
while True:
@@ -84,6 +86,10 @@ class LVMShellProxy(object):
else:
break
# Check to see if the lvm process died on us
if self.lvm_shell.poll():
raise Exception(self.lvm_shell.returncode, "%s" % stderr)
except IOError as ioe:
log_debug(str(ioe))
pass
@@ -115,6 +121,10 @@ class LVMShellProxy(object):
local_env["LVM_REPORT_FD"] = "32"
local_env["LVM_COMMAND_PROFILE"] = "lvmdbusd"
# Disable the abort logic if lvm logs too much, which easily happens
# when utilizing the lvm shell.
local_env["LVM_LOG_FILE_MAX_LINES"] = "0"
flags = fcntl(self.report_r, F_GETFL)
fcntl(self.report_r, F_SETFL, flags | os.O_NONBLOCK)
@@ -123,20 +133,24 @@ class LVMShellProxy(object):
[LVM_CMD + " 32>%s" % tmp_file],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=local_env,
stderr=subprocess.PIPE, close_fds=True, shell=True)
flags = fcntl(self.lvm_shell.stdout, F_GETFL)
fcntl(self.lvm_shell.stdout, F_SETFL, flags | os.O_NONBLOCK)
flags = fcntl(self.lvm_shell.stderr, F_GETFL)
fcntl(self.lvm_shell.stderr, F_SETFL, flags | os.O_NONBLOCK)
# wait for the first prompt
errors = self._read_until_prompt()[2]
if errors and len(errors):
raise RuntimeError(errors)
try:
flags = fcntl(self.lvm_shell.stdout, F_GETFL)
fcntl(self.lvm_shell.stdout, F_SETFL, flags | os.O_NONBLOCK)
flags = fcntl(self.lvm_shell.stderr, F_GETFL)
fcntl(self.lvm_shell.stderr, F_SETFL, flags | os.O_NONBLOCK)
# These will get deleted when the FD count goes to zero so we can be
# sure to clean up correctly no matter how we finish
os.unlink(tmp_file)
os.rmdir(tmp_dir)
# wait for the first prompt
errors = self._read_until_prompt()[2]
if errors and len(errors):
raise RuntimeError(errors)
except:
raise
finally:
# These will get deleted when the FD count goes to zero so we can be
# sure to clean up correctly no matter how we finish
os.unlink(tmp_file)
os.rmdir(tmp_dir)
def get_error_msg(self):
# We got an error, lets go fetch the error message
@@ -171,6 +185,11 @@ class LVMShellProxy(object):
error_msg = ""
json_result = ""
if self.lvm_shell.poll():
raise Exception(
self.lvm_shell.returncode,
"Underlying lvm shell process is not present!")
# create the command string
cmd = " ".join(_quote_arg(arg) for arg in argv)
cmd += "\n"
@@ -222,7 +241,7 @@ if __name__ == "__main__":
end = time.time()
print(("RC: %d" % ret))
# print(("OUT:\n%s" % out))
print(("OUT:\n%s" % out))
print(("ERR:\n%s" % err))
print("Command = %f seconds" % (end - start))

View File

@@ -1249,8 +1249,8 @@ static int _update_metadata(lvmetad_state *s, const char *arg_name, const char *
const char *old_vgid = NULL;
const char *new_vgid = NULL;
const char *new_metadata_vgid;
int new_seq;
int old_seq = -1;
int new_seq = -1;
int needs_repair = 0;
int abort_daemon = 0;
int retval = 0;

View File

@@ -858,7 +858,7 @@ static void _choose_preferred_devs(struct cmd_context *cmd,
struct dm_list *add_cache_devs)
{
char uuid[64] __attribute__((aligned(8)));
const char *reason = "none";
const char *reason;
struct dm_list altdevs;
struct dm_list new_unused;
struct dev_types *dt = cmd->dev_types;

View File

@@ -88,9 +88,10 @@ struct cmd_context {
* Command line and arguments.
*/
const char *cmd_line;
const char *name; /* needed before cmd->command is set */
struct command *command;
char **argv;
struct arg_values *arg_values;
struct arg_values *opt_arg_values;
struct dm_list arg_value_groups;
/*

View File

@@ -61,7 +61,6 @@ struct logical_volume {
uint64_t timestamp;
unsigned new_lock_args:1;
unsigned process_specific:1; /* lv is identified specifically for processing */
const char *hostname;
const char *lock_args;
};

View File

@@ -956,7 +956,7 @@ static int _raid_add_images(struct logical_volume *lv,
int commit, int use_existing_area_len)
{
int rebuild_flag_cleared = 0;
struct lv_segment *seg = first_seg(lv);
struct lv_segment *seg;
uint32_t s;
if (!_raid_add_images_without_commit(lv, new_count, pvs, use_existing_area_len))

View File

@@ -472,7 +472,7 @@ static int _check_pool_create(const struct logical_volume *lv)
int update_pool_lv(struct logical_volume *lv, int activate)
{
int monitored = DMEVENTD_MONITOR_IGNORE;
int monitored;
int ret = 1;
if (!lv_is_thin_pool(lv)) {

View File

@@ -19,7 +19,6 @@
#include <assert.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>

View File

@@ -1228,7 +1228,10 @@ static int _canonicalize_field_ids(struct dm_report *rh)
return_0;
if (differs) {
canonical_field_dup = dm_pool_strdup(rh->mem, canonical_field);
if (!(canonical_field_dup = dm_pool_strdup(rh->mem, canonical_field))) {
log_error("_canonicalize_field_dup: dm_pool_alloc failed.");
return 0;
}
rh->canonical_field_ids[i] = canonical_field_dup;
} else
rh->canonical_field_ids[i] = rh->fields[i].id;

View File

@@ -4195,9 +4195,9 @@ static int _stats_add_extent(struct dm_pool *mem, struct fiemap_extent *fm_ext,
static struct _extent *_stats_get_extents_for_file(struct dm_pool *mem, int fd,
uint64_t *count)
{
uint64_t buf[STATS_FIE_BUF_LEN];
struct fiemap *fiemap = (struct fiemap *)buf;
struct fiemap_extent *fm_ext = &fiemap->fm_extents[0];
uint64_t *buf;
struct fiemap *fiemap = NULL;
struct fiemap_extent *fm_ext = NULL;
struct fiemap_extent fm_last = {0};
struct _extent *extents;
unsigned long long expected = 0;
@@ -4208,10 +4208,18 @@ static struct _extent *_stats_get_extents_for_file(struct dm_pool *mem, int fd,
int last = 0;
int rc;
memset(buf, 0, sizeof(buf));
buf = dm_zalloc(STATS_FIE_BUF_LEN);
if (!buf) {
log_error("Could not allocate memory for FIEMAP buffer.");
return NULL;
}
/* initialise pointers into the ioctl buffer. */
fiemap = (struct fiemap *) buf;
fm_ext = &fiemap->fm_extents[0];
/* space available per ioctl */
*count = (sizeof(buf) - sizeof(*fiemap))
*count = (STATS_FIE_BUF_LEN - sizeof(*fiemap))
/ sizeof(struct fiemap_extent);
/* grow temporary extent table in the pool */
@@ -4277,9 +4285,16 @@ static struct _extent *_stats_get_extents_for_file(struct dm_pool *mem, int fd,
/* return total number of extents */
*count = tot_extents;
return dm_pool_end_object(mem);
extents = dm_pool_end_object(mem);
/* free FIEMAP buffer. */
dm_free(buf);
return extents;
bad:
dm_pool_abandon_object(mem);
dm_free(buf);
return NULL;
}

View File

@@ -609,9 +609,6 @@ of device-mapper devices.
%if %{enable_systemd}
systemctl preset dm-event.socket > /dev/null 2>&1 || :
%endif
if [ -e %{_default_pid_dir}/dmeventd.pid ]; then
%{_sbindir}/dmeventd -R || echo "Failed to restart dmeventd daemon. Please, try manual restart."
fi
%preun -n device-mapper-event
%if %{enable_systemd}
@@ -626,6 +623,11 @@ if [ $1 = 0 ]; then
%daemon_reload
fi
%posttrans -n device-mapper-event
if [ -e %{_default_pid_dir}/dmeventd.pid ]; then
%{_sbindir}/dmeventd -R || echo "Failed to restart dmeventd daemon. Please, try manual restart."
fi
%files -n device-mapper-event
%defattr(-,root,root,-)
%{_sbindir}/dmeventd

View File

@@ -18,5 +18,15 @@ SKIP_WITH_CLVMD=1
aux prepare_pvs 6
# We need the lvmdbusd.profile for the daemon to utilize JSON
# output
mkdir -p $TESTDIR/etc/profile/
cp -v $TESTOLDPWD/../conf/lvmdbusd.profile $TESTDIR/etc/profile/.
# Need to set this up so that the lvmdbusd service knows which
# binary to be running, which should be the one we just built
export LVM_BINARY=$TESTOLDPWD/../tools/lvm
aux prepare_lvmdbusd
$test_data_dir/dbus/lvmdbustest.py -v

View File

@@ -9,6 +9,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# noinspection PyUnresolvedReferences
import dbus
# noinspection PyUnresolvedReferences
from dbus.mainloop.glib import DBusGMainLoop
@@ -21,6 +22,8 @@ from testlib import *
g_tmo = 0
g_prefix = os.getenv('PREFIX', '')
use_session = os.getenv('LVMDBUSD_USE_SESSION', False)
if use_session:
@@ -29,10 +32,28 @@ else:
bus = dbus.SystemBus(mainloop=DBusGMainLoop())
def std_err_print(*args):
sys.stderr.write(' '.join(map(str, args)) + '\n')
sys.stderr.flush()
def vg_n():
return g_prefix + rs(8, '_vg')
def lv_n(suffix=None):
if not suffix:
s = '_lv'
else:
s = suffix
return g_prefix + rs(8, s)
def get_objects():
rc = {MANAGER_INT: [], PV_INT: [], VG_INT: [], LV_INT: [],
THINPOOL_INT: [], JOB_INT: [], SNAPSHOT_INT: [], LV_COMMON_INT: [],
CACHE_POOL_INT: [], CACHE_LV_INT: []}
rc = {
MANAGER_INT: [], PV_INT: [], VG_INT: [], LV_INT: [],
THINPOOL_INT: [], JOB_INT: [], SNAPSHOT_INT: [], LV_COMMON_INT: [],
CACHE_POOL_INT: [], CACHE_LV_INT: []}
manager = dbus.Interface(bus.get_object(
BUSNAME, "/com/redhat/lvmdbus1"),
@@ -63,14 +84,14 @@ class TestDbusService(unittest.TestCase):
# we are not mucking with someones data on their system
self.objs, self.bus = get_objects()
if len(self.objs[PV_INT]) == 0:
print('No PVs present exiting!')
std_err_print('No PVs present exiting!')
sys.exit(1)
if len(self.objs[MANAGER_INT]) != 1:
print('Expecting a manager object!')
std_err_print('Expecting a manager object!')
sys.exit(1)
if len(self.objs[VG_INT]) != 0:
print('Expecting no VGs to exist!')
std_err_print('Expecting no VGs to exist!')
sys.exit(1)
self.pvs = []
@@ -141,7 +162,7 @@ class TestDbusService(unittest.TestCase):
if not pv_paths:
pv_paths = [self.objs[PV_INT][0].object_path]
vg_name = rs(8, '_vg')
vg_name = vg_n()
vg_path = self.handle_return(
self.objs[MANAGER_INT][0].Manager.VgCreate(
@@ -270,7 +291,7 @@ class TestDbusService(unittest.TestCase):
if len(self.objs[PV_INT]) >= 2:
vg = self._vg_create(
[self.objs[PV_INT][0].object_path,
self.objs[PV_INT][1].object_path]).Vg
self.objs[PV_INT][1].object_path]).Vg
path = self.handle_return(
vg.Reduce(False, [vg.Pvs[0]], g_tmo, {})
@@ -319,12 +340,14 @@ class TestDbusService(unittest.TestCase):
for l in lv_paths:
lv_proxy = ClientProxy(self.bus, l).LvCommon
self.assertTrue(lv_proxy.Vg == vg.object_path, "%s != %s" %
(lv_proxy.Vg, vg.object_path))
self.assertTrue(
lv_proxy.Vg == vg.object_path, "%s != %s" %
(lv_proxy.Vg, vg.object_path))
full_name = "%s/%s" % (new_name, lv_proxy.Name)
lv_path = mgr.LookUpByLvmId(full_name)
self.assertTrue(lv_path == lv_proxy.object_path, "%s != %s" %
(lv_path, lv_proxy.object_path))
self.assertTrue(
lv_path == lv_proxy.object_path, "%s != %s" %
(lv_path, lv_proxy.object_path))
def _verify_hidden_lookups(self, lv_common_object, vgname):
mgr = self.objs[MANAGER_INT][0].Manager
@@ -362,7 +385,7 @@ class TestDbusService(unittest.TestCase):
self._verify_hidden_lookups(thin_pool.LvCommon, vg_name_start)
for i in range(0, 5):
lv_name = rs(8, '_lv')
lv_name = lv_n()
thin_lv_path = self.handle_return(
thin_pool.ThinPool.LvCreate(
@@ -373,8 +396,9 @@ class TestDbusService(unittest.TestCase):
full_name = "%s/%s" % (vg_name_start, lv_name)
lookup_lv_path = mgr.LookUpByLvmId(full_name)
self.assertTrue(thin_lv_path == lookup_lv_path,
"%s != %s" % (thin_lv_path, lookup_lv_path))
self.assertTrue(
thin_lv_path == lookup_lv_path,
"%s != %s" % (thin_lv_path, lookup_lv_path))
# Rename the VG
new_name = 'renamed_' + vg.Name
@@ -392,13 +416,15 @@ class TestDbusService(unittest.TestCase):
for l in lv_paths:
lv_proxy = ClientProxy(self.bus, l).LvCommon
self.assertTrue(lv_proxy.Vg == vg.object_path, "%s != %s" %
(lv_proxy.Vg, vg.object_path))
self.assertTrue(
lv_proxy.Vg == vg.object_path, "%s != %s" %
(lv_proxy.Vg, vg.object_path))
full_name = "%s/%s" % (new_name, lv_proxy.Name)
# print('Full Name %s' % (full_name))
lv_path = mgr.LookUpByLvmId(full_name)
self.assertTrue(lv_path == lv_proxy.object_path, "%s != %s" %
(lv_path, lv_proxy.object_path))
self.assertTrue(
lv_path == lv_proxy.object_path, "%s != %s" %
(lv_path, lv_proxy.object_path))
# noinspection PyTypeChecker
self._verify_hidden_lookups(thin_pool.LvCommon, new_name)
@@ -424,14 +450,14 @@ class TestDbusService(unittest.TestCase):
vg = self._vg_create().Vg
self._test_lv_create(
vg.LvCreate,
(rs(8, '_lv'), mib(4),
dbus.Array([], '(ott)'), g_tmo, {}), vg)
(lv_n(), mib(4),
dbus.Array([], '(ott)'), g_tmo, {}), vg)
def test_lv_create_job(self):
vg = self._vg_create().Vg
(object_path, job_path) = vg.LvCreate(rs(8, '_lv'), mib(4),
dbus.Array([], '(ott)'), 0, {})
(object_path, job_path) = vg.LvCreate(
lv_n(), mib(4), dbus.Array([], '(ott)'), 0, {})
self.assertTrue(object_path == '/')
self.assertTrue(job_path != '/')
@@ -443,7 +469,7 @@ class TestDbusService(unittest.TestCase):
vg = self._vg_create().Vg
self._test_lv_create(
vg.LvCreateLinear,
(rs(8, '_lv'), mib(4), False, g_tmo, {}), vg)
(lv_n(), mib(4), False, g_tmo, {}), vg)
def test_lv_create_striped(self):
pv_paths = []
@@ -452,9 +478,7 @@ class TestDbusService(unittest.TestCase):
vg = self._vg_create(pv_paths).Vg
self._test_lv_create(
vg.LvCreateStriped,
(rs(8, '_lv'), mib(4), 2, 8, False,
g_tmo, {}), vg)
vg.LvCreateStriped, (lv_n(), mib(4), 2, 8, False, g_tmo, {}), vg)
def test_lv_create_mirror(self):
pv_paths = []
@@ -462,8 +486,8 @@ class TestDbusService(unittest.TestCase):
pv_paths.append(pp.object_path)
vg = self._vg_create(pv_paths).Vg
self._test_lv_create(vg.LvCreateMirror,
(rs(8, '_lv'), mib(4), 2, g_tmo, {}), vg)
self._test_lv_create(
vg.LvCreateMirror, (lv_n(), mib(4), 2, g_tmo, {}), vg)
def test_lv_create_raid(self):
pv_paths = []
@@ -471,9 +495,8 @@ class TestDbusService(unittest.TestCase):
pv_paths.append(pp.object_path)
vg = self._vg_create(pv_paths).Vg
self._test_lv_create(vg.LvCreateRaid,
(rs(8, '_lv'), 'raid4',
mib(16), 2, 8, g_tmo, {}), vg)
self._test_lv_create(
vg.LvCreateRaid, (lv_n(), 'raid4', mib(16), 2, 8, g_tmo, {}), vg)
def _create_lv(self, thinpool=False, size=None, vg=None):
@@ -489,7 +512,7 @@ class TestDbusService(unittest.TestCase):
return self._test_lv_create(
vg.LvCreateLinear,
(rs(8, '_lv'), size, thinpool, g_tmo, {}), vg)
(lv_n(), size, thinpool, g_tmo, {}), vg)
def test_lv_create_rounding(self):
self._create_lv(size=(mib(2) + 13))
@@ -516,8 +539,9 @@ class TestDbusService(unittest.TestCase):
def test_lv_thinpool_rename(self):
# Rename a thin pool
tp = self._create_lv(True)
self.assertTrue(THINPOOL_LV_PATH in tp.object_path,
"%s" % (tp.object_path))
self.assertTrue(
THINPOOL_LV_PATH in tp.object_path,
"%s" % (tp.object_path))
new_name = 'renamed_' + tp.LvCommon.Name
self.handle_return(tp.Lv.Rename(new_name, g_tmo, {}))
@@ -535,7 +559,7 @@ class TestDbusService(unittest.TestCase):
thin_path = self.handle_return(
tp.ThinPool.LvCreate(
rs(10, '_thin_lv'), mib(8), g_tmo, {})
lv_n('_thin_lv'), mib(8), g_tmo, {})
)
lv = ClientProxy(self.bus, thin_path)
@@ -593,11 +617,13 @@ class TestDbusService(unittest.TestCase):
pv = vg.Pvs
pv_proxy = ClientProxy(self.bus, pv[0])
pvp = ClientProxy(self.bus, pv[0])
self._test_lv_create(vg.LvCreate, (rs(8, '_lv'), mib(4),
dbus.Array([[pv_proxy.object_path, 0, (pv_proxy.Pv.PeCount - 1)]],
'(ott)'), g_tmo, {}), vg)
self._test_lv_create(
vg.LvCreate,
(lv_n(), mib(4),
dbus.Array([[pvp.object_path, 0, (pvp.Pv.PeCount - 1)]],
'(ott)'), g_tmo, {}), vg)
def test_lv_resize(self):
@@ -627,8 +653,8 @@ class TestDbusService(unittest.TestCase):
rc = self.handle_return(
lv.Lv.Resize(
size,
dbus.Array([[p.object_path, 0, p.Pv.PeCount - 1]],
'(oii)'),
dbus.Array(
[[p.object_path, 0, p.Pv.PeCount - 1]], '(oii)'),
g_tmo, {}))
else:
rc = self.handle_return(
@@ -655,8 +681,8 @@ class TestDbusService(unittest.TestCase):
lv = self._create_lv(vg=vg)
with self.assertRaises(dbus.exceptions.DBusException):
lv.Lv.Resize(lv.LvCommon.SizeBytes, dbus.Array([], '(oii)'),
-1, {})
lv.Lv.Resize(
lv.LvCommon.SizeBytes, dbus.Array([], '(oii)'), -1, {})
def test_lv_move(self):
lv = self._create_lv()
@@ -674,8 +700,8 @@ class TestDbusService(unittest.TestCase):
lv.update()
new_pv = str(lv.LvCommon.Devices[0][0])
self.assertTrue(pv_path_move != new_pv, "%s == %s" %
(pv_path_move, new_pv))
self.assertTrue(
pv_path_move != new_pv, "%s == %s" % (pv_path_move, new_pv))
def test_lv_activate_deactivate(self):
lv_p = self._create_lv()
@@ -740,7 +766,7 @@ class TestDbusService(unittest.TestCase):
for pp in self.objs[PV_INT]:
pv_paths.append(pp.object_path)
vg_name = rs(8, '_vg')
vg_name = vg_n()
# Test getting a job right away
vg_path, vg_job = self.objs[MANAGER_INT][0].Manager.VgCreate(
@@ -770,7 +796,7 @@ class TestDbusService(unittest.TestCase):
if vg_proxy.Vg.FreeCount > 0:
job = self.handle_return(
vg_proxy.Vg.LvCreateLinear(
rs(8, "_lv"), mib(4), False, g_tmo, {}))
lv_n(), mib(4), False, g_tmo, {}))
self.assertTrue(job != '/')
else:
# We ran out of space, test will probably fail
@@ -803,12 +829,17 @@ class TestDbusService(unittest.TestCase):
yes = False
for pp in self.objs[PV_INT]:
if '/dev/sd' not in pp.Pv.Name:
std_err_print("Skipping test_job_handling_timer on loopback")
return
# This may not pass
for i in [48, 64, 128]:
yes = self._test_expired_timer(i)
if yes:
break
print('Attempt (%d) failed, trying again...' % (i))
std_err_print('Attempt (%d) failed, trying again...' % (i))
self.assertTrue(yes)
@@ -861,7 +892,7 @@ class TestDbusService(unittest.TestCase):
vg = self._vg_create().Vg
lv = self._test_lv_create(
vg.LvCreateLinear,
(rs(8, '_lv'), mib(4), False, g_tmo, {}),
(lv_n(), mib(4), False, g_tmo, {}),
vg)
t = ['Testing', 'tags']
@@ -899,8 +930,9 @@ class TestDbusService(unittest.TestCase):
vg.MaxPvSet(p, g_tmo, {}))
self.assertEqual(rc, '/')
vg.update()
self.assertTrue(vg.MaxPv == p, "Expected %s != Actual %s" %
(str(p), str(vg.MaxPv)))
self.assertTrue(
vg.MaxPv == p,
"Expected %s != Actual %s" % (str(p), str(vg.MaxPv)))
def test_vg_max_lv(self):
vg = self._vg_create().Vg
@@ -911,14 +943,15 @@ class TestDbusService(unittest.TestCase):
rc = self.handle_return(vg.MaxLvSet(p, g_tmo, {}))
self.assertEqual(rc, '/')
vg.update()
self.assertTrue(vg.MaxLv == p, "Expected %s != Actual %s" %
(str(p), str(vg.MaxLv)))
self.assertTrue(
vg.MaxLv == p,
"Expected %s != Actual %s" % (str(p), str(vg.MaxLv)))
def test_vg_uuid_gen(self):
# TODO renable test case when
# https://bugzilla.redhat.com/show_bug.cgi?id=1264169 gets fixed
# This was tested with lvmetad disabled and we passed
print("\nSkipping Vg.UuidGenerate until BZ: 1264169 resolved\n")
std_err_print("\nSkipping Vg.UuidGenerate until BZ: 1264169 resolved\n")
if False:
vg = self._vg_create().Vg
@@ -926,14 +959,15 @@ class TestDbusService(unittest.TestCase):
rc = self.handle_return(vg.UuidGenerate(g_tmo, {}))
self.assertEqual(rc, '/')
vg.update()
self.assertTrue(vg.Uuid != prev_uuid, "Expected %s != Actual %s" %
(vg.Uuid, prev_uuid))
self.assertTrue(
vg.Uuid != prev_uuid,
"Expected %s != Actual %s" % (vg.Uuid, prev_uuid))
def test_vg_activate_deactivate(self):
vg = self._vg_create().Vg
self._test_lv_create(
vg.LvCreateLinear,
(rs(8, '_lv'), mib(4), False, g_tmo, {}),
(lv_n(), mib(4), False, g_tmo, {}),
vg)
vg.update()
@@ -1008,8 +1042,9 @@ class TestDbusService(unittest.TestCase):
self.assertEqual(
self.handle_return(
mgr.PvScan(False, True, dbus.Array([], 's'),
dbus.Array([], '(ii)'), g_tmo, {})), '/')
mgr.PvScan(
False, True, dbus.Array([], 's'),
dbus.Array([], '(ii)'), g_tmo, {})), '/')
self.assertEqual(self._refresh(), 0)
self.assertEqual(
@@ -1039,13 +1074,8 @@ class TestDbusService(unittest.TestCase):
mm.append((int(d.properties['MAJOR']), int(d.properties['MINOR'])))
self.assertEqual(
self.handle_return(
mgr.PvScan
(False, True,
block_path,
mm, g_tmo, {})
), '/')
mgr.PvScan(False, True, block_path, mm, g_tmo, {})), '/')
self.assertEqual(self._refresh(), 0)
@@ -1092,7 +1122,7 @@ class TestDbusService(unittest.TestCase):
thin_path = self.handle_return(
tp.ThinPool.LvCreate(
rs(10, '_thin_lv'), mib(10), g_tmo, {}))
lv_n('_thin_lv'), mib(10), g_tmo, {}))
lv_p = ClientProxy(self.bus, thin_path)
@@ -1126,8 +1156,8 @@ class TestDbusService(unittest.TestCase):
vg, cache_pool = self._create_cache_pool()
self.assertTrue('/com/redhat/lvmdbus1/CachePool' in
cache_pool.object_path)
self.assertTrue(
'/com/redhat/lvmdbus1/CachePool' in cache_pool.object_path)
def test_cache_lv_create(self):
@@ -1143,11 +1173,10 @@ class TestDbusService(unittest.TestCase):
cached_lv = ClientProxy(self.bus, c_lv_path)
uncached_lv_path = self.handle_return(
cached_lv.CachedLv.DetachCachePool(
destroy_cache, g_tmo, {}))
cached_lv.CachedLv.DetachCachePool(destroy_cache, g_tmo, {}))
self.assertTrue('/com/redhat/lvmdbus1/Lv' in
uncached_lv_path)
self.assertTrue(
'/com/redhat/lvmdbus1/Lv' in uncached_lv_path)
rc = self.handle_return(vg.Remove(g_tmo, {}))
self.assertTrue(rc == '/')
@@ -1209,22 +1238,24 @@ class TestDbusService(unittest.TestCase):
with self.assertRaises(dbus.exceptions.DBusException):
self.handle_return(
vg_proxy.Vg.LvCreateLinear(
rs(8, '_lv') + c,
lv_n() + c,
mib(4), False, g_tmo, {}))
for r in ("_cdata", "_cmeta", "_corig", "_mimage", "_mlog",
"_pmspare", "_rimage", "_rmeta", "_tdata", "_tmeta", "_vorigin"):
for reserved in (
"_cdata", "_cmeta", "_corig", "_mimage", "_mlog",
"_pmspare", "_rimage", "_rmeta", "_tdata", "_tmeta",
"_vorigin"):
with self.assertRaises(dbus.exceptions.DBusException):
self.handle_return(
vg_proxy.Vg.LvCreateLinear(
rs(8, '_lv') + r,
lv_n() + reserved,
mib(4), False, g_tmo, {}))
for r in ("snapshot", "pvmove"):
for reserved in ("snapshot", "pvmove"):
with self.assertRaises(dbus.exceptions.DBusException):
self.handle_return(
vg_proxy.Vg.LvCreateLinear(
r + rs(8, '_lv'),
reserved + lv_n(),
mib(4), False, g_tmo, {}))
_ALLOWABLE_TAG_CH = string.ascii_letters + string.digits + "._-+/=!:&#"
@@ -1264,16 +1295,18 @@ class TestDbusService(unittest.TestCase):
for i in range(1, 64):
tag = rs(i, "", self._ALLOWABLE_TAG_CH)
r = self.handle_return(
tmp = self.handle_return(
vg_proxy.Vg.TagsAdd([tag], g_tmo, {}))
self.assertTrue(r == '/')
self.assertTrue(tmp == '/')
vg_proxy.update()
self.assertTrue(tag in vg_proxy.Vg.Tags, "%s not in %s" %
(tag, str(vg_proxy.Vg.Tags)))
self.assertTrue(
tag in vg_proxy.Vg.Tags,
"%s not in %s" % (tag, str(vg_proxy.Vg.Tags)))
self.assertEqual(i, len(vg_proxy.Vg.Tags), "%d != %d" %
(i, len(vg_proxy.Vg.Tags)))
self.assertEqual(
i, len(vg_proxy.Vg.Tags),
"%d != %d" % (i, len(vg_proxy.Vg.Tags)))
def test_tag_regression(self):
mgr = self.objs[MANAGER_INT][0].Manager
@@ -1285,17 +1318,39 @@ class TestDbusService(unittest.TestCase):
tag = '--h/K.6g0A4FOEatf3+k_nI/Yp&L_u2oy-=j649x:+dUcYWPEo6.IWT0c'
r = self.handle_return(
tmp = self.handle_return(
vg_proxy.Vg.TagsAdd([tag], g_tmo, {})
)
self.assertTrue(r == '/')
self.assertTrue(tmp == '/')
vg_proxy.update()
self.assertTrue(tag in vg_proxy.Vg.Tags, "%s not in %s" %
(tag, str(vg_proxy.Vg.Tags)))
self.assertTrue(
tag in vg_proxy.Vg.Tags,
"%s not in %s" % (tag, str(vg_proxy.Vg.Tags)))
class AggregateResults(object):
def __init__(self):
self.no_errors = True
def register_result(self, result):
if not result.result.wasSuccessful():
self.no_errors = False
def register_fail(self):
self.no_errors = False
def exit_run(self):
if self.no_errors:
sys.exit(0)
sys.exit(1)
if __name__ == '__main__':
r = AggregateResults()
# Test forking & exec new each time
test_shell = os.getenv('LVM_DBUS_TEST_SHELL', 1)
@@ -1303,20 +1358,24 @@ if __name__ == '__main__':
set_execution(False)
if int(test_shell) == 0:
print('\n Shortened fork & exec test ***\n')
unittest.main(exit=True)
std_err_print('\n Running only lvm fork & exec test ***\n')
r.register_result(unittest.main(exit=False))
else:
print('\n *** Testing fork & exec *** \n')
unittest.main(exit=False)
std_err_print('\n *** Testing with lvm fork & exec *** \n')
r.register_result(unittest.main(exit=False))
g_tmo = 15
unittest.main(exit=False)
r.register_result(unittest.main(exit=False))
# Test lvm shell
print('\n *** Testing lvm shell *** \n')
std_err_print('\n *** Testing with lvm shell *** \n')
if set_execution(True):
g_tmo = 0
unittest.main(exit=False)
r.register_result(unittest.main(exit=False))
g_tmo = 15
unittest.main()
r.register_result(unittest.main(exit=False))
else:
print("WARNING: Unable to dynamically configure "
"service to use lvm shell!")
r.register_fail()
std_err_print(
"ERROR: Unable to dynamically configure service to use "
"lvm shell!")
r.exit_run()

View File

@@ -32,8 +32,7 @@ THINPOOL_LV_PATH = '/' + THINPOOL_INT.replace('.', '/')
def rs(length, suffix, character_set=string.ascii_lowercase):
return ''.join(random.choice(character_set)
for _ in range(length)) + suffix
return ''.join(random.choice(character_set) for _ in range(length)) + suffix
def mib(s):
@@ -50,8 +49,7 @@ class DbusIntrospection(object):
for c in root:
if c.tag == "interface":
in_f = c.attrib['name']
interfaces[in_f] = \
dict(methods=OrderedDict(), properties={})
interfaces[in_f] = dict(methods=OrderedDict(), properties={})
for nested in c:
if nested.tag == "method":
mn = nested.attrib['name']
@@ -71,7 +69,8 @@ class DbusIntrospection(object):
v = dict(
name=mn,
a_dir=arg_dir,
a_type=arg_type)
a_type=arg_type
)
interfaces[in_f]['methods'][mn][n] = v
elif nested.tag == 'property':
@@ -148,10 +147,9 @@ def verify_type(value, dbus_str_rep):
# print("%s ~= %s" % (dbus_str_rep, actual_str_rep))
# Unless we have a full filled out type we won't match exactly
if not dbus_str_rep.startswith(actual_str_rep):
raise RuntimeError("Incorrect type, expected= %s actual "
"= %s object= %s" %
(dbus_str_rep, actual_str_rep,
str(type(value))))
raise RuntimeError(
"Incorrect type, expected= %s actual = %s object= %s" %
(dbus_str_rep, actual_str_rep, str(type(value))))
class RemoteObject(object):
@@ -174,12 +172,14 @@ class RemoteObject(object):
if props:
for kl, vl in list(props.items()):
# Verify type is correct!
verify_type(vl,
verify_type(
vl,
self.introspect[self.interface]['properties'][kl]['p_type'])
setattr(self, kl, vl)
def __init__(self, specified_bus, object_path, interface, introspect,
properties=None):
def __init__(
self, specified_bus, object_path, interface, introspect,
properties=None):
self.object_path = object_path
self.interface = interface
self.bus = specified_bus
@@ -238,11 +238,11 @@ class ClientProxy(object):
# print('Client proxy has interface: %s %s' % (k, sn))
if interface and interface == k and props is not None:
ro = RemoteObject(specified_bus, object_path, k,
self.intro_spect, props)
ro = RemoteObject(
specified_bus, object_path, k, self.intro_spect, props)
else:
ro = RemoteObject(specified_bus, object_path, k,
self.intro_spect)
ro = RemoteObject(
specified_bus, object_path, k, self.intro_spect)
setattr(self, sn, ro)

View File

@@ -325,8 +325,8 @@ prepare_lvmdbusd() {
daemon="$(which lvmdbusd || :)"
fi
[[ -n $daemon && -x $daemon ]] || skip "The daemon is missing"
which python3 >/dev/null || skip "Missing python3"
python3 -c "import pyudev, dbus, gi.repository" || skip "Missing python modules"
# Copy the needed file to run on the system bus if it doesn't
@@ -336,6 +336,8 @@ prepare_lvmdbusd() {
fi
echo "preparing lvmdbusd..."
lvmconf "global/notify_dbus = 1"
"$daemon" --debug > debug.log_LVMDBUSD_out 2>&1 &
local pid=$!
@@ -1079,6 +1081,7 @@ devices/global_filter = [ "a|$DM_DEV_DIR/mapper/.*pv[0-9_]*$|", "r|.*|" ]
devices/md_component_detection = 0
devices/scan = "$DM_DEV_DIR"
devices/sysfs_scan = 1
devices/write_cache_state = 0
global/abort_on_internal_errors = 1
global/cache_check_executable = "$LVM_TEST_CACHE_CHECK_CMD"
global/cache_dump_executable = "$LVM_TEST_CACHE_DUMP_CMD"
@@ -1088,6 +1091,7 @@ global/fallback_to_local_locking = 0
global/library_dir = "$TESTDIR/lib"
global/locking_dir = "$TESTDIR/var/lock/lvm"
global/locking_type=$LVM_TEST_LOCKING
global/notify_dbus = 0
global/si_unit_consistency = 1
global/thin_check_executable = "$LVM_TEST_THIN_CHECK_CMD"
global/thin_dump_executable = "$LVM_TEST_THIN_DUMP_CMD"

View File

@@ -81,7 +81,8 @@ 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
invalid lvscan "$dev1"
# ignores unused positional arg dev1
lvscan "$dev1"
lvdisplay --maps
lvscan --all
@@ -108,13 +109,16 @@ vgmknodes --refresh
lvscan
lvmdiskscan
invalid pvscan "$dev1"
# ignores unused arg
pvscan "$dev1"
invalid pvscan -aay
invalid pvscan --major 254
invalid pvscan --minor 0
invalid pvscan --novolumegroup -e
invalid vgscan $vg
invalid lvscan $vg
# ignores unsed arg
vgscan $vg
# ignroes unused arg
lvscan $vg
if aux have_readline; then
cat <<EOF | lvm

View File

@@ -56,7 +56,7 @@ fail lvcreate -l 1 --cachepool pool8 $vg
# no size specified
invalid lvcreate --cachepool pool $vg 2>&1 | tee err
grep "specify either size or extents" err
# grep "specify either size or extents" err
# Check nothing has been created yet
check vg_field $vg lv_count 0

View File

@@ -42,6 +42,7 @@ dmsetup suspend $vg-$lv1
# now this should pass without blocking
dmsetup suspend --noflush --nolockfs $vg1-snap &
DMPID=$!
#dmsetup suspend $vg1-snap &
sleep .5
@@ -55,20 +56,28 @@ dmsetup resume $vg-$lv1
# otherwise --noudevsync would be needed
dmsetup resume $vg1-snap
# Expecting success from 'dmsetup'
wait $DMPID
# Try how force removal works
dmsetup suspend $vg-$lv1
# needs to fail as device is still open
not dmsetup remove --force $vg1-snap &
DMPID=$!
# on older snapshot target 'remove' will wait till $lv1 is resumed
if aux target_at_least dm-snapshot 1 6 0 ; then
sleep .5
dmsetup table $vg1-snap | tee out
should grep -i error out
fi
dmsetup resume $vg-$lv1
wait
# Expecting success from 'not dmsetup'
wait $DMPID
# check it really is now 'error' target
dmsetup table $vg1-snap | tee out

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

@@ -17,215 +17,214 @@
* Put all long args that don't have a corresponding short option first.
*/
/* *INDENT-OFF* */
arg(abort_ARG, '\0', "abort", NULL, 0, 0)
arg(activationmode_ARG, '\0', "activationmode", string_arg, 0, 0)
arg(addtag_ARG, '\0', "addtag", tag_arg, ARG_GROUPABLE, 0)
arg(aligned_ARG, '\0', "aligned", NULL, 0, 0)
arg(alloc_ARG, '\0', "alloc", alloc_arg, 0, 0)
arg(atomic_ARG, '\0', "atomic", NULL, 0, 0)
arg(atversion_ARG, '\0', "atversion", string_arg, 0, 0)
arg(binary_ARG, '\0', "binary", NULL, 0, 0)
arg(bootloaderareasize_ARG, '\0', "bootloaderareasize", size_mb_arg, 0, 0)
arg(cache_long_ARG, '\0', "cache", NULL, 0, 0)
arg(cachemode_ARG, '\0', "cachemode", cachemode_arg, 0, 0)
arg(cachepool_ARG, '\0', "cachepool", string_arg, 0, 0)
arg(commandprofile_ARG, '\0', "commandprofile", string_arg, 0, 0)
arg(config_ARG, '\0', "config", string_arg, 0, 0)
arg(configreport_ARG, '\0', "configreport", string_arg, ARG_GROUPABLE, 1)
arg(configtype_ARG, '\0', "type", string_arg, 0, 0)
arg(corelog_ARG, '\0', "corelog", NULL, 0, 0)
arg(dataalignment_ARG, '\0', "dataalignment", size_kb_arg, 0, 0)
arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", size_kb_arg, 0, 0)
arg(deltag_ARG, '\0', "deltag", tag_arg, ARG_GROUPABLE, 0)
arg(detachprofile_ARG, '\0', "detachprofile", NULL, 0, 0)
arg(discards_ARG, '\0', "discards", discards_arg, 0, 0)
arg(driverloaded_ARG, '\0', "driverloaded", yes_no_arg, 0, 0)
arg(errorwhenfull_ARG, '\0', "errorwhenfull", yes_no_arg, 0, 0)
arg(force_long_ARG, '\0', "force", NULL, ARG_COUNTABLE, 0)
arg(foreign_ARG, '\0', "foreign", NULL, 0, 0)
arg(handlemissingpvs_ARG, '\0', "handlemissingpvs", NULL, 0, 0)
arg(ignoreadvanced_ARG, '\0', "ignoreadvanced", NULL, 0, 0)
arg(ignorelocal_ARG, '\0', "ignorelocal", NULL, 0, 0)
arg(ignorelockingfailure_ARG, '\0', "ignorelockingfailure", NULL, 0, 0)
arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", NULL, 0, 0)
arg(ignoreskippedcluster_ARG, '\0', "ignoreskippedcluster", NULL, 0, 0)
arg(ignoreunsupported_ARG, '\0', "ignoreunsupported", NULL, 0, 0)
arg(labelsector_ARG, '\0', "labelsector", int_arg, 0, 0)
arg(lockopt_ARG, '\0', "lockopt", string_arg, 0, 0)
arg(lockstart_ARG, '\0', "lockstart", NULL, 0, 0)
arg(lockstop_ARG, '\0', "lockstop", NULL, 0, 0)
arg(locktype_ARG, '\0', "locktype", locktype_arg, 0, 0)
arg(logonly_ARG, '\0', "logonly", NULL, 0, 0)
arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", size_kb_arg, 0, 0)
arg(merge_ARG, '\0', "merge", NULL, 0, 0)
arg(mergedconfig_ARG, '\0', "mergedconfig", NULL, 0, 0)
arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_arg, 0, 0)
arg(metadataignore_ARG, '\0', "metadataignore", yes_no_arg, 0, 0)
arg(metadataprofile_ARG, '\0', "metadataprofile", string_arg, 0, 0)
arg(metadatasize_ARG, '\0', "metadatasize", size_mb_arg, 0, 0)
arg(minor_ARG, '\0', "minor", int_arg, ARG_GROUPABLE, 0)
arg(minrecoveryrate_ARG, '\0', "minrecoveryrate", size_kb_arg, 0, 0)
arg(mirrorlog_ARG, '\0', "mirrorlog", mirrorlog_arg, 0, 0)
arg(mirrorsonly_ARG, '\0', "mirrorsonly", NULL, 0, 0)
arg(mknodes_ARG, '\0', "mknodes", NULL, 0, 0)
arg(monitor_ARG, '\0', "monitor", yes_no_arg, 0, 0)
arg(nameprefixes_ARG, '\0', "nameprefixes", NULL, 0, 0)
arg(noheadings_ARG, '\0', "noheadings", NULL, 0, 0)
arg(nohistory_ARG, '\0', "nohistory", NULL, 0, 0)
arg(nolocking_ARG, '\0', "nolocking", NULL, 0, 0)
arg(norestorefile_ARG, '\0', "norestorefile", NULL, 0, 0)
arg(nosuffix_ARG, '\0', "nosuffix", NULL, 0, 0)
arg(nosync_ARG, '\0', "nosync", NULL, 0, 0)
arg(notifydbus_ARG, '\0', "notifydbus", NULL, 0, 0)
arg(noudevsync_ARG, '\0', "noudevsync", NULL, 0, 0)
arg(originname_ARG, '\0', "originname", string_arg, 0, 0)
arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", size_mb_arg, 0, 0)
arg(poll_ARG, '\0', "poll", yes_no_arg, 0, 0)
arg(polloperation_ARG, '\0', "polloperation", string_arg, 0, 0)
arg(pooldatasize_ARG, '\0', "pooldatasize", size_mb_arg, 0, 0)
arg(poolmetadata_ARG, '\0', "poolmetadata", string_arg, 0, 0)
arg(poolmetadatasize_ARG, '\0', "poolmetadatasize", size_mb_arg, 0, 0)
arg(poolmetadataspare_ARG, '\0', "poolmetadataspare", yes_no_arg, 0, 0)
arg(profile_ARG, '\0', "profile", string_arg, 0, 0)
arg(pvmetadatacopies_ARG, '\0', "pvmetadatacopies", int_arg, 0, 0)
arg(raidrebuild_ARG, '\0', "raidrebuild", string_arg, ARG_GROUPABLE, 0)
arg(raidmaxrecoveryrate_ARG, '\0', "raidmaxrecoveryrate", size_kb_arg, 0, 0)
arg(raidminrecoveryrate_ARG, '\0', "raidminrecoveryrate", size_kb_arg, 0, 0)
arg(raidsyncaction_ARG, '\0', "raidsyncaction", string_arg, 0, 0)
arg(raidwritebehind_ARG, '\0', "raidwritebehind", int_arg, 0, 0)
arg(raidwritemostly_ARG, '\0', "raidwritemostly", string_arg, ARG_GROUPABLE, 0)
arg(readonly_ARG, '\0', "readonly", NULL, 0, 0)
arg(refresh_ARG, '\0', "refresh", NULL, 0, 0)
arg(removemissing_ARG, '\0', "removemissing", NULL, 0, 0)
arg(rebuild_ARG, '\0', "rebuild", string_arg, ARG_GROUPABLE, 0)
arg(repair_ARG, '\0', "repair", NULL, 0, 0)
arg(replace_ARG, '\0', "replace", string_arg, ARG_GROUPABLE, 0)
arg(reportformat_ARG, '\0', "reportformat", string_arg, 0, 0)
arg(restorefile_ARG, '\0', "restorefile", string_arg, 0, 0)
arg(restoremissing_ARG, '\0', "restoremissing", NULL, 0, 0)
arg(resync_ARG, '\0', "resync", NULL, 0, 0)
arg(rows_ARG, '\0', "rows", NULL, 0, 0)
arg(segments_ARG, '\0', "segments", NULL, 0, 0)
arg(separator_ARG, '\0', "separator", string_arg, 0, 0)
arg(shared_ARG, '\0', "shared", NULL, 0, 0)
arg(sinceversion_ARG, '\0', "sinceversion", string_arg, 0, 0)
arg(split_ARG, '\0', "split", NULL, 0, 0)
arg(splitcache_ARG, '\0', "splitcache", NULL, 0, 0)
arg(splitmirrors_ARG, '\0', "splitmirrors", int_arg, 0, 0)
arg(splitsnapshot_ARG, '\0', "splitsnapshot", NULL, 0, 0)
arg(showdeprecated_ARG, '\0', "showdeprecated", NULL, 0, 0)
arg(showunsupported_ARG, '\0', "showunsupported", NULL, 0, 0)
arg(stripes_long_ARG, '\0', "stripes", int_arg, 0, 0)
arg(syncaction_ARG, '\0', "syncaction", string_arg, 0, 0) /* FIXME Use custom validation fn */
arg(sysinit_ARG, '\0', "sysinit", NULL, 0, 0)
arg(systemid_ARG, '\0', "systemid", string_arg, 0, 0)
arg(thinpool_ARG, '\0', "thinpool", string_arg, 0, 0)
arg(trackchanges_ARG, '\0', "trackchanges", NULL, 0, 0)
arg(trustcache_ARG, '\0', "trustcache", NULL, 0, 0)
arg(type_ARG, '\0', "type", segtype_arg, 0, 0)
arg(unbuffered_ARG, '\0', "unbuffered", NULL, 0, 0)
arg(uncache_ARG, '\0', "uncache", NULL, 0, 0)
arg(cachepolicy_ARG, '\0', "cachepolicy", string_arg, 0, 0)
arg(cachesettings_ARG, '\0', "cachesettings", string_arg, ARG_GROUPABLE, 0)
arg(unconfigured_ARG, '\0', "unconfigured", NULL, 0, 0)
arg(units_ARG, '\0', "units", string_arg, 0, 0)
arg(unquoted_ARG, '\0', "unquoted", NULL, 0, 0)
arg(usepolicies_ARG, '\0', "usepolicies", NULL, 0, 0)
arg(validate_ARG, '\0', "validate", NULL, 0, 0)
arg(version_ARG, '\0', "version", NULL, 0, 0)
arg(vgmetadatacopies_ARG, '\0', "vgmetadatacopies", metadatacopies_arg, 0, 0)
arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", size_mb_arg, 0, 0)
arg(withsummary_ARG, '\0', "withsummary", NULL, 0, 0)
arg(withcomments_ARG, '\0', "withcomments", NULL, 0, 0)
arg(withspaces_ARG, '\0', "withspaces", NULL, 0, 0)
arg(withversions_ARG, '\0', "withversions", NULL, 0, 0)
arg(writebehind_ARG, '\0', "writebehind", int_arg, 0, 0)
arg(writemostly_ARG, '\0', "writemostly", string_arg, ARG_GROUPABLE, 0)
arg(abort_ARG, '\0', "abort", 0, 0, 0)
arg(activationmode_ARG, '\0', "activationmode", activationmode_VAL, 0, 0)
arg(addtag_ARG, '\0', "addtag", tag_VAL, ARG_GROUPABLE, 0)
arg(aligned_ARG, '\0', "aligned", 0, 0, 0)
arg(alloc_ARG, '\0', "alloc", alloc_VAL, 0, 0)
arg(atomic_ARG, '\0', "atomic", 0, 0, 0)
arg(atversion_ARG, '\0', "atversion", string_VAL, 0, 0)
arg(binary_ARG, '\0', "binary", 0, 0, 0)
arg(bootloaderareasize_ARG, '\0', "bootloaderareasize", sizemb_VAL, 0, 0)
arg(cache_long_ARG, '\0', "cache", 0, 0, 0)
arg(cachemode_ARG, '\0', "cachemode", cachemode_VAL, 0, 0)
arg(cachepool_ARG, '\0', "cachepool", lv_VAL, 0, 0)
arg(commandprofile_ARG, '\0', "commandprofile", string_VAL, 0, 0)
arg(config_ARG, '\0', "config", string_VAL, 0, 0)
arg(configreport_ARG, '\0', "configreport", string_VAL, ARG_GROUPABLE, 1)
arg(configtype_ARG, '\0', "typeconfig", string_VAL, 0, 0)
arg(corelog_ARG, '\0', "corelog", 0, 0, 0)
arg(dataalignment_ARG, '\0', "dataalignment", sizekb_VAL, 0, 0)
arg(dataalignmentoffset_ARG, '\0', "dataalignmentoffset", sizekb_VAL, 0, 0)
arg(deltag_ARG, '\0', "deltag", tag_VAL, ARG_GROUPABLE, 0)
arg(detachprofile_ARG, '\0', "detachprofile", 0, 0, 0)
arg(discards_ARG, '\0', "discards", discards_VAL, 0, 0)
arg(driverloaded_ARG, '\0', "driverloaded", bool_VAL, 0, 0)
arg(errorwhenfull_ARG, '\0', "errorwhenfull", bool_VAL, 0, 0)
arg(force_long_ARG, '\0', "force", 0, ARG_COUNTABLE, 0)
arg(foreign_ARG, '\0', "foreign", 0, 0, 0)
arg(handlemissingpvs_ARG, '\0', "handlemissingpvs", 0, 0, 0)
arg(ignoreadvanced_ARG, '\0', "ignoreadvanced", 0, 0, 0)
arg(ignorelocal_ARG, '\0', "ignorelocal", 0, 0, 0)
arg(ignorelockingfailure_ARG, '\0', "ignorelockingfailure", 0, 0, 0)
arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", 0, 0, 0)
arg(ignoreskippedcluster_ARG, '\0', "ignoreskippedcluster", 0, 0, 0)
arg(ignoreunsupported_ARG, '\0', "ignoreunsupported", 0, 0, 0)
arg(labelsector_ARG, '\0', "labelsector", number_VAL, 0, 0)
arg(lockopt_ARG, '\0', "lockopt", string_VAL, 0, 0)
arg(lockstart_ARG, '\0', "lockstart", 0, 0, 0)
arg(lockstop_ARG, '\0', "lockstop", 0, 0, 0)
arg(locktype_ARG, '\0', "locktype", locktype_VAL, 0, 0)
arg(logonly_ARG, '\0', "logonly", 0, 0, 0)
arg(maxrecoveryrate_ARG, '\0', "maxrecoveryrate", sizekb_VAL, 0, 0)
arg(merge_ARG, '\0', "merge", 0, 0, 0)
arg(mergedconfig_ARG, '\0', "mergedconfig", 0, 0, 0)
arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_VAL, 0, 0)
arg(metadataignore_ARG, '\0', "metadataignore", bool_VAL, 0, 0)
arg(metadataprofile_ARG, '\0', "metadataprofile", string_VAL, 0, 0)
arg(metadatasize_ARG, '\0', "metadatasize", sizemb_VAL, 0, 0)
arg(minor_ARG, '\0', "minor", number_VAL, ARG_GROUPABLE, 0)
arg(minrecoveryrate_ARG, '\0', "minrecoveryrate", sizekb_VAL, 0, 0)
arg(mirrorlog_ARG, '\0', "mirrorlog", mirrorlog_VAL, 0, 0)
arg(mirrorsonly_ARG, '\0', "mirrorsonly", 0, 0, 0)
arg(mknodes_ARG, '\0', "mknodes", 0, 0, 0)
arg(monitor_ARG, '\0', "monitor", bool_VAL, 0, 0)
arg(nameprefixes_ARG, '\0', "nameprefixes", 0, 0, 0)
arg(noheadings_ARG, '\0', "noheadings", 0, 0, 0)
arg(nohistory_ARG, '\0', "nohistory", 0, 0, 0)
arg(nolocking_ARG, '\0', "nolocking", 0, 0, 0)
arg(norestorefile_ARG, '\0', "norestorefile", 0, 0, 0)
arg(nosuffix_ARG, '\0', "nosuffix", 0, 0, 0)
arg(nosync_ARG, '\0', "nosync", 0, 0, 0)
arg(notifydbus_ARG, '\0', "notifydbus", 0, 0, 0)
arg(noudevsync_ARG, '\0', "noudevsync", 0, 0, 0)
arg(originname_ARG, '\0', "originname", lv_VAL, 0, 0)
arg(physicalvolumesize_ARG, '\0', "setphysicalvolumesize", sizemb_VAL, 0, 0)
arg(poll_ARG, '\0', "poll", bool_VAL, 0, 0)
arg(polloperation_ARG, '\0', "polloperation", string_VAL, 0, 0)
arg(pooldatasize_ARG, '\0', "pooldatasize", sizemb_VAL, 0, 0)
arg(poolmetadata_ARG, '\0', "poolmetadata", lv_VAL, 0, 0)
arg(poolmetadatasize_ARG, '\0', "poolmetadatasize", sizemb_VAL, 0, 0)
arg(poolmetadataspare_ARG, '\0', "poolmetadataspare", bool_VAL, 0, 0)
arg(profile_ARG, '\0', "profile", string_VAL, 0, 0)
arg(pvmetadatacopies_ARG, '\0', "pvmetadatacopies", number_VAL, 0, 0)
arg(raidrebuild_ARG, '\0', "raidrebuild", string_VAL, ARG_GROUPABLE, 0)
arg(raidmaxrecoveryrate_ARG, '\0', "raidmaxrecoveryrate", sizekb_VAL, 0, 0)
arg(raidminrecoveryrate_ARG, '\0', "raidminrecoveryrate", sizekb_VAL, 0, 0)
arg(raidsyncaction_ARG, '\0', "raidsyncaction", string_VAL, 0, 0)
arg(raidwritebehind_ARG, '\0', "raidwritebehind", number_VAL, 0, 0)
arg(raidwritemostly_ARG, '\0', "raidwritemostly", string_VAL, ARG_GROUPABLE, 0)
arg(readonly_ARG, '\0', "readonly", 0, 0, 0)
arg(refresh_ARG, '\0', "refresh", 0, 0, 0)
arg(removemissing_ARG, '\0', "removemissing", 0, 0, 0)
arg(rebuild_ARG, '\0', "rebuild", pv_VAL, ARG_GROUPABLE, 0)
arg(repair_ARG, '\0', "repair", 0, 0, 0)
arg(replace_ARG, '\0', "replace", pv_VAL, ARG_GROUPABLE, 0)
arg(reportformat_ARG, '\0', "reportformat", string_VAL, 0, 0)
arg(restorefile_ARG, '\0', "restorefile", string_VAL, 0, 0)
arg(restoremissing_ARG, '\0', "restoremissing", 0, 0, 0)
arg(resync_ARG, '\0', "resync", 0, 0, 0)
arg(rows_ARG, '\0', "rows", 0, 0, 0)
arg(segments_ARG, '\0', "segments", 0, 0, 0)
arg(separator_ARG, '\0', "separator", string_VAL, 0, 0)
arg(shared_ARG, '\0', "shared", 0, 0, 0)
arg(sinceversion_ARG, '\0', "sinceversion", string_VAL, 0, 0)
arg(split_ARG, '\0', "split", 0, 0, 0)
arg(splitcache_ARG, '\0', "splitcache", 0, 0, 0)
arg(splitmirrors_ARG, '\0', "splitmirrors", number_VAL, 0, 0)
arg(splitsnapshot_ARG, '\0', "splitsnapshot", 0, 0, 0)
arg(showdeprecated_ARG, '\0', "showdeprecated", 0, 0, 0)
arg(showunsupported_ARG, '\0', "showunsupported", 0, 0, 0)
arg(stripes_long_ARG, '\0', "stripes", number_VAL, 0, 0)
arg(syncaction_ARG, '\0', "syncaction", string_VAL, 0, 0) /* FIXME Use custom VAL */
arg(sysinit_ARG, '\0', "sysinit", 0, 0, 0)
arg(systemid_ARG, '\0', "systemid", string_VAL, 0, 0)
arg(thinpool_ARG, '\0', "thinpool", lv_VAL, 0, 0)
arg(trackchanges_ARG, '\0', "trackchanges", 0, 0, 0)
arg(trustcache_ARG, '\0', "trustcache", 0, 0, 0)
arg(type_ARG, '\0', "type", segtype_VAL, 0, 0)
arg(unbuffered_ARG, '\0', "unbuffered", 0, 0, 0)
arg(uncache_ARG, '\0', "uncache", 0, 0, 0)
arg(cachepolicy_ARG, '\0', "cachepolicy", string_VAL, 0, 0)
arg(cachesettings_ARG, '\0', "cachesettings", string_VAL, ARG_GROUPABLE, 0)
arg(unconfigured_ARG, '\0', "unconfigured", 0, 0, 0)
arg(units_ARG, '\0', "units", units_VAL, 0, 0)
arg(unquoted_ARG, '\0', "unquoted", 0, 0, 0)
arg(usepolicies_ARG, '\0', "usepolicies", 0, 0, 0)
arg(validate_ARG, '\0', "validate", 0, 0, 0)
arg(version_ARG, '\0', "version", 0, 0, 0)
arg(vgmetadatacopies_ARG, '\0', "vgmetadatacopies", metadatacopies_VAL, 0, 0)
arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", sizemb_VAL, 0, 0)
arg(withsummary_ARG, '\0', "withsummary", 0, 0, 0)
arg(withcomments_ARG, '\0', "withcomments", 0, 0, 0)
arg(withspaces_ARG, '\0', "withspaces", 0, 0, 0)
arg(withversions_ARG, '\0', "withversions", 0, 0, 0)
arg(writebehind_ARG, '\0', "writebehind", number_VAL, 0, 0)
arg(writemostly_ARG, '\0', "writemostly", string_VAL, ARG_GROUPABLE, 0)
/* Allow some variations */
arg(allocation_ARG, '\0', "allocation", yes_no_arg, 0, 0)
arg(available_ARG, '\0', "available", activation_arg, 0, 0)
arg(resizable_ARG, '\0', "resizable", yes_no_arg, 0, 0)
arg(allocation_ARG, '\0', "allocation", bool_VAL, 0, 0)
arg(available_ARG, '\0', "available", activation_VAL, 0, 0)
arg(resizable_ARG, '\0', "resizable", bool_VAL, 0, 0)
/*
* ... and now the short args.
*/
arg(activate_ARG, 'a', "activate", activation_arg, 0, 0)
arg(all_ARG, 'a', "all", NULL, 0, 0)
arg(autobackup_ARG, 'A', "autobackup", yes_no_arg, 0, 0)
arg(activevolumegroups_ARG, 'A', "activevolumegroups", NULL, 0, 0)
arg(background_ARG, 'b', "background", NULL, 0, 0)
arg(backgroundfork_ARG, 'b', "background", NULL, 0, 0)
arg(basevgname_ARG, 'n', "basevgname", string_arg, 0, 0)
arg(blockdevice_ARG, 'b', "blockdevice", NULL, 0, 0)
arg(chunksize_ARG, 'c', "chunksize", size_kb_arg, 0, 0)
arg(clustered_ARG, 'c', "clustered", yes_no_arg, 0, 0)
arg(colon_ARG, 'c', "colon", NULL, 0, 0)
arg(columns_ARG, 'C', "columns", NULL, 0, 0)
arg(contiguous_ARG, 'C', "contiguous", yes_no_arg, 0, 0)
arg(debug_ARG, 'd', "debug", NULL, ARG_COUNTABLE, 0)
arg(exported_ARG, 'e', "exported", NULL, 0, 0)
arg(physicalextent_ARG, 'E', "physicalextent", NULL, 0, 0)
arg(file_ARG, 'f', "file", string_arg, 0, 0)
arg(force_ARG, 'f', "force", NULL, ARG_COUNTABLE, 0)
arg(full_ARG, 'f', "full", NULL, 0, 0)
arg(help_ARG, 'h', "help", NULL, 0, 0)
arg(cache_ARG, 'H', "cache", NULL, 0, 0)
arg(history_ARG, 'H', "history", NULL, 0, 0)
arg(help2_ARG, '?', "", NULL, 0, 0)
arg(import_ARG, 'i', "import", NULL, 0, 0)
arg(interval_ARG, 'i', "interval", int_arg, 0, 0)
arg(iop_version_ARG, 'i', "iop_version", NULL, 0, 0)
arg(stripes_ARG, 'i', "stripes", int_arg, 0, 0)
arg(stripesize_ARG, 'I', "stripesize", size_kb_arg, 0, 0)
arg(logicalvolume_ARG, 'l', "logicalvolume", int_arg, 0, 0)
arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", int_arg, 0, 0)
arg(extents_ARG, 'l', "extents", int_arg_with_sign_and_percent, 0, 0)
arg(list_ARG, 'l', "list", NULL, 0, 0)
arg(lvmpartition_ARG, 'l', "lvmpartition", NULL, 0, 0)
arg(logicalextent_ARG, 'L', "logicalextent", int_arg_with_sign, 0, 0)
arg(size_ARG, 'L', "size", size_mb_arg, 0, 0)
arg(persistent_ARG, 'M', "persistent", yes_no_arg, 0, 0)
arg(major_ARG, 'j', "major", int_arg, ARG_GROUPABLE, 0)
arg(setactivationskip_ARG, 'k', "setactivationskip", yes_no_arg, 0, 0)
arg(ignoreactivationskip_ARG, 'K', "ignoreactivationskip", NULL, 0, 0)
arg(maps_ARG, 'm', "maps", NULL, 0, 0)
arg(mirrors_ARG, 'm', "mirrors", int_arg_with_sign, 0, 0)
arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_arg, 0, 0)
arg(name_ARG, 'n', "name", string_arg, 0, 0)
arg(nofsck_ARG, 'n', "nofsck", NULL, 0, 0)
arg(novolumegroup_ARG, 'n', "novolumegroup", NULL, 0, 0)
arg(oldpath_ARG, 'n', "oldpath", NULL, 0, 0)
arg(options_ARG, 'o', "options", string_arg, ARG_GROUPABLE, 0)
arg(sort_ARG, 'O', "sort", string_arg, ARG_GROUPABLE, 0)
arg(maxphysicalvolumes_ARG, 'p', "maxphysicalvolumes", int_arg, 0, 0)
arg(permission_ARG, 'p', "permission", permission_arg, 0, 0)
arg(partial_ARG, 'P', "partial", NULL, 0, 0)
arg(physicalvolume_ARG, 'P', "physicalvolume", NULL, 0, 0)
arg(quiet_ARG, 'q', "quiet", NULL, ARG_COUNTABLE, 0)
arg(readahead_ARG, 'r', "readahead", readahead_arg, 0, 0)
arg(resizefs_ARG, 'r', "resizefs", NULL, 0, 0)
arg(reset_ARG, 'R', "reset", NULL, 0, 0)
arg(regionsize_ARG, 'R', "regionsize", size_mb_arg, 0, 0)
arg(physicalextentsize_ARG, 's', "physicalextentsize", size_mb_arg, 0, 0)
arg(snapshot_ARG, 's', "snapshot", NULL, 0, 0)
arg(short_ARG, 's', "short", NULL, 0, 0)
arg(stdin_ARG, 's', "stdin", NULL, 0, 0)
arg(select_ARG, 'S', "select", string_arg, ARG_GROUPABLE, 0)
arg(test_ARG, 't', "test", NULL, 0, 0)
arg(thin_ARG, 'T', "thin", NULL, 0, 0)
arg(uuid_ARG, 'u', "uuid", NULL, 0, 0)
arg(uuidstr_ARG, 'u', "uuid", string_arg, 0, 0)
arg(uuidlist_ARG, 'U', "uuidlist", NULL, 0, 0)
arg(verbose_ARG, 'v', "verbose", NULL, ARG_COUNTABLE, 0)
arg(volumegroup_ARG, 'V', "volumegroup", NULL, 0, 0)
arg(virtualsize_ARG, 'V', "virtualsize", size_mb_arg, 0, 0)
arg(wipesignatures_ARG, 'W', "wipesignatures", yes_no_arg, 0, 0)
arg(allocatable_ARG, 'x', "allocatable", yes_no_arg, 0, 0)
arg(resizeable_ARG, 'x', "resizeable", yes_no_arg, 0, 0)
arg(yes_ARG, 'y', "yes", NULL, 0, 0)
arg(zero_ARG, 'Z', "zero", yes_no_arg, 0, 0)
arg(activate_ARG, 'a', "activate", activation_VAL, 0, 0)
arg(all_ARG, 'a', "all", 0, 0, 0)
arg(autobackup_ARG, 'A', "autobackup", bool_VAL, 0, 0)
arg(activevolumegroups_ARG, 'A', "activevolumegroups", 0, 0, 0)
arg(background_ARG, 'b', "background", 0, 0, 0)
arg(backgroundfork_ARG, 'b', "background", 0, 0, 0)
arg(basevgname_ARG, 'n', "basevgname", string_VAL, 0, 0)
arg(blockdevice_ARG, 'b', "blockdevice", 0, 0, 0)
arg(chunksize_ARG, 'c', "chunksize", sizekb_VAL, 0, 0)
arg(clustered_ARG, 'c', "clustered", bool_VAL, 0, 0)
arg(colon_ARG, 'c', "colon", 0, 0, 0)
arg(columns_ARG, 'C', "columns", 0, 0, 0)
arg(contiguous_ARG, 'C', "contiguous", bool_VAL, 0, 0)
arg(debug_ARG, 'd', "debug", 0, ARG_COUNTABLE, 0)
arg(exported_ARG, 'e', "exported", 0, 0, 0)
arg(physicalextent_ARG, 'E', "physicalextent", 0, 0, 0)
arg(file_ARG, 'f', "file", string_VAL, 0, 0)
arg(force_ARG, 'f', "force", 0, ARG_COUNTABLE, 0)
arg(full_ARG, 'f', "full", 0, 0, 0)
arg(help_ARG, 'h', "help", 0, ARG_COUNTABLE, 0)
arg(cache_ARG, 'H', "cache", 0, 0, 0)
arg(history_ARG, 'H', "history", 0, 0, 0)
arg(help2_ARG, '?', "", 0, 0, 0)
arg(import_ARG, 'i', "import", 0, 0, 0)
arg(interval_ARG, 'i', "interval", number_VAL, 0, 0)
arg(iop_version_ARG, 'i', "iop_version", 0, 0, 0)
arg(stripes_ARG, 'i', "stripes", number_VAL, 0, 0)
arg(stripesize_ARG, 'I', "stripesize", sizekb_VAL, 0, 0)
arg(logicalvolume_ARG, 'l', "logicalvolume", number_VAL, 0, 0)
arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", number_VAL, 0, 0)
arg(extents_ARG, 'l', "extents", numsignedper_VAL, 0, 0)
arg(list_ARG, 'l', "list", 0, 0, 0)
arg(lvmpartition_ARG, 'l', "lvmpartition", 0, 0, 0)
arg(size_ARG, 'L', "size", sizemb_VAL, 0, 0)
arg(persistent_ARG, 'M', "persistent", bool_VAL, 0, 0)
arg(major_ARG, 'j', "major", number_VAL, ARG_GROUPABLE, 0)
arg(setactivationskip_ARG, 'k', "setactivationskip", bool_VAL, 0, 0)
arg(ignoreactivationskip_ARG, 'K', "ignoreactivationskip", 0, 0, 0)
arg(maps_ARG, 'm', "maps", 0, 0, 0)
arg(mirrors_ARG, 'm', "mirrors", numsigned_VAL, 0, 0)
arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_VAL, 0, 0)
arg(name_ARG, 'n', "name", string_VAL, 0, 0)
arg(nofsck_ARG, 'n', "nofsck", 0, 0, 0)
arg(novolumegroup_ARG, 'n', "novolumegroup", 0, 0, 0)
arg(oldpath_ARG, 'n', "oldpath", 0, 0, 0)
arg(options_ARG, 'o', "options", string_VAL, ARG_GROUPABLE, 0)
arg(sort_ARG, 'O', "sort", string_VAL, ARG_GROUPABLE, 0)
arg(maxphysicalvolumes_ARG, 'p', "maxphysicalvolumes", number_VAL, 0, 0)
arg(permission_ARG, 'p', "permission", permission_VAL, 0, 0)
arg(partial_ARG, 'P', "partial", 0, 0, 0)
arg(physicalvolume_ARG, 'P', "physicalvolume", 0, 0, 0)
arg(quiet_ARG, 'q', "quiet", 0, ARG_COUNTABLE, 0)
arg(readahead_ARG, 'r', "readahead", readahead_VAL, 0, 0)
arg(resizefs_ARG, 'r', "resizefs", 0, 0, 0)
arg(reset_ARG, 'R', "reset", 0, 0, 0)
arg(regionsize_ARG, 'R', "regionsize", sizemb_VAL, 0, 0)
arg(physicalextentsize_ARG, 's', "physicalextentsize", sizemb_VAL, 0, 0)
arg(snapshot_ARG, 's', "snapshot", 0, 0, 0)
arg(short_ARG, 's', "short", 0, 0, 0)
arg(stdin_ARG, 's', "stdin", 0, 0, 0)
arg(select_ARG, 'S', "select", string_VAL, ARG_GROUPABLE, 0)
arg(test_ARG, 't', "test", 0, 0, 0)
arg(thin_ARG, 'T', "thin", 0, 0, 0)
arg(uuid_ARG, 'u', "uuid", 0, 0, 0)
arg(uuidstr_ARG, 'u', "uuid", string_VAL, 0, 0)
arg(uuidlist_ARG, 'U', "uuidlist", 0, 0, 0)
arg(verbose_ARG, 'v', "verbose", 0, ARG_COUNTABLE, 0)
arg(volumegroup_ARG, 'V', "volumegroup", 0, 0, 0)
arg(virtualsize_ARG, 'V', "virtualsize", sizemb_VAL, 0, 0)
arg(wipesignatures_ARG, 'W', "wipesignatures", bool_VAL, 0, 0)
arg(allocatable_ARG, 'x', "allocatable", bool_VAL, 0, 0)
arg(resizeable_ARG, 'x', "resizeable", bool_VAL, 0, 0)
arg(yes_ARG, 'y', "yes", 0, 0, 0)
arg(zero_ARG, 'Z', "zero", bool_VAL, 0, 0)
/* this should always be last */
arg(ARG_COUNT, '-', "", NULL, 0, 0)
arg(ARG_COUNT, '-', "", 0, 0, 0)
/* *INDENT-ON* */

1536
tools/command-lines.in Normal file

File diff suppressed because it is too large Load Diff

169
tools/command.h Normal file
View File

@@ -0,0 +1,169 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _LVM_COMMAND_H
#define _LVM_COMMAND_H
struct cmd_context;
/* old per-command-name function */
typedef int (*command_fn) (struct cmd_context *cmd, int argc, char **argv);
/* new per-command-line-id functions */
typedef int (*command_line_fn) (struct cmd_context *cmd, int argc, char **argv);
struct command_function {
int command_line_enum;
command_line_fn fn;
};
struct command_name {
const char *name;
const char *desc; /* general command description from commands.h */
unsigned int flags;
/* union of {required,optional}_opt_args for all commands with this name */
int valid_args[ARG_COUNT];
int num_args;
};
/*
* Command defintion
*
* A command is defined in terms of a command name,
* required options (+args), optional options (+args),
* required positional args, optional positional args.
*
* A positional arg always has non-zero pos_arg.def.types.
* The first positional arg has pos_arg.pos of 1.
*/
/* arg_def flags */
#define ARG_DEF_FLAG_NEW 1 << 0
#define ARG_DEF_FLAG_MAY_REPEAT 1 << 1
/* arg_def lv_types */
enum {
ARG_DEF_LV_ANY = 0,
ARG_DEF_LV_LINEAR = 1 << 0,
ARG_DEF_LV_STRIPED = 1 << 1,
ARG_DEF_LV_SNAPSHOT = 1 << 2,
ARG_DEF_LV_MIRROR = 1 << 3,
ARG_DEF_LV_RAID = 1 << 4,
ARG_DEF_LV_RAID0 = 1 << 5,
ARG_DEF_LV_RAID1 = 1 << 6,
ARG_DEF_LV_RAID4 = 1 << 7,
ARG_DEF_LV_RAID5 = 1 << 8,
ARG_DEF_LV_RAID6 = 1 << 9,
ARG_DEF_LV_RAID10 = 1 << 10,
ARG_DEF_LV_THIN = 1 << 11,
ARG_DEF_LV_THINPOOL = 1 << 12,
ARG_DEF_LV_CACHE = 1 << 13,
ARG_DEF_LV_CACHEPOOL = 1 << 14,
ARG_DEF_LV_LAST = 1 << 15,
};
static inline int val_bit_is_set(uint64_t val_bits, int val_enum)
{
return (val_bits & (1 << val_enum)) ? 1 : 0;
}
static inline uint64_t val_enum_to_bit(int val_enum)
{
return 1 << val_enum;
}
/* Description a value that follows an option or exists in a position. */
struct arg_def {
uint64_t val_bits; /* bits of x_VAL, can be multiple for pos_arg */
uint64_t num; /* a literal number for conststr_VAL */
const char *str; /* a literal string for constnum_VAL */
uint32_t lv_types; /* ARG_DEF_LV_, for lv_VAL, can be multiple */
uint32_t flags; /* ARG_DEF_FLAG_ */
};
/* Description of an option and the value that follows it. */
struct opt_arg {
int opt; /* option, e.g. foo_ARG */
struct arg_def def; /* defines accepted values */
};
/* Description of a position and the value that exists there. */
struct pos_arg {
int pos; /* position, e.g. first is 1 */
struct arg_def def; /* defines accepted values */
};
/*
* CMD_RO_ARGS needs to accomodate a list of options,
* of which one is required after which the rest are
* optional.
*/
#define CMD_RO_ARGS 64 /* required opt args */
#define CMD_OO_ARGS 150 /* optional opt args */
#define CMD_RP_ARGS 8 /* required positional args */
#define CMD_OP_ARGS 8 /* optional positional args */
/*
* one or more from required_opt_args is required,
* then the rest are optional.
*/
#define CMD_FLAG_ONE_REQUIRED_OPT 1
/* a register of the lvm commands */
struct command {
const char *name;
const char *desc; /* specific command description from command-lines.h */
const char *usage; /* excludes common options like --help, --debug */
const char *usage_common; /* includes commmon options like --help, --debug */
const char *command_line_id;
int command_line_enum; /* <command_line_id>_CMD */
struct command_name *cname;
command_fn fn; /* old style */
struct command_function *functions; /* new style */
unsigned int flags; /* copied from command_name.flags from commands.h */
unsigned int cmd_flags; /* CMD_FLAG_ */
/* definitions of opt/pos args */
/* required args following an --opt */
struct opt_arg required_opt_args[CMD_RO_ARGS];
/* optional args following an --opt */
struct opt_arg optional_opt_args[CMD_OO_ARGS];
/* required positional args */
struct pos_arg required_pos_args[CMD_RP_ARGS];
/* optional positional args */
struct pos_arg optional_pos_args[CMD_OP_ARGS];
int ro_count;
int oo_count;
int rp_count;
int op_count;
/* used for processing current position */
int pos_count;
};
#endif

File diff suppressed because it is too large Load Diff

2487
tools/create-commands.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1436,3 +1436,286 @@ int lvchange(struct cmd_context *cmd, int argc, char **argv)
update ? READ_FOR_UPDATE : 0, NULL,
&_lvchange_single);
}
#if 0
/*
* Check if the status of the LV allows running lvchange.
*
* FIXME: check for invalid VG/LV properties in a way that is not prone
* to missing some. Currently, there are some checks here, some in the
* functions above, some in process_each, and some may be missing.
*/
static int _lvchange_status_is_valid(struct cmd_context *cmd, struct logical_volume *lv)
{
if (!(lv->vg->status & LVM_WRITE)) {
log_error("Operation not permitted on LV %s: writable VG required.",
display_lvname(lv));
return 0;
}
if (lv_is_pvmove(lv)) {
log_error("Operation not permitted on LV %s: used for pvmove.",
display_lvname(lv));
if (arg_is_set(cmd, activate_ARG))
log_error("Use 'pvmove --abort' to abandon a pvmove");
return 0;
}
if (lv_is_mirror_log(lv)) {
log_error("Operation not permitted on LV %s: is mirror log.",
display_lvname(lv));
return 0;
}
if (lv_is_mirror_image(lv)) {
log_error("Operation not permitted on LV %s: is mirror image.",
display_lvname(lv));
return 0;
}
if (lv_is_origin(lv) && !lv_is_thin_volume(lv)) {
log_error("Operation not permitted on LV %s: is under snapshot.",
display_lvname(lv));
return 0;
}
return 1;
}
static int _lvchange_properties_single(struct cmd_context *cmd,
struct logical_volume *lv,
struct processing_handle *handle)
{
int doit = 0, docmds = 0;
/* FIXME: sort out hidden/internal LVs, e.g. _lvchange_hidden_is_valid() */
if (!_lvchange_status_is_valid(cmd, lv))
return_ECMD_FAILED;
if (arg_is_set(cmd, persistent_ARG) && lv_is_pool(lv)) {
log_error("Operation not permitted on LV %s: persistent device numbers are not supported with pools.",
display_lvname(lv));
return ECMD_FAILED;
}
/*
* If a persistent lv lock already exists from activation
* (with the needed mode or higher), this will be a no-op.
* Otherwise, the lv lock will be taken as non-persistent
* and released when this command exits.
*/
if (!lockd_lv(cmd, lv, "ex", 0)) {
stack;
return ECMD_FAILED;
}
for (i = 0; i < cmd->command->ro_count; i++) {
opt_enum = cmd->command->required_opt_args[i].opt;
if (!arg_is_set(cmd, opt_enum))
continue;
if (!archive(lv->vg))
return_ECMD_FAILED;
docmds++;
switch (opt_enum) {
case permission_ARG:
doit += _lvchange_permission(cmd, lv);
break;
case alloc_ARG:
case contiguous_ARG:
doit += _lvchange_alloc(cmd, lv);
break;
case errorwhenfull_ARG:
doit += _lvchange_errorwhenfull(cmd, lv);
break;
case readahead_ARG:
doit += _lvchange_readahead(cmd, lv);
break;
case persistent_ARG:
doit += _lvchange_persistent(cmd, lv);
break;
case discards_ARG:
case zero_ARG:
doit += _lvchange_pool_update(cmd, lv);
break;
case addtag_ARG:
case deltag_ARG:
doit += _lvchange_tag(cmd, lv, opt_enum);
break;
case writemostly_ARG:
case writebehind_ARG:
doit += _lvchange_writemostly(lv);
break;
case minrecoveryrate_ARG:
case maxrecoveryrate_ARG:
doit += _lvchange_recovery_rate(lv);
break;
case profile_ARG:
case metadataprofile_ARG:
case detachprofile_ARG:
doit += _lvchange_profile(lv);
break;
case setactivationskip_ARG:
doit += _lvchange_activation_skip(lv);
break;
case cachemode_ARG:
case cachepolicy_ARG:
case cachesettings_ARG:
doit += _lvchange_cache(cmd, lv);
break;
default:
log_error(INTERNAL_ERROR "Failed to check for option %s",
arg_long_option_name(i));
}
if (doit)
log_print_unless_silent("Logical volume %s changed.", display_lvname(lv));
if (doit != docmds)
return_ECMD_FAILED;
return ECMD_PROCESSED;
}
int lvchange_properties_cmd(struct cmd_context *cmd, int argc, char **argv)
{
struct processing_handle *handle = init_processing_handle(cmd, NULL);
int ret;
ret = process_each_lv(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, handle, _lvchange_properties_single);
destroy_processing_handle(cmd, handle);
return ret;
}
static int _lvchange_activate_single(struct cmd_context *cmd,
struct logical_volume *lv,
struct processing_handle *handle)
{
struct logical_volume *origin;
char snaps_msg[128];
/* FIXME: sort out hidden/internal LVs, e.g. _lvchange_hidden_is_valid() */
if (!_lvchange_status_is_valid(cmd, lv))
return_ECMD_FAILED;
/* FIXME: untangle the proper logic for cow / sparse / virtual origin */
/* If LV is sparse, activate origin instead */
if (lv_is_cow(lv) && lv_is_virtual_origin(origin = origin_from_cow(lv)))
lv = origin;
if (lv_is_cow(lv)) {
origin = origin_from_cow(lv);
if (origin->origin_count < 2)
snaps_msg[0] = '\0';
else if (dm_snprintf(snaps_msg, sizeof(snaps_msg),
" and %u other snapshot(s)",
origin->origin_count - 1) < 0) {
log_error("Failed to prepare message.");
return ECMD_FAILED;
}
if (!arg_is_set(cmd, yes_ARG) &&
(yes_no_prompt("Change of snapshot %s will also change its "
"origin %s%s. Proceed? [y/n]: ",
display_lvname(lv), display_lvname(origin),
snaps_msg) == 'n')) {
log_error("Logical volume %s not changed.", display_lvname(lv));
return ECMD_FAILED;
}
}
/*
* If --sysinit -aay is used and at the same time lvmetad is used,
* we want to rely on autoactivation to take place. Also, we
* need to take special care here as lvmetad service does
* not neet to be running at this moment yet - it could be
* just too early during system initialization time.
*/
if (arg_is_set(cmd, sysinit_ARG) && (arg_uint_value(cmd, activate_ARG, 0) == CHANGE_AAY)) {
if (lvmetad_used()) {
log_warn("WARNING: lvmetad is active, skipping direct activation during sysinit.");
return ECMD_PROCESSED;
}
}
if (!_lvchange_activate(cmd, lv))
return_ECMD_FAILED;
return ECMD_PROCESSED;
}
int lvchange_activate_cmd(struct cmd_context *cmd, int argc, char **argv)
{
struct processing_handle *handle = init_processing_handle(cmd, NULL);
cmd->handles_missing_pvs = 1;
cmd->lockd_vg_default_sh = 1;
/*
* Include foreign VGs that contain active LVs.
* That shouldn't happen in general, but if it does by some
* mistake, then we want to allow those LVs to be deactivated.
*/
cmd->include_active_foreign_vgs = 1;
/* Allow deactivating if locks fail. */
if (is_change_activating((activation_change_t)arg_uint_value(cmd, activate_ARG, CHANGE_AY)))
cmd->lockd_vg_enforce_sh = 1;
ret = process_each_lv(cmd, argc, argv, NULL, NULL, 0, handle, _lvchange_activate_single);
destroy_processing_handle(cmd, handle);
return ret;
}
static int _lvchange_refresh_single(struct cmd_context *cmd,
struct logical_volume *lv,
struct processing_handle *handle)
{
/* FIXME: sort out hidden/internal LVs, e.g. _lvchange_hidden_is_valid() */
if (!_lvchange_status_is_valid(cmd, lv))
return_ECMD_FAILED;
log_verbose("Refreshing logical volume %s (if active).", display_lvname(lv));
if (!_lv_refresh(cmd, lv))
return_ECMD_FAILED;
return ECMD_PROCESSED;
}
int lvchange_refresh_cmd(struct cmd_context *cmd, int argc, char **argv)
{
struct processing_handle *handle = init_processing_handle(cmd, NULL);
int ret;
cmd->handles_missing_pvs = 1;
cmd->lockd_vg_default_sh = 1;
ret = process_each_lv(cmd, argc, argv, NULL, NULL, 0, handle, _lvchange_refresh_single);
destroy_processing_handle(cmd, handle);
return ret;
}
#endif

View File

@@ -50,8 +50,6 @@ struct lvconvert_params {
int splitsnapshot;
int thin;
int uncache;
int other_conversion; /* Everything else */
int corelog; /* Equivalent to --mirrorlog core */
int mirrorlog; /* Only one of corelog and mirrorlog may be set */
@@ -236,6 +234,12 @@ static int _lvconvert_name_params(struct lvconvert_params *lp,
return 0;
}
/*
* FIXME: avoid this distinct validation out of scope of _convert_*()
*
* We should not rely on namespace here any more!
* It is the duty of lvcreate/lvrename to avoid reserved names.
*/
if (!lp->merge_mirror &&
!lp->repair &&
!lp->keep_mimages &&
@@ -243,6 +247,7 @@ static int _lvconvert_name_params(struct lvconvert_params *lp,
!strstr(lp->lv_name, "_tmeta") &&
!strstr(lp->lv_name, "_cdata") &&
!strstr(lp->lv_name, "_cmeta") &&
!strstr(lp->lv_name, "_corig") &&
!apply_lvname_restrictions(lp->lv_name))
return_0;
@@ -307,9 +312,14 @@ static int _striped_type_requested(const char *type_str)
return (!strcmp(type_str, SEG_TYPE_NAME_STRIPED) || _linear_type_requested(type_str));
}
static int _check_conversion_type(struct cmd_context *cmd, const char *type_str)
static int _read_conversion_type(struct cmd_context *cmd,
struct lvconvert_params *lp)
{
if (!type_str || !*type_str)
const char *type_str = arg_str_value(cmd, type_ARG, "");
lp->type_str = type_str;
if (!lp->type_str[0])
return 1;
/* FIXME: Check thin-pool and thin more thoroughly! */
@@ -320,6 +330,7 @@ static int _check_conversion_type(struct cmd_context *cmd, const char *type_str)
return 1;
log_error("Conversion using --type %s is not supported.", type_str);
return 0;
}
@@ -436,11 +447,33 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
int region_size;
int pagesize = lvm_getpagesize();
lp->type_str = arg_str_value(cmd, type_ARG, "");
if (*lp->type_str && !_check_conversion_type(cmd, lp->type_str))
if (!_read_conversion_type(cmd, lp))
return_0;
if (!arg_is_set(cmd, background_ARG))
lp->wait_completion = 1;
if (arg_is_set(cmd, corelog_ARG))
lp->corelog = 1;
if (arg_is_set(cmd, mirrorlog_ARG)) {
if (lp->corelog) {
log_error("--mirrorlog and --corelog are incompatible.");
return 0;
}
lp->mirrorlog = 1;
}
if (arg_is_set(cmd, merge_ARG)) {
if (arg_outside_list_is_set(cmd, "cannot be used with --merge",
merge_ARG,
background_ARG, interval_ARG,
force_ARG, noudevsync_ARG, test_ARG,
-1))
return_0;
lp->merge = 1;
}
/* If --repair, check for incompatible args. */
if (arg_is_set(cmd, repair_ARG)) {
if (arg_outside_list_is_set(cmd, "cannot be used with --repair",
@@ -452,15 +485,8 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
lp->repair = 1;
}
if (arg_is_set(cmd, mirrorlog_ARG))
lp->mirrorlog = 1;
if (arg_is_set(cmd, corelog_ARG))
lp->corelog = 1;
if (lp->mirrorlog && lp->corelog) {
log_error("--mirrorlog and --corelog are incompatible.");
return 0;
}
if (arg_is_set(cmd, replace_ARG))
lp->replace = 1;
if (arg_is_set(cmd, split_ARG)) {
if (arg_outside_list_is_set(cmd, "cannot be used with --split",
@@ -490,6 +516,9 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
lp->splitsnapshot = 1;
}
if (arg_is_set(cmd, trackchanges_ARG))
lp->track_changes = 1;
if (arg_is_set(cmd, uncache_ARG)) {
if (arg_outside_list_is_set(cmd, "cannot be used with --uncache",
uncache_ARG,
@@ -528,21 +557,14 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
if (!_read_pool_params(cmd, &argc, &argv, lp))
return_0;
if (!arg_is_set(cmd, background_ARG))
lp->wait_completion = 1;
if (_snapshot_type_requested(cmd, lp->type_str)) {
if (arg_is_set(cmd, merge_ARG)) {
if (lp->merge) {
log_error("--snapshot and --merge are mutually exclusive.");
return 0;
}
lp->snapshot = 1;
}
if (arg_is_set(cmd, trackchanges_ARG))
lp->track_changes = 1;
if (lp->split) {
lp->lv_split_name = arg_str_value(cmd, name_ARG, NULL);
@@ -579,12 +601,6 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
}
}
if (arg_is_set(cmd, merge_ARG))
lp->merge = 1;
if (arg_is_set(cmd, replace_ARG))
lp->replace = 1;
/* If no other case was identified, then use of --stripes means --type striped */
if (!arg_is_set(cmd, type_ARG) && !*lp->type_str && !lp->merge && !lp->splitsnapshot &&
!lp->splitcache && !lp->split && !lp->snapshot && !lp->uncache && !lp->cache && !lp->thin &&
@@ -611,9 +627,7 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
}
if (arg_is_set(cmd, mirrors_ARG)) {
/*
* --splitmirrors is the mechanism for detaching and keeping a mimage
*/
/* --splitmirrors is the mechanism for detaching and keeping a mimage */
lp->mirrors_supplied = 1;
lp->mirrors = arg_uint_value(cmd, mirrors_ARG, 0);
lp->mirrors_sign = arg_sign_value(cmd, mirrors_ARG, SIGN_NONE);
@@ -626,8 +640,7 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
lp->cache + lp->thin + lp->keep_mimages + lp->snapshot + lp->replace + lp->repair > 1) {
log_error(INTERNAL_ERROR "Unexpected combination of incompatible options selected.");
return 0;
} else
lp->other_conversion = 1;
}
/*
* Final checking of each case:
@@ -645,14 +658,9 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
* --type mirror|raid lp->mirrorlog lp->corelog
* --type raid0|striped
*/
if (lp->merge) { /* Snapshot or mirror merge */
if (arg_outside_list_is_set(cmd, "cannot be used with --merge",
merge_ARG,
background_ARG, interval_ARG,
force_ARG, noudevsync_ARG, test_ARG,
-1))
return_0;
} else if (lp->splitsnapshot) /* Destroy snapshot retaining cow as separate LV */
if (lp->merge) /* Snapshot or mirror merge */
;
else if (lp->splitsnapshot) /* Destroy snapshot retaining cow as separate LV */
;
else if (lp->splitcache)
;
@@ -4097,11 +4105,11 @@ static int _convert_striped_raid(struct cmd_context *cmd, struct logical_volume
static int _convert_cow_snapshot(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
if (arg_is_set(cmd, splitsnapshot_ARG))
if (lp->splitsnapshot)
return _convert_cow_snapshot_splitsnapshot(cmd, lv, lp);
/* FIXME: add --merge-snapshot to make this distinct from --merge-mirror. */
if (arg_is_set(cmd, merge_ARG))
if (lp->merge)
return _convert_cow_snapshot_merge(cmd, lv, lp);
log_error("Operation not permitted on COW snapshot LV %s.", display_lvname(lv));
@@ -4115,7 +4123,7 @@ static int _convert_thin_volume(struct cmd_context *cmd, struct logical_volume *
struct lvconvert_params *lp)
{
/* FIXME: add --merge-snapshot to make this distinct from --merge-mirror. */
if (arg_is_set(cmd, merge_ARG))
if (lp->merge)
return _convert_thin_volume_merge(cmd, lv, lp);
log_error("Operation not permitted on thin LV %s.", display_lvname(lv));
@@ -4127,19 +4135,19 @@ static int _convert_thin_volume(struct cmd_context *cmd, struct logical_volume *
static int _convert_thin_pool(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
if (arg_is_set(cmd, splitcache_ARG))
if (lp->splitcache)
return _convert_thin_pool_splitcache(cmd, lv, lp);
if (arg_is_set(cmd, split_ARG))
if (lp->split)
return _convert_thin_pool_splitcache(cmd, lv, lp);
if (arg_is_set(cmd, uncache_ARG))
if (lp->uncache)
return _convert_thin_pool_uncache(cmd, lv, lp);
if (lp->cache)
return _convert_thin_pool_cache(cmd, lv, lp);
if (arg_is_set(cmd, repair_ARG))
if (lp->repair)
return _convert_thin_pool_repair(cmd, lv, lp);
/* FIXME: swapping the thin pool metadata LV needs a specific option like --swapmetadata */
@@ -4160,21 +4168,20 @@ static int _convert_thin_pool(struct cmd_context *cmd, struct logical_volume *lv
static int _convert_cache_volume(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
if (arg_is_set(cmd, splitcache_ARG))
if (lp->splitcache)
return _convert_cache_volume_splitcache(cmd, lv, lp);
if (arg_is_set(cmd, split_ARG))
if (lp->split)
return _convert_cache_volume_splitcache(cmd, lv, lp);
if (arg_is_set(cmd, uncache_ARG))
if (lp->uncache)
return _convert_cache_volume_uncache(cmd, lv, lp);
if (arg_is_set(cmd, splitmirrors_ARG))
return _convert_cache_volume_splitmirrors(cmd, lv, lp);
/* Using --thinpool is ambiguous and not preferred. */
if (!strcmp(lp->type_str, SEG_TYPE_NAME_THIN_POOL) || arg_is_set(cmd, thinpool_ARG))
if (!strcmp(lp->type_str, SEG_TYPE_NAME_THIN_POOL) ||
arg_is_set(cmd, thinpool_ARG))
return _convert_cache_volume_thin_pool(cmd, lv, lp);
/* The --thinpool alternative for --type thin-pool is not preferred, so not shown. */
@@ -4191,10 +4198,10 @@ static int _convert_cache_volume(struct cmd_context *cmd, struct logical_volume
static int _convert_cache_pool(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
if (arg_is_set(cmd, splitcache_ARG))
if (lp->splitcache)
return _convert_cache_pool_splitcache(cmd, lv, lp);
if (arg_is_set(cmd, split_ARG))
if (lp->split)
return _convert_cache_pool_splitcache(cmd, lv, lp);
/* FIXME: swapping the cache pool metadata LV needs a specific option like --swapmetadata */
@@ -4221,7 +4228,7 @@ static int _convert_mirror(struct cmd_context *cmd, struct logical_volume *lv,
if (arg_is_set(cmd, mirrorlog_ARG) || arg_is_set(cmd, corelog_ARG))
return _convert_mirror_log(cmd, lv, lp);
if (arg_is_set(cmd, repair_ARG))
if (lp->repair)
return _convert_mirror_repair(cmd, lv, lp);
if (_linear_type_requested(lp->type_str))
@@ -4262,42 +4269,53 @@ static int _convert_mirror(struct cmd_context *cmd, struct logical_volume *lv,
static int _convert_raid(struct cmd_context *cmd, struct logical_volume *lv,
struct lvconvert_params *lp)
{
/* Permitted convert options on visible or hidden RaidLVs */
/* The --thinpool alternative for --type thin-pool is not preferred, so not shown. */
const char *permitted_options = lv_is_visible(lv) ?
" --mirrors\n"
" --splitmirrors\n"
" --merge\n"
" --repair\n"
" --replace\n"
" --type snapshot\n"
" --type thin\n"
" --type cache\n"
" --type thin-pool\n"
" --type cache-pool\n"
" --type raid*\n"
" --type mirror\n"
" --type striped\n"
" --type linear\n"
:
" --mirrors\n"
" --splitmirrors\n"
" --repair\n"
" --replace\n"
" --type raid*\n"
" --type mirror\n"
" --type striped\n"
" --type linear\n";
/* Applicable to any hidden _or_ visible LVs. */
if (arg_is_set(cmd, mirrors_ARG))
return _convert_raid_number(cmd, lv, lp);
if (arg_is_set(cmd, splitmirrors_ARG))
return _convert_raid_splitmirrors(cmd, lv, lp);
if (arg_is_set(cmd, merge_ARG))
return _convert_raid_merge(cmd, lv, lp);
if (arg_is_set(cmd, repair_ARG))
if (lp->repair)
return _convert_raid_repair(cmd, lv, lp);
if (arg_is_set(cmd, replace_ARG))
return _convert_raid_replace(cmd, lv, lp);
if (!strcmp(lp->type_str, SEG_TYPE_NAME_SNAPSHOT) || arg_is_set(cmd, snapshot_ARG))
return _convert_raid_snapshot(cmd, lv, lp);
if (arg_is_set(cmd, splitmirrors_ARG))
return _convert_raid_splitmirrors(cmd, lv, lp);
if (lp->thin)
return _convert_raid_thin(cmd, lv, lp);
if (segtype_is_raid(lp->segtype)) {
/* Only --type allowed on hidden RaidLV. */
if (!lv_is_visible(lv) && !arg_is_set(cmd, type_ARG))
goto out;
if (lp->cache)
return _convert_raid_cache(cmd, lv, lp);
/* Using --thinpool is ambiguous and not preferred. */
if (!strcmp(lp->type_str, SEG_TYPE_NAME_THIN_POOL) || arg_is_set(cmd, thinpool_ARG))
return _convert_raid_thin_pool(cmd, lv, lp);
/* Using --cachepool is ambiguous and not preferred. */
if (!strcmp(lp->type_str, SEG_TYPE_NAME_CACHE_POOL) || arg_is_set(cmd, cachepool_ARG))
return _convert_raid_cache_pool(cmd, lv, lp);
if (segtype_is_raid(lp->segtype))
return _convert_raid_raid(cmd, lv, lp);
}
if (segtype_is_mirror(lp->segtype))
return _convert_raid_mirror(cmd, lv, lp);
@@ -4308,24 +4326,33 @@ static int _convert_raid(struct cmd_context *cmd, struct logical_volume *lv,
if (_linear_type_requested(lp->type_str))
return _convert_raid_linear(cmd, lv, lp);
/* The --thinpool alternative for --type thin-pool is not preferred, so not shown. */
/* Applicable to visible LVs only. */
if (lv_is_visible(lv)) {
if (lp->merge)
return _convert_raid_merge(cmd, lv, lp);
if (!strcmp(lp->type_str, SEG_TYPE_NAME_SNAPSHOT) || arg_is_set(cmd, snapshot_ARG))
return _convert_raid_snapshot(cmd, lv, lp);
if (lp->thin)
return _convert_raid_thin(cmd, lv, lp);
if (lp->cache)
return _convert_raid_cache(cmd, lv, lp);
if (!strcmp(lp->type_str, SEG_TYPE_NAME_THIN_POOL) ||
arg_is_set(cmd, thinpool_ARG))
return _convert_raid_thin_pool(cmd, lv, lp);
if (!strcmp(lp->type_str, SEG_TYPE_NAME_CACHE_POOL) ||
arg_is_set(cmd, cachepool_ARG))
return _convert_raid_cache_pool(cmd, lv, lp);
}
out:
log_error("Operation not permitted on raid LV %s.", display_lvname(lv));
log_error("Operations permitted on a raid LV are:\n"
" --mirrors\n"
" --splitmirrors\n"
" --merge\n"
" --repair\n"
" --replace\n"
" --type snapshot\n"
" --type thin\n"
" --type cache\n"
" --type thin-pool\n"
" --type cache-pool\n"
" --type raid*\n"
" --type mirror\n"
" --type striped\n"
" --type linear\n");
log_error("Operations permitted on a raid LV are:\n%s", permitted_options);
return 0;
}
@@ -4335,10 +4362,10 @@ static int _convert_striped(struct cmd_context *cmd, struct logical_volume *lv,
const char *mirrors_type = find_config_tree_str(cmd, global_mirror_segtype_default_CFG, NULL);
/* FIXME: add --merge-mirror to make this distinct from --merge-snapshot. */
if (arg_is_set(cmd, merge_ARG))
if (lp->merge)
return _convert_striped_merge(cmd, lv, lp);
if (!strcmp(lp->type_str, SEG_TYPE_NAME_SNAPSHOT) || arg_is_set(cmd, snapshot_ARG))
if (lp->snapshot || !strcmp(lp->type_str, SEG_TYPE_NAME_SNAPSHOT))
return _convert_striped_snapshot(cmd, lv, lp);
if (lp->thin)
@@ -4347,14 +4374,12 @@ static int _convert_striped(struct cmd_context *cmd, struct logical_volume *lv,
if (lp->cache)
return _convert_striped_cache(cmd, lv, lp);
/* Using --thinpool is ambiguous and not preferred. */
if (!strcmp(lp->type_str, SEG_TYPE_NAME_THIN_POOL) || arg_is_set(cmd, thinpool_ARG))
if (!strcmp(lp->type_str, SEG_TYPE_NAME_THIN_POOL) ||
arg_is_set(cmd, thinpool_ARG))
return _convert_striped_thin_pool(cmd, lv, lp);
/* Using --cachepool is ambiguous and not preferred. */
if (!strcmp(lp->type_str, SEG_TYPE_NAME_CACHE_POOL) || arg_is_set(cmd, cachepool_ARG))
if (!strcmp(lp->type_str, SEG_TYPE_NAME_CACHE_POOL) ||
arg_is_set(cmd, cachepool_ARG))
return _convert_striped_cache_pool(cmd, lv, lp);
if (!strcmp(lp->type_str, SEG_TYPE_NAME_MIRROR))
@@ -4418,13 +4443,11 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
if (lv_is_locked(lv)) {
log_error("Cannot convert locked LV %s.", display_lvname(lv));
ret = 0;
goto out;
}
if (lv_is_pvmove(lv)) {
log_error("Cannot convert pvmove LV %s.", display_lvname(lv));
ret = 0;
goto out;
}
@@ -4440,9 +4463,9 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
!lv_is_thin_pool_metadata(lv) &&
!lv_is_thin_pool_data(lv) &&
!lv_is_used_cache_pool(lv) &&
!lv_is_raid_image(lv)) {
!lv_is_mirrored(lv) &&
!lv_is_raid(lv)) {
log_error("Cannot convert internal LV %s.", display_lvname(lv));
ret = 0;
goto out;
}
}
@@ -4451,20 +4474,21 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
if (!*lp->type_str)
lp->segtype = seg->segtype;
else if (!(lp->segtype = get_segtype_from_string(cmd, lp->type_str)))
return_0;
goto_out;
if (!strcmp(lp->type_str, SEG_TYPE_NAME_MIRROR)) {
if (!lp->mirrors_supplied && !seg_is_raid1(seg)) {
log_error("Conversions to --type mirror require -m/--mirrors");
return 0;
goto out;
}
}
if (activation() && lp->segtype && lp->segtype->ops->target_present &&
/* lv->segtype can't be NULL */
if (activation() && lp->segtype->ops->target_present &&
!lp->segtype->ops->target_present(cmd, NULL, &lp->target_attr)) {
log_error("%s: Required device-mapper target(s) not "
"detected in your kernel.", lp->segtype->name);
return 0;
goto out;
}
/* Process striping parameters */
@@ -4473,7 +4497,7 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
_striped_type_requested(lp->type_str) || lp->repair || lp->mirrorlog || lp->corelog) {
/* FIXME Handle +/- adjustments too? */
if (!get_stripe_params(cmd, lp->segtype, &lp->stripes, &lp->stripe_size, &lp->stripes_supplied, &lp->stripe_size_supplied))
return_0;
goto_out;
if (_raid0_type_requested(lp->type_str) || _striped_type_requested(lp->type_str))
/* FIXME Shouldn't need to override get_stripe_params which defaults to 1 stripe (i.e. linear)! */
@@ -4539,7 +4563,6 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv,
* reach here, but this covers anything that was missed.
*/
log_error("Cannot convert LV %s.", display_lvname(lv));
ret = 0;
out:
return ret ? ECMD_PROCESSED : ECMD_FAILED;

View File

@@ -45,9 +45,9 @@ static char *_list_cmds(const char *text, int state)
len = strlen(text);
}
while (i < _cmdline->num_commands)
if (!strncmp(text, _cmdline->commands[i++].name, len))
return strdup(_cmdline->commands[i - 1].name);
while (i < _cmdline->num_command_names)
if (!strncmp(text, _cmdline->command_names[i++].name, len))
return strdup(_cmdline->command_names[i - 1].name);
return NULL;
}
@@ -57,7 +57,7 @@ static char *_list_args(const char *text, int state)
{
static int match_no = 0;
static size_t len = 0;
static struct command *com;
static struct command_name *cname;
/* Initialise if this is a new completion attempt */
if (!state) {
@@ -65,40 +65,40 @@ static char *_list_args(const char *text, int state)
int j;
match_no = 0;
com = NULL;
cname = NULL;
len = strlen(text);
/* Find start of first word in line buffer */
while (isspace(*s))
s++;
/* Look for word in list of commands */
for (j = 0; j < _cmdline->num_commands; j++) {
/* Look for word in list of command names */
for (j = 0; j < _cmdline->num_command_names; j++) {
const char *p;
char *q = s;
p = _cmdline->commands[j].name;
p = _cmdline->command_names[j].name;
while (*p == *q) {
p++;
q++;
}
if ((!*p) && *q == ' ') {
com = _cmdline->commands + j;
cname = _cmdline->command_names + j;
break;
}
}
}
if (!com)
if (!cname)
return NULL;
/* Short form arguments */
if (len < 3) {
while (match_no < com->num_args) {
while (match_no < cname->num_args) {
char s[3];
char c;
if (!(c = (_cmdline->arg_props +
com->valid_args[match_no++])->short_arg))
cname->valid_args[match_no++])->short_arg))
continue;
sprintf(s, "-%c", c);
@@ -108,13 +108,13 @@ static char *_list_args(const char *text, int state)
}
/* Long form arguments */
if (match_no < com->num_args)
match_no = com->num_args;
if (match_no < cname->num_args)
match_no = cname->num_args;
while (match_no - com->num_args < com->num_args) {
while (match_no - cname->num_args < cname->num_args) {
const char *l;
l = (_cmdline->arg_props +
com->valid_args[match_no++ - com->num_args])->long_arg;
cname->valid_args[match_no++ - cname->num_args])->long_arg;
if (*(l + 2) && !strncmp(text, l, len))
return strdup(l);
}

View File

@@ -19,10 +19,11 @@
struct cmd_context;
struct cmdline_context {
struct arg_props *arg_props;
struct command *commands;
int num_commands;
int commands_size;
struct arg_props *arg_props;
struct command *commands;
int num_commands;
struct command_name *command_names;
int num_command_names;
};
int lvm2_main(int argc, char **argv);

View File

@@ -30,12 +30,12 @@ void *cmdlib_lvm2_init(unsigned static_compile)
{
struct cmd_context *cmd;
lvm_register_commands();
init_is_static(static_compile);
if (!(cmd = init_lvm(1, 1)))
return NULL;
lvm_register_commands();
return (void *) cmd;
}

File diff suppressed because it is too large Load Diff

View File

@@ -2350,9 +2350,12 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
struct dm_str_list *sl;
struct dm_list final_lvs;
struct lv_list *final_lvl;
struct dm_list found_arg_lvnames;
struct glv_list *glvl, *tglvl;
int do_report_ret_code = 1;
int lv_is_specific = 0;
uint32_t lv_types;
struct logical_volume *lv;
struct lv_segment *seg;
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_LV);
@@ -2361,6 +2364,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
stack;
dm_list_init(&final_lvs);
dm_list_init(&found_arg_lvnames);
if (!vg_check_status(vg, EXPORTED_VG)) {
ret_max = ECMD_FAILED;
@@ -2436,8 +2440,9 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
if (arg_is_set(cmd, all_ARG) ||
(lvargs_supplied && str_list_match_item(arg_lvnames, lvl->lv->name))) {
log_very_verbose("Processing lockd_sanlock_lv %s/%s.", vg->name, lvl->lv->name);
} else
} else {
continue;
}
}
/*
@@ -2449,19 +2454,16 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
*/
process_lv = process_all;
lv_is_specific = 0;
if (lvargs_supplied && str_list_match_item(arg_lvnames, lvl->lv->name)) {
/* Remove LV from list of unprocessed LV names */
str_list_del(arg_lvnames, lvl->lv->name);
str_list_add(cmd->mem, &found_arg_lvnames, lvl->lv->name);
process_lv = 1;
lv_is_specific = 1;
}
if (!process_lv && tags_supplied && str_list_match_list(tags_in, &lvl->lv->tags, NULL)) {
if (!process_lv && tags_supplied && str_list_match_list(tags_in, &lvl->lv->tags, NULL))
process_lv = 1;
lv_is_specific = 1;
}
process_lv = process_lv && select_match_lv(cmd, handle, vg, lvl->lv) && _select_matches(handle);
@@ -2481,7 +2483,6 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
goto_out;
}
final_lvl->lv = lvl->lv;
final_lvl->lv->process_specific = lv_is_specific;
dm_list_add(&final_lvs, &final_lvl->list);
}
log_set_report_object_name_and_id(NULL, NULL);
@@ -2505,6 +2506,68 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
if (lv_is_removed(lvl->lv))
continue;
/*
* If the command definition specifies one required positional
* LV (possibly repeatable), and specifies accepted LV types,
* then verify that the LV being processed matches one of those
* types.
*
* process_each_lv() can only be used for commands that have
* one positional LV arg (optionally repeating, where each is
* processed independently.) It cannot work for commands that
* have different required LVs in designated positions, like
* 'lvrename LV1 LV2', where each LV is not processed
* independently. That means that this LV type check only
* needs to check the lv_type of the first positional arg.
*
* There is one command that violates this rule by stealing
* the first positional LV arg before calling process_each_lv:
* lvconvert --type snapshot LV_linear_striped_raid LV_snapshot
* This code cannot validate that case. process_each_lv() sees
* a single LV name arg, but it's in pos 2. Could we work around
* this by looking at the final positional arg rather than always
* looking at pos 1?
*
* This only validates types for required LV positional args
* (currently there are no command specifications that include
* specific LV types in optional positional args.)
*/
if ((cmd->command->rp_count == 1) &&
val_bit_is_set(cmd->command->required_pos_args[0].def.val_bits, lv_VAL) &&
cmd->command->required_pos_args[0].def.lv_types) {
lv_types = cmd->command->required_pos_args[0].def.lv_types;
lv = lvl->lv;
seg = first_seg(lv);
if ((lv_is_cow(lv) && !(lv_types & ARG_DEF_LV_SNAPSHOT)) ||
(lv_is_thin_volume(lv) && !(lv_types & ARG_DEF_LV_THIN)) ||
(lv_is_thin_pool(lv) && !(lv_types & ARG_DEF_LV_THINPOOL)) ||
(lv_is_cache(lv) && !(lv_types & ARG_DEF_LV_CACHE)) ||
(lv_is_cache_pool(lv) && !(lv_types & ARG_DEF_LV_CACHEPOOL)) ||
(lv_is_mirror(lv) && !(lv_types & ARG_DEF_LV_MIRROR)) ||
(lv_is_raid(lv) && !(lv_types & (ARG_DEF_LV_RAID | ARG_DEF_LV_RAID0 | ARG_DEF_LV_RAID1 | ARG_DEF_LV_RAID4 | ARG_DEF_LV_RAID5 | ARG_DEF_LV_RAID6 | ARG_DEF_LV_RAID10))) ||
(segtype_is_striped(seg->segtype) && !(lv_types & ARG_DEF_LV_STRIPED)) ||
(segtype_is_linear(seg->segtype) && !(lv_types & ARG_DEF_LV_LINEAR))) {
/*
* If a named LV arg cannot be processed it's an error, otherwise
* the LV is skipped and doesn't cause the command to fail.
*/
if (str_list_match_item(&found_arg_lvnames, lv->name)) {
log_error("Operation not permitted (%s %d) on LV %s with type %s.",
cmd->command->command_line_id, cmd->command->command_line_enum,
display_lvname(lv), seg->segtype->name);
ret_max = ECMD_FAILED;
} else {
log_warn("Operation not permitted (%s %d) on LV %s with type %s.",
cmd->command->command_line_id, cmd->command->command_line_enum,
display_lvname(lv), seg->segtype->name);
}
continue;
}
}
log_very_verbose("Processing LV %s in VG %s.", lvl->lv->name, vg->name);
ret = process_single_lv(cmd, lvl->lv, handle);
@@ -3269,9 +3332,12 @@ static int _process_duplicate_pvs(struct cmd_context *cmd,
* Don't pass dev to lvmcache_info_from_pvid because we looking
* for the chosen/preferred dev for this pvid.
*/
info = lvmcache_info_from_pvid(devl->dev->pvid, NULL, 0);
if (info)
vgname = lvmcache_vgname_from_info(info);
if (!(info = lvmcache_info_from_pvid(devl->dev->pvid, NULL, 0))) {
log_error(INTERNAL_ERROR "No info for pvid");
return_ECMD_FAILED;
}
vgname = lvmcache_vgname_from_info(info);
if (vgname)
vgid = lvmcache_vgid_from_vgname(cmd, vgname);
if (vgid)
@@ -3834,14 +3900,6 @@ int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
force_t force = (force_t) arg_count(cmd, force_ARG)
? : (arg_is_set(cmd, yes_ARG) ? DONT_PROMPT : PROMPT);
if ((force == PROMPT) &&
!lv->process_specific &&
(cmd->command->flags & CONFIRM_UNLESS_SPECIFIC)) {
if (yes_no_prompt("Remove LV %s that was not named directly? [y/n]: ",
display_lvname(lv)) == 'n')
return ECMD_PROCESSED;
}
if (!lv_remove_with_dependencies(cmd, lv, force, 0))
return_ECMD_FAILED;

View File

@@ -50,20 +50,27 @@
#define CMD_LEN 256
#define MAX_ARGS 64
/* command functions */
typedef int (*command_fn) (struct cmd_context * cmd, int argc, char **argv);
/* define the enums for the values accepted by command line --options */
enum {
#define val(a, b, c, d) a ,
#include "vals.h"
#undef val
};
#define xx(a, b...) int a(struct cmd_context *cmd, int argc, char **argv);
#include "commands.h"
#undef xx
/* define the enums for the command line switches */
/* define the enums for the command line --options */
enum {
#define arg(a, b, c, d, e, f) a ,
#include "args.h"
#undef arg
};
/* command functions */
#define xx(a, b...) int a(struct cmd_context *cmd, int argc, char **argv);
#include "commands.h"
#undef xx
#include "command.h"
#define ARG_COUNTABLE 0x00000001 /* E.g. -vvvv */
#define ARG_GROUPABLE 0x00000002 /* E.g. --addtag */
@@ -79,13 +86,13 @@ struct arg_values {
/* void *ptr; // Currently not used. */
};
/* a global table of possible arguments */
/* a global table of possible --option's */
struct arg_props {
int arg_enum; /* foo_ARG from args.h */
const char short_arg;
char _padding[7];
const char *long_arg;
int (*fn) (struct cmd_context *cmd, struct arg_values *av);
int val_enum; /* foo_VAL from vals.h */
uint32_t flags;
uint32_t prio;
};
@@ -96,6 +103,14 @@ struct arg_value_group_list {
uint32_t prio;
};
/* a global table of possible --option values */
struct val_props {
int val_enum; /* foo_VAL from vals.h */
int (*fn) (struct cmd_context *cmd, struct arg_values *av);
const char *name;
const char *usage;
};
#define CACHE_VGMETADATA 0x00000001
#define PERMITTED_READ_ONLY 0x00000002
/* Process all VGs if none specified on the command line. */
@@ -118,20 +133,6 @@ struct arg_value_group_list {
#define ENABLE_DUPLICATE_DEVS 0x00000400
/* Command does not accept tags as args. */
#define DISALLOW_TAG_ARGS 0x00000800
#define CONFIRM_UNLESS_SPECIFIC 0x00001000
/* a register of the lvm commands */
struct command {
const char *name;
const char *desc;
const char *usage;
command_fn fn;
unsigned flags;
int num_args;
int *valid_args;
};
void usage(const char *name);

135
tools/vals.h Normal file
View File

@@ -0,0 +1,135 @@
/*
* Define value types which describe values accepted
* by the --option's in args.h, and can also describe
* the values accepted as positional args.
*
* Previously, accepted values were only "described"
* by identifying the parsing function to use.
*
* Some standard val types are used by many options,
* e.g. many options (aa_ARG, bb_ARG, cc_ARG) all
* accept a number_VAL.
*
* Other special val types are used by only one option,
* e.g. only mirrorlog_ARG accepts a mirrorlog_VAL.
* This typically means that there are some specific
* words that are recognized after the option.
*
* Some options currently take a standard val type,
* (esp string_VAL), but they could be given their
* own custom val type. The advantage of using a
* custom val type is the possibility of validating
* the value when parsing it with a custom parsing
* function, and the possibility of displaying the
* actual accepted values in the command usage.
* Without a custom val type, the code must do ad hoc
* validation of the string values, and the usage
* output for the option will only say "String"
* rather than giving the accepted string values.
* Even without a custom parsing function, there is
* reason to define a custom x_VAL enum so that a
* more descriptive usage string can be specified
* as opposed to just "String".
*
* Most of the val types defined here are used after
* --option's, and are referenced in foo_ARG entries
* in args.h. But, some val types are only used to
* represent positional values in command definitions,
* e.g. vg_VAL.
*
* val(a, b, c, d)
*
* a: foo_VAL enums
* b: the function to parse and set the value
* c: the name used to reference this value in command defs
* d: what to display in usage output for this value
*
* command defintions will use --option NAME, where NAME
* is shown in val() field c. NAME will be translated to
* foo_VAL enum in field a, which is used in commands[]
* structs.
*
* option definitions (arg.h) will reference foo_VAL enum
* in field a.
*
* FIXME: for specialized val types, the set of recognized
* words is not defined or stored in a consistent way,
* but is just whatever the parsing function happens to look
* for, so adding a new accepted value for the val type is
* often just making the parsing function recognize a new
* word. This new word should then also be added to the
* usage string for the val type here. It would be nice
* if the accepted values could be defined in a more
* consistent way, perhaps in struct val_props.
*
* The usage text for an option is not always the full
* set of words accepted for an option, but may be a
* subset. i.e. an outdated word that no longer does
* anything may not be shown, but may still be recognized
* and ignored, or an option that shouldn't be used in
* general isn't shown to avoid suggesting it.
* e.g. for --activate we show the most common "y|n|ay"
* without showing the lvmlockd variations "ey|sy" which
* are not applicable in general.
*
* FIXME: are there some specialized or irrelevant
* options included in the usage text below that should
* be removed? Should "lvm1" be removed?
*
* For Number args that take optional units, a full usage
* could be "Number[bBsSkKmMgGtTpPeE]" (with implied |),
* but repeating this full specification produces cluttered
* output, and doesn't indicate which unit is the default.
* "Number[units]" would be cleaner, as would a subset of
* common units, e.g. "Number[kmg...]", but neither helps
* with default. "Number[k|unit]" and "Number[m|unit]" show
* the default, and "unit" indicates that other units
* are possible without listing them all. This also
* suggests using the preferred lower case letters, because
* --size and other option args treat upper/lower letters
* the same, all as 1024 SI base. For this reason, we
* should avoid suggesting the upper case letters.
*/
val(none_VAL, NULL, "None", "") /* unused, for enum value 0 */
val(conststr_VAL, NULL, "ConstString", "") /* used only for command defs */
val(constnum_VAL, NULL, "ConstNumber", "") /* used only for command defs */
val(bool_VAL, yes_no_arg, "Bool", "y|n")
val(number_VAL, int_arg, "Number", NULL)
val(string_VAL, string_arg, "String", NULL)
val(vg_VAL, string_arg, "VG", NULL)
val(lv_VAL, string_arg, "LV", NULL)
val(pv_VAL, string_arg, "PV", NULL)
val(tag_VAL, tag_arg, "Tag", NULL)
val(select_VAL, NULL, "Select", NULL) /* used only for command defs */
val(activationmode_VAL, string_arg, "ActivationMode", "partial|degraded|complete")
val(activation_VAL, activation_arg, "Active", "y|n|ay")
val(cachemode_VAL, cachemode_arg, "CacheMode", "writethrough|writeback")
val(discards_VAL, discards_arg, "Discards", "passdown|nopassdown|ignore")
val(mirrorlog_VAL, mirrorlog_arg, "MirrorLog", "core|disk")
val(sizekb_VAL, size_kb_arg, "SizeKB", "Number[k|unit]")
val(sizemb_VAL, size_mb_arg, "SizeMB", "Number[m|unit]")
val(numsigned_VAL, int_arg_with_sign, "SNumber", "[+|-]Number")
val(numsignedper_VAL, int_arg_with_sign_and_percent, "SNumberP", "[+|-]Number[%{VG|PVS|FREE}]")
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")
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")
/* this should always be last */
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:
*
* configreport_ARG, configtype_ARG, polloperation_ARG, raidrebuild_ARG,
* raidsyncaction_ARG, raidwritemostly_ARG, reportformat_ARG, syncaction_ARG,
* cachepolicy_ARG, cachesettings_ARG, writemostly_ARG
*/