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

Compare commits

..

62 Commits

Author SHA1 Message Date
Marian Csontos
4b84dc8db2 Revert "tests: do not set zero interval in aux lvm.conf"
This reverts commit b38564b8dc.
2016-11-14 09:50:47 +01:00
Marian Csontos
df4f4c1d9e Comments 2016-11-14 09:27:41 +01:00
Marian Csontos
56b2ffddc4 spec: Disable sanlock only, keep lockd_dlm enabled 2016-11-14 09:27:41 +01:00
Marian Csontos
9dc3dfe7b5 spec: Replace remaining %define by %global 2016-11-14 09:27:41 +01:00
Marian Csontos
f8d41ae850 spec: Use %global instead of %define for constants
Using %define is now discouraged by Fedora Packaging Guidelines
2016-11-14 09:27:41 +01:00
Marian Csontos
32f89f6f5b spec: Update requirements for lockd
lockd requires sanlock >= 3.3.0
2016-11-14 09:27:40 +01:00
Marian Csontos
76848c5be9 spec: Profiles are not %confi(noreplace)
These files are just examles and should not be edited by user.
2016-11-14 09:27:40 +01:00
Zdenek Kabelac
a7691cdebb cleanup: debug trace and indent change 2016-11-11 16:58:20 +01:00
Zdenek Kabelac
6db5b91231 cleanup: avoid using double __ in extracted image name 2016-11-11 16:58:20 +01:00
Zdenek Kabelac
1bdcb01f63 cleanup: add dots to debug messages 2016-11-11 16:58:20 +01:00
Zdenek Kabelac
b38564b8dc tests: do not set zero interval in aux lvm.conf
0 interval leads as of now to a busy loop with lvmetad and command.

Avoid testing this patological case.

TODO: Code should possibly translate zero interval into some small
sleep. With lvmpolld it's already 1/10s
2016-11-11 16:58:20 +01:00
Zdenek Kabelac
de3d054f78 tests: avoid using polling 2016-11-11 16:58:20 +01:00
Zdenek Kabelac
4a2250f9ce tests: update make targets
Add  new targets:

make check_lvmpolld
make check_cluster_lvmpolld
make check_lvmetad_lvmpolld
make check_all_lvmpolld

So check_lvmetad runs only base lvmetad test - to much
logic of remaining targets.

Previous behavior is available via  check_all_lvmpolld.
2016-11-11 16:58:20 +01:00
Zdenek Kabelac
d8fc4d093e conf: support zero for missing_stripe_filler
Make it easier to replace missing segments with 'zero' returning
target - otherwise user would have to create some extra target
to provide zeros as /dev/zero can't be used (not a block device).

Also break code loop when segment is found and make it an INTERNAL_ERROR
where it's missing.
2016-11-11 16:58:16 +01:00
Zdenek Kabelac
e54cce245f cleanup: skip checking for just assigned string
When 'stripe_filler' has been just set to 'error',
do not check it again for not being 'error'.
2016-11-11 16:52:24 +01:00
Zdenek Kabelac
59b29716e5 lvconvert: repair accepts interval and background
For mirror and raid we expose --interval and --background on
command line (instead of using just always using compiled-in defaults).
2016-11-11 16:51:33 +01:00
Alasdair G Kergon
f8b3b0bc9a lvconvert: Introduce enum to separate cases.
Start to separate out the different things that lvconvert does by using
an enum to identify 12 distinct cases.
2016-11-11 00:27:01 +00:00
Heinz Mauelshagen
b11f4f93d7 dmsetup: [v2] return 0 for [--]{version,help}
Leverage 0b1c796420 to cope with "dmsetup SubCommand --{help,version}"
and bail out directly when _report_init() fails.

Related: rhbz1393692
2016-11-10 18:09:37 +01:00
Heinz Mauelshagen
0b1c796420 dmsetup: return 0 for [--]{version,help}
dmsetup regressed returning 1 when properly processing
version or help subcommands.

Resolves: rhbz1393692
2016-11-10 17:03:04 +01:00
Zdenek Kabelac
c1862ea84c tests: for repair we need neewer version
Older cache targets were not able to report write failures.
2016-11-08 16:01:35 +01:00
Zdenek Kabelac
2ec3e7dca8 tests: test raid0_meta type
Enable testing of raid0_meta type.
Also slow down devices a bit more.
2016-11-08 16:01:35 +01:00
Zdenek Kabelac
ada5733c56 raid: faster rmeta clearing
Instead of clearing multiple rmeta device with sequential activation
process and waiting for udev for every _rmeta device separately,
activate all _rmeta devices first and then clear them and deactivate
afterwards.

Also update some tracing messages.

When anyhing goes wrong during clearing process, always try to
deactivate as much _rmeta devices as possible before fail.
2016-11-08 16:00:14 +01:00
Alasdair G Kergon
9e03fc3c2a post-release 2016-11-05 01:14:06 +00:00
Alasdair G Kergon
eed708dbd9 pre-release 2016-11-05 01:03:32 +00:00
Alasdair G Kergon
6dce0e9489 tests: Disable 3-leg raid1 pre-sync repair attempt
Test fails as it doesn't ensure device isn't already in sync.
2016-11-04 00:23:08 +00:00
Tony Asleson
461d340bd7 lvmdbusd: Remove the periodic timer task
This code is no longer needed because the back ground task has been
removed.  Will add back if we change the design and end up utilizing
multiple worker threads.
2016-11-03 18:38:10 -05:00
Tony Asleson
ee0c9e7b23 lvmdbusd: Take out background thread
There is no reason to create another background task when the task that
created it is going to block waiting for it to finish.  Instead we will
just execute the logic in the worker thread that is servicing the worker
queue.
2016-11-03 18:29:06 -05:00
Zdenek Kabelac
a9ee86ccf2 dmeventd: provide message context
Show device name with printed message.
Also use different level for printing error message and
standard informational message.
2016-11-03 17:49:07 +01:00
Zdenek Kabelac
4e26024add cleanup: use WARNING prefix for log_warn
Use capital WARNING prefix for log_warn() messages.
2016-11-03 17:49:07 +01:00
Zdenek Kabelac
0d95082aa9 cleanup: remove goto
Move goto path into 'if()' branch.
2016-11-03 17:49:07 +01:00
Zdenek Kabelac
9cbe4c1af9 log_info to log_very_verbose
Translate log_info() into log_very_verbose() which is macro
supposed to be used by our code.

log_info() is internal macro with eventually some 'symbolic' meaning
in syslogging daemons.
2016-11-03 17:49:07 +01:00
Zdenek Kabelac
cc19cc07f7 log_info to log_warn
Switch to log_warn level when we are reporting these message.
2016-11-03 17:49:07 +01:00
Zdenek Kabelac
e3775173b4 cleanup: log_info to log_error
Switch to more appropriate logging level.
2016-11-03 17:49:07 +01:00
Zdenek Kabelac
ee13f265f0 libdm: use dm_log_with_errno always
Instead of compiling 2 log call for 2 different logging functions,
and runtime decide which version to use - use only 'newer' function
and when user sets his own OLD dm_log logging translate it runtime
for old arg list set.

The positive part is - we get shorter generated library,
on the negative part this translation means, we always have evaluate
all args and print the message into local on stack buffer, before
we can pass this buffer to the users' logging function with proper
expected parameters (and such function may later decide to discard
logging based on message level so whole printing was unnecessary).
2016-11-03 17:49:07 +01:00
David Teigland
221d8ff2a4 tests: check that pvscan cannot activate exported VG 2016-11-03 11:43:37 -05:00
Zdenek Kabelac
28b210f4fa cleanup: add 'static' for local struct 2016-11-03 12:43:09 +01:00
Zdenek Kabelac
1db4b81d5a cleanup: drop unused attribute
In this function we pass args through so make the function
header look the same as with _default_log().
2016-11-03 12:43:09 +01:00
Zdenek Kabelac
4b4d19e3aa dmeventd: separate dm and dmeventd logging
Ensure different logging function for dmeventd.c logging
and dm and lvm library.

We can recognize we want to show every log_info() and
log_notice() message from dmeventd.c code while not
exposing those from libdm/libdevmapper-event

Also switch to use log with errno - it's not changing
anything and doesn't bring any more features yet to dmeventd
logging but we just properly pass dm_errno_or_class properly
through the whole code stack for possible future use
(i.e. support of class logging for dmeventd).
2016-11-03 12:43:09 +01:00
Zdenek Kabelac
cd468b6218 dmeventd: debug only subsystemd with # sign
Reword the logging logic and try to restore previous logging
behavior for 'standalone' running daemon while preserving
debuggable feautures it has gained.

So actual rules:

dmeventd without any '-d' option will syslog all messages
from dmeventd.c it dmeventd plugins.

log_notice()==log_verbose()
log_info()==log_very_verbose()
But to show also log_debug() used has to give '-ddd'.

When user specified '-d, -dd, -ddd, -dddd' it
will also enable tracing of messages from libdm & lib
executed code - which is mainly useful for testing
i.e.: 'dmeventd -fldddd'
2016-11-03 12:43:09 +01:00
Zdenek Kabelac
33dd1f7747 dmeventd: abort on internal error
Provide same support for DM_ABORT_ON_INTERNAL_ERRORS we do have
with default libdm logging  as  dmeventd is libdm based tool.
2016-11-03 12:43:09 +01:00
Zdenek Kabelac
e50d434a35 libdm: report logging with errno as changed default
When user changes logging with 'dm_log_with_errno_init()'
also report this as non default dm logging.
2016-11-03 12:43:09 +01:00
Zdenek Kabelac
6af26273cb logging: add more log macros
Introduce macros:

log_level(), log_stderr(), log_once(), log_bypass_report()

For easier and more consisten way how to 'decoder' bits
of info from passed 'level'.

This patch fixes potential problem when 'level' of message
might not have always masked right bits.
2016-11-03 12:43:09 +01:00
Tony Asleson
96118a2508 lvmdbusd: Stop using threads for job wait
Instead of creating a thread to handle the case where a client
is calling job.Wait, we will utilize a timer.  This significantly
reduces the number of threads that get created and destroyed while
the service is running.
2016-11-02 16:39:13 -05:00
Tony Asleson
95abadd13c lvmdbusd: main.py: change debug msg text 2016-11-02 16:39:13 -05:00
Tony Asleson
60de09b00c lvmdbusd: Don't use dbus lib in worker thread
Simplify the code paths so that we don't utilize the dbus library code
when we are in worker thread context.

ref. https://bugs.freedesktop.org/show_bug.cgi?id=98521
2016-11-02 16:39:03 -05:00
Tony Asleson
38dd79307a lvmdbusd: Execute load in main thread
We will fetch the lvm state in non-main thread and only process the new
data with the main thread to prevent hanging the main thread event loop.

ref. https://bugs.freedesktop.org/show_bug.cgi?id=98521
2016-11-02 16:38:49 -05:00
Tony Asleson
24803bbaad lvmdbusd: Return results in main thread
Also introduce some additional new code to execute code other code
in main thread too.

ref. https://bugs.freedesktop.org/show_bug.cgi?id=98521
2016-11-02 16:38:00 -05:00
Tony Asleson
c8e8439b3d lvmdbusd: Use timer instead of thread
We had a thread sitting around for cleaning up other processes, changed to
a periodic timer task.
2016-11-02 16:35:45 -05:00
David Teigland
68e7d34965 pvscan: fix autoactivation of exported VG
pvscan --cache -aay was activating LVs in exported VGs
when it should not.

It appears that this was a regression from commit 9b640c3684
"pvscan: use process_each_vg for autoactivate".
2016-11-02 16:29:52 -05:00
Peter Rajnoha
4585785613 blkdeactivate: deactivate dev stack if dev on top already unmounted
If blkdeactivate finds out that the device on top of device stack
is already unmounted, it still proceeds with device stack deactivation
underneath now.

This situation can happen if blkdeactivate is started and the mount
point is unmounted in parallel by chance (so when blkdeactivate
gets the the actual umount call, the device is not mounted anymore).
Before, the blkdeactivate added such device to skip list which caused
all the stack underneath to be skipped too on deactivation. Now, we
proceed just as if blkdeactivate did the umount itself.

For example, in the example below, the vg-lvol0 is mounted on /mnt/test
when blkdeactivate is called, but it gets unmounted in parallel later
on when blkdeactivate gets to the actual umount call.

Before this patch (vg-lvol0 underneath not deactivated):

  $ blkdeactivate -u
  Deactivating block devices:
    [UMOUNT]: unmounting vg-lvol0 (dm-2) mounted on /mnt/test... skipping

With this patch applied (vg-lvol0 underneath still deactivated):

  $ blkdeactivate -u
  Deactivating block devices:
    [UMOUNT]: unmounting vg-lvol0 (dm-2) mounted on /mnt/test... already unmounted
    [LVM]: deactivating Logical Volume vg/lvol0... done
2016-11-01 16:52:51 +01:00
Heinz Mauelshagen
a9651adc84 test: add raid4 checks to respective tests
Add missing checks for valid raid4 mapping to tests.
2016-10-28 21:54:10 +02:00
Heinz Mauelshagen
e611f82a11 lvconvert: fix raid repair regression
Limit prevention to raid1 as intended with commit 8270ff5702.

Related to rhbz1311765
2016-10-28 21:45:00 +02:00
Heinz Mauelshagen
8270ff5702 lvconvert: prevent non-synced raid1 primary leg repair
(Automatic) repair may not be allowed during the initial sync of an upconverted
linear LV, because the data on the failing, primary leg hasn't been completely
synchronized to the N-1 other legs of the raid1 LV (replacing failed legs during
repair involves discontinuing access to any replaced legs data, thus preventing
data recovery on the primary leg e.g. via dd_rescue).

Even though repair would not cause data loss when adding legs to a fully synced
raid1 LV, we don't have information yet defining this state yet (e.g. a raid1
LV flag telling the fully synchronized status before any legs were added),
hence can't automatically decide to allow to repair.

If nonetheless a repair on a non-synced raid1 LVs is intended, the "--force"
option has to be provided.

Resolves: rhbz1311765
2016-10-28 15:55:10 +02:00
Heinz Mauelshagen
e118b65d65 lvconvert: check for supported raid0/raid4 segtypes
Validate kernel support for raid0/raid4 on given and
requested segtype before requesting conversions on them.

Because raid10 wasn't present in old RAID targets, add
the same validation to be prepared once we support them.
2016-10-27 16:44:32 +02:00
Heinz Mauelshagen
61ae07966d lvconvert-raid-takeover.sh: fix test 2016-10-27 16:38:15 +02:00
Heinz Mauelshagen
ff05ed7afd lvchange/vgchange/lvconvert: prevent raid4 creation/activation/conversion on non-supporting raid targets
Check for dm-raid target version with non-standard raid4 mapping expecting the dedicated
parity device in the last rather than the first slot and prohibit to create, activate or
convert to such LVs from striped/raid0* or vice-versa in order to avoid data corruption.

Add related tests to lvconvert-raid-takeover.sh

Resolves: rhbz1388962
2016-10-27 11:42:07 +02:00
Heinz Mauelshagen
e84f527cd3 lvconvert: revert to only letting raid4 through to lv_raid_convert()
Commit de78e8eae7 allowed to let any raid layout through
which we want to avoid until further validation cleanups.

Related to rhbz1386184
2016-10-26 17:54:19 +02:00
Heinz Mauelshagen
0468f5da6d raid_manip: fix typo
Related to rhbz1386184
2016-10-26 17:53:55 +02:00
Bryn M. Reeves
021715e897 dmsetup: remove stray '\n' in delete log message 2016-10-24 17:21:35 +01:00
Bryn M. Reeves
5eda393488 dmsetup: obey --programid when deleting regions 2016-10-24 17:21:18 +01:00
Heinz Mauelshagen
de78e8eae7 lvconvert: position dedicated parity device in raid4 conversions porperly
On conversions between striped/raid0* and raid4, the kernel expects
the dedicated raid4 parity SubLVs in the first segment area rather than
in the last it's been allocated to, thus the data mapping ain't proper.

Enhance lvconvert (lib/metadata/raid_manip.c) to shift the dedicated
parity SubLVs on conversions from striped/raid0* to raid4 and vice-versa.

In case of raid0_meta -> raid4 where the MD raid0 personality already has
stored RAID array device positions in the superblocks, the MetaLVs have to
be cleared so that the kernel doesn't fail validating the array positions
after lvm has shifted them up by one.

Add more tests to lvconvert-raid-takeover.sh including one to check for
mapping flaws by converting a created raid4 with filesystem -> striped
and fsck it.

Whilst on it:
- add missing direct striped -> raid4 conversion to the takeover array
  to avoid an intermim conversion from striped -> raid0*
- clean up the takeover array
- allow lvconvert to actually call lv_raid_convert() on all takeover requests
  in order to check parameters and display messages provided by takeover
  functions rather than just "...not supported" from within lvconvert
- fix a typo

Resolves: rhbz1386148
2016-10-21 19:00:31 +02:00
Alasdair G Kergon
34da83d729 dmsetup: Produce partial output if dev disappears.
If a device disappears after obtaining the list of devices but before
processing it as a member of that list, dmsetup exits with a failure code.

Most commands still produce what output they can in these circumstances,
but 'ls --tree' and 'info -c' with fields depending on device dependencies
didn't.  Change this.
2016-10-18 18:01:52 +01:00
82 changed files with 3170 additions and 6738 deletions

View File

@@ -1 +1 @@
2.02.167(2)-git (2016-09-26)
2.02.168(2)-git (2016-11-05)

View File

@@ -1 +1 @@
1.02.136-git (2016-09-26)
1.02.137-git (2016-11-05)

View File

@@ -1,5 +1,17 @@
Version 2.02.167 -
======================================
Version 2.02.168 -
====================================
Missing stripe filler now could be also 'zero'.
lvconvert --repair accepts --interval and --background option.
More efficiently prepare _rmeta devices when creating a new raid LV.
Version 2.02.167 - 5th November 2016
====================================
Use log_error in regex and sysfs filter to describe reason of failure.
Fix blkdeactivate to deactivate dev stack if dev on top already unmounted.
Prevent non-synced raid1 repair unless --force
Prevent raid4 creation/conversion on non-supporting kernels
Add direct striped -> raid4 conversion
Fix raid4 parity image pair position on conversions from striped/raid0*
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,16 @@
Version 1.02.136 -
======================================
Version 1.02.137 -
====================================
Version 1.02.136 - 5th November 2016
====================================
Log failure of raid device with log_error level.
Use dm_log_with_errno and translate runtime to dm_log only when needed.
Make log messages from dm and lvm library different from dmeventd.
Notice and Info messages are again logged from dmeventd and its plugins.
Dmeventd now also respects DM_ABORT_ON_INTERNAL_ERRORS as libdm based tool.
Report as non default dm logging also when logging with errno was changed.
Use log_level() macro to consistently decode message log level in dmeventd.
Still produce output when dmsetup dependency tree building finds dev missing.
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.

View File

@@ -99,13 +99,28 @@ static time_t _idle_since = 0;
static char **_initial_registrations = 0;
/* FIXME Make configurable at runtime */
__attribute__((format(printf, 4, 5)))
static void _dmeventd_log(int level, const char *file, int line,
const char *format, ...)
/* All libdm messages */
__attribute__((format(printf, 5, 6)))
static void _libdm_log(int level, const char *file, int line,
int dm_errno_or_class, const char *format, ...)
{
va_list ap;
va_start(ap, format);
dm_event_log("dm", level, file, line, 0, format, ap);
dm_event_log("#dm", level, file, line, dm_errno_or_class, format, ap);
va_end(ap);
}
/* All dmeventd messages */
#undef LOG_MESG
#define LOG_MESG(l, f, ln, e, x...) _dmeventd_log(l, f, ln, e, ## x)
__attribute__((format(printf, 5, 6)))
static void _dmeventd_log(int level, const char *file, int line,
int dm_errno_or_class, const char *format, ...)
{
va_list ap;
va_start(ap, format);
dm_event_log("dmeventd", level, file, line, dm_errno_or_class, format, ap);
va_end(ap);
}
@@ -2191,7 +2206,7 @@ int main(int argc, char *argv[])
openlog("dmeventd", LOG_PID, LOG_DAEMON);
dm_event_log_set(_debug_level, _use_syslog);
dm_log_init(_dmeventd_log);
dm_log_with_errno_init(_libdm_log);
(void) dm_prepare_selinux_context(DMEVENTD_PIDFILE, S_IFREG);
if (dm_create_lockfile(DMEVENTD_PIDFILE) == 0)

View File

@@ -865,28 +865,38 @@ void dm_event_log(const char *subsys, int level, const char *file,
int line, int dm_errno_or_class,
const char *format, va_list ap)
{
static int _abort_on_internal_errors = -1;
static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
static time_t start = 0;
const char *indent = "";
FILE *stream = stdout;
FILE *stream = log_stderr(level) ? stderr : stdout;
int prio;
time_t now;
int log_with_debug = 0;
switch (level & ~(_LOG_STDERR | _LOG_ONCE)) {
if (subsys[0] == '#') {
/* Subsystems starting with '#' are logged
* only when debugging is enabled. */
log_with_debug++;
subsys++;
}
switch (log_level(level)) {
case _LOG_DEBUG:
/* Never shown without -ddd */
if (_debug_level < 3)
return;
prio = LOG_DEBUG;
indent = " ";
break;
case _LOG_INFO:
if (_debug_level < 2)
if (log_with_debug && _debug_level < 2)
return;
prio = LOG_INFO;
indent = " ";
break;
case _LOG_NOTICE:
if (_debug_level < 1)
if (log_with_debug && _debug_level < 1)
return;
prio = LOG_NOTICE;
indent = " ";
@@ -912,12 +922,13 @@ void dm_event_log(const char *subsys, int level, const char *file,
if (!start)
start = now;
now -= start;
fprintf(stream, "[%2d:%02d] %8x:%-6s%s",
(int)now / 60, (int)now % 60,
// TODO: Maybe use shorter ID
// ((int)(pthread_self()) >> 6) & 0xffff,
(int)pthread_self(), subsys,
(_debug_level > 3) ? "" : indent);
if (_debug_level)
fprintf(stream, "[%2d:%02d] %8x:%-6s%s",
(int)now / 60, (int)now % 60,
// TODO: Maybe use shorter ID
// ((int)(pthread_self()) >> 6) & 0xffff,
(int)pthread_self(), subsys,
(_debug_level > 3) ? "" : indent);
if (_debug_level > 3)
fprintf(stream, "%28s:%4d %s", file, line, indent);
vfprintf(stream, _(format), ap);
@@ -926,6 +937,15 @@ void dm_event_log(const char *subsys, int level, const char *file,
}
pthread_mutex_unlock(&_log_mutex);
if (_abort_on_internal_errors < 0)
/* Set when env DM_ABORT_ON_INTERNAL_ERRORS is not "0" */
_abort_on_internal_errors =
strcmp(getenv("DM_ABORT_ON_INTERNAL_ERRORS") ? : "0", "0");
if (_abort_on_internal_errors &&
!strncmp(format, INTERNAL_ERROR, sizeof(INTERNAL_ERROR) - 1))
abort();
}
#if 0 /* left out for now */

View File

@@ -32,7 +32,7 @@ static int _register_count = 0;
static struct dm_pool *_mem_pool = NULL;
static void *_lvm_handle = NULL;
DM_EVENT_LOG_FN("lvm")
DM_EVENT_LOG_FN("#lvm")
static void _lvm2_print_log(int level, const char *file, int line,
int dm_errno_or_class, const char *msg)

View File

@@ -73,8 +73,10 @@ static int _get_mirror_event(struct dso_state *state, char *params)
unsigned i;
struct dm_status_mirror *ms;
if (!dm_get_status_mirror(state->mem, params, &ms))
goto_out;
if (!dm_get_status_mirror(state->mem, params, &ms)) {
log_error("Unable to parse mirror status string.");
return ME_IGNORE;
}
/* Check for bad mirror devices */
for (i = 0; i < ms->dev_count; ++i)
@@ -95,27 +97,23 @@ static int _get_mirror_event(struct dso_state *state, char *params)
dm_pool_free(state->mem, ms);
return r;
out:
log_error("Unable to parse mirror status string.");
return ME_IGNORE;
}
static int _remove_failed_devices(const char *cmd_lvscan, const char *cmd_lvconvert)
static int _remove_failed_devices(const char *cmd_lvscan, const char *cmd_lvconvert,
const char *device)
{
int r;
if (!dmeventd_lvm2_run_with_lock(cmd_lvscan))
log_info("Re-scan of mirrored device failed.");
log_warn("WARNING: Re-scan of mirrored device %s failed.", device);
/* if repair goes OK, report success even if lvscan has failed */
r = dmeventd_lvm2_run_with_lock(cmd_lvconvert);
if (!dmeventd_lvm2_run_with_lock(cmd_lvconvert)) {
log_error("Repair of mirrored device %s failed.", device);
return 0;
}
log_info("Repair of mirrored device %s.",
(r) ? "finished successfully" : "failed");
log_info("Repair of mirrored device %s finished successfully.", device);
return r;
return 1;
}
void process_event(struct dm_task *dmt,
@@ -154,7 +152,8 @@ void process_event(struct dm_task *dmt,
case ME_FAILURE:
log_error("Device failure in %s.", device);
if (!_remove_failed_devices(state->cmd_lvscan,
state->cmd_lvconvert))
state->cmd_lvconvert,
device))
/* FIXME Why are all the error return codes unused? Get rid of them? */
log_error("Failed to remove faulty devices in %s.",
device);
@@ -168,7 +167,7 @@ void process_event(struct dm_task *dmt,
break;
default:
/* FIXME Provide value then! */
log_info("Unknown event received.");
log_warn("WARNING: %s received unknown event.", device);
}
} while (next);
}

View File

@@ -76,7 +76,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char
/* if repair goes OK, report success even if lvscan has failed */
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) {
log_info("Repair of RAID device %s failed.", device);
log_error("Repair of RAID device %s failed.", device);
r = 0;
}
} else {

View File

@@ -301,7 +301,7 @@ out:
static int _use_policy(struct dm_task *dmt, struct dso_state *state)
{
#if THIN_DEBUG
log_info("dmeventd executes: %s.", state->cmd_str);
log_debug("dmeventd executes: %s.", state->cmd_str);
#endif
if (!dmeventd_lvm2_run_with_lock(state->cmd_str)) {
log_error("Failed to extend thin pool %s.",

View File

@@ -7,19 +7,13 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import threading
import subprocess
from . import cfg
import time
from .cmdhandler import options_to_cli_args
import dbus
from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug
import traceback
import os
_rlock = threading.RLock()
_thread_list = list()
def pv_move_lv_cmd(move_options, lv_full_name,
pv_source, pv_source_range, pv_dest_range_list):
@@ -42,15 +36,40 @@ def lv_merge_cmd(merge_options, lv_full_name):
return cmd
def _move_merge(interface_name, cmd, job_state):
add(cmd, job_state)
def _move_merge(interface_name, command, job_state):
# We need to execute these command stand alone by forking & exec'ing
# the command always as we will be getting periodic output from them on
# the status of the long running operation.
command.insert(0, cfg.LVM_CMD)
process = subprocess.Popen(command, stdout=subprocess.PIPE,
env=os.environ,
stderr=subprocess.PIPE, close_fds=True)
done = job_state.Wait(-1)
if not done:
ec, err_msg = job_state.GetError
log_debug("Background process for %s is %d" %
(str(command), process.pid))
lines_iterator = iter(process.stdout.readline, b"")
for line in lines_iterator:
line_str = line.decode("utf-8")
# Check to see if the line has the correct number of separators
try:
if line_str.count(':') == 2:
(device, ignore, percentage) = line_str.split(':')
job_state.Percent = round(
float(percentage.strip()[:-1]), 1)
except ValueError:
log_error("Trying to parse percentage which failed for %s" %
line_str)
out = process.communicate()
if process.returncode == 0:
job_state.Percent = 100
else:
raise dbus.exceptions.DBusException(
interface_name,
'Exit code %s, stderr = %s' % (str(ec), err_msg))
'Exit code %s, stderr = %s' % (str(process.returncode), out[1]))
cfg.load()
return '/'
@@ -85,8 +104,6 @@ def move(interface_name, lv_name, pv_src_obj, pv_source_range,
pv_dests.append((pv_dbus_obj.lvm_id, pr[1], pr[2]))
# Generate the command line for this command, but don't
# execute it.
cmd = pv_move_lv_cmd(move_options,
lv_name,
pv_src.lvm_id,
@@ -109,106 +126,3 @@ def merge(interface_name, lv_uuid, lv_name, merge_options, job_state):
raise dbus.exceptions.DBusException(
interface_name,
'LV with uuid %s and name %s not present!' % (lv_uuid, lv_name))
def background_reaper():
while cfg.run.value != 0:
with _rlock:
num_threads = len(_thread_list) - 1
if num_threads >= 0:
for i in range(num_threads, -1, -1):
_thread_list[i].join(0)
if not _thread_list[i].is_alive():
log_debug("Removing thread: %s" % _thread_list[i].name)
_thread_list.pop(i)
time.sleep(3)
def background_execute(command, background_job):
# Wrap this whole operation in an exception handler, otherwise if we
# hit a code bug we will silently exit this thread without anyone being
# the wiser.
try:
# We need to execute these command stand alone by forking & exec'ing
# the command always!
command.insert(0, cfg.LVM_CMD)
process = subprocess.Popen(command, stdout=subprocess.PIPE,
env=os.environ,
stderr=subprocess.PIPE, close_fds=True)
log_debug("Background process for %s is %d" %
(str(command), process.pid))
lines_iterator = iter(process.stdout.readline, b"")
for line in lines_iterator:
line_str = line.decode("utf-8")
# Check to see if the line has the correct number of separators
try:
if line_str.count(':') == 2:
(device, ignore, percentage) = line_str.split(':')
background_job.Percent = round(
float(percentage.strip()[:-1]), 1)
except ValueError:
log_error("Trying to parse percentage which failed for %s" %
line_str)
out = process.communicate()
if process.returncode == 0:
background_job.Percent = 100
else:
log_error("Failed to execute background job %s, STDERR= %s"
% (str(command), out[1]))
background_job.set_result(process.returncode, out[1])
log_debug("Background process %d complete!" % process.pid)
except Exception:
# In the unlikely event that we blow up, we need to unblock caller which
# is waiting on an answer.
st = traceback.format_exc()
error = "Exception in background thread: \n%s" % st
log_error(error)
background_job.set_result(1, error)
def add(command, reporting_job):
# Create the thread, get it running and then add it to the list
t = threading.Thread(
target=background_execute,
name="thread: " + ' '.join(command),
args=(command, reporting_job))
t.start()
with _rlock:
_thread_list.append(t)
def wait_thread(job, timeout, cb, cbe):
# We need to put the wait on it's own thread, so that we don't block the
# entire dbus queue processing thread
try:
cb(job.state.Wait(timeout))
except Exception as e:
cbe("Wait exception: %s" % str(e))
return 0
def add_wait(job, timeout, cb, cbe):
if timeout == 0:
# Users are basically polling, do not create thread
cb(job.Complete)
else:
t = threading.Thread(
target=wait_thread,
name="thread job.Wait: %s" % job.dbus_object_path(),
args=(job, timeout, cb, cbe)
)
t.start()
with _rlock:
_thread_list.append(t)

View File

@@ -11,20 +11,37 @@ from .pv import load_pvs
from .vg import load_vgs
from .lv import load_lvs
from . import cfg
from .utils import MThreadRunner, log_debug
def load(refresh=True, emit_signal=True, cache_refresh=True, log=True):
def _main_thread_load(refresh=True, emit_signal=True):
num_total_changes = 0
num_total_changes += load_pvs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1]
num_total_changes += load_vgs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1]
num_total_changes += load_lvs(
refresh=refresh,
emit_signal=emit_signal,
cache_refresh=False)[1]
return num_total_changes
def load(refresh=True, emit_signal=True, cache_refresh=True, log=True,
need_main_thread=True):
# Go through and load all the PVs, VGs and LVs
if cache_refresh:
cfg.db.refresh(log)
num_total_changes += load_pvs(refresh=refresh, emit_signal=emit_signal,
cache_refresh=False)[1]
num_total_changes += load_vgs(refresh=refresh, emit_signal=emit_signal,
cache_refresh=False)[1]
num_total_changes += load_lvs(refresh=refresh, emit_signal=emit_signal,
cache_refresh=False)[1]
if need_main_thread:
rc = MThreadRunner(_main_thread_load, refresh, emit_signal).done()
else:
rc = _main_thread_load(refresh, emit_signal)
return num_total_changes
return rc

View File

@@ -8,12 +8,54 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from .automatedproperties import AutomatedProperties
from .utils import job_obj_path_generate
from .utils import job_obj_path_generate, mt_async_result, log_debug
from . import cfg
from .cfg import JOB_INTERFACE
import dbus
import threading
from . import background
from gi.repository import GLib
# Class that handles a client waiting for something to be complete. We either
# get a timeout or the operation is done.
class WaitingClient(object):
# A timeout occurred
@staticmethod
def _timeout(wc):
with wc.rlock:
if wc.in_use:
wc.in_use = False
# Remove ourselves from waiting client
wc.job_state.remove_waiting_client(wc)
wc.timer_id = -1
mt_async_result(wc.cb, wc.job_state.Complete)
wc.job_state = None
def __init__(self, job_state, tmo, cb, cbe):
self.rlock = threading.RLock()
self.job_state = job_state
self.cb = cb
self.cbe = cbe
self.in_use = True # Indicates if object is in play
self.timer_id = -1
if tmo > 0:
self.timer_id = GLib.timeout_add_seconds(
tmo, WaitingClient._timeout, self)
# The job finished before the timer popped and we are being notified that
# it's done
def notify(self):
with self.rlock:
if self.in_use:
self.in_use = False
# Clear timer
if self.timer_id != -1:
GLib.source_remove(self.timer_id)
self.timer_id = -1
mt_async_result(self.cb, self.job_state.Complete)
self.job_state = None
# noinspection PyPep8Naming
@@ -24,9 +66,9 @@ class JobState(object):
self._percent = 0
self._complete = False
self._request = request
self._cond = threading.Condition(self.rlock)
self._ec = 0
self._stderr = ''
self._waiting_clients = []
# This is an lvm command that is just taking too long and doesn't
# support background operation
@@ -57,7 +99,7 @@ class JobState(object):
with self.rlock:
self._complete = value
self._percent = 100
self._cond.notify_all()
self.notify_waiting_clients()
@property
def GetError(self):
@@ -71,29 +113,10 @@ class JobState(object):
else:
return (-1, 'Job is not complete!')
def set_result(self, ec, msg):
with self.rlock:
self.Complete = True
self._ec = ec
self._stderr = msg
def dtor(self):
with self.rlock:
self._request = None
def Wait(self, timeout):
try:
with self._cond:
# Check to see if we are done, before we wait
if not self.Complete:
if timeout != -1:
self._cond.wait(timeout)
else:
self._cond.wait()
return self.Complete
except RuntimeError:
return False
@property
def Result(self):
with self.rlock:
@@ -101,6 +124,36 @@ class JobState(object):
return self._request.result()
return '/'
def add_waiting_client(self, client):
with self.rlock:
# Avoid race condition where it goes complete before we get added
# to the list of waiting clients
if self.Complete:
client.notify()
else:
self._waiting_clients.append(client)
def remove_waiting_client(self, client):
# If a waiting client timer pops before the job is done we will allow
# the client to remove themselves from the list. As we have a lock
# here and a lock in the waiting client too, and they can be obtained
# in different orders, a dead lock can occur.
# As this remove is really optional, we will try to acquire the lock
# and remove. If we are unsuccessful it's not fatal, we just delay
# the time when the objects can be garbage collected by python
if self.rlock.acquire(False):
try:
self._waiting_clients.remove(client)
finally:
self.rlock.release()
def notify_waiting_clients(self):
with self.rlock:
for c in self._waiting_clients:
c.notify()
self._waiting_clients = []
# noinspection PyPep8Naming
class Job(AutomatedProperties):
@@ -122,10 +175,6 @@ class Job(AutomatedProperties):
def Percent(self):
return dbus.Double(float(self.state.Percent))
@Percent.setter
def Percent(self, value):
self.state.Percent = value
@property
def Complete(self):
return dbus.Boolean(self.state.Complete)
@@ -138,9 +187,6 @@ class Job(AutomatedProperties):
def GetError(self):
return dbus.Struct(self.state.GetError, signature="(is)")
def set_result(self, ec, msg):
self.state.set_result(ec, msg)
@dbus.service.method(dbus_interface=JOB_INTERFACE)
def Remove(self):
if self.state.Complete:
@@ -155,7 +201,11 @@ class Job(AutomatedProperties):
out_signature='b',
async_callbacks=('cb', 'cbe'))
def Wait(self, timeout, cb, cbe):
background.add_wait(self, timeout, cb, cbe)
if timeout == 0 or self.state.Complete:
cb(dbus.Boolean(self.state.Complete))
else:
self.state.add_waiting_client(
WaitingClient(self.state, timeout, cb, cbe))
@property
def Result(self):

View File

@@ -21,7 +21,7 @@ from .utils import n, n32
from .loader import common
from .state import State
from . import background
from .utils import round_size
from .utils import round_size, mt_remove_dbus_objects
from .job import JobState
@@ -415,7 +415,6 @@ class Lv(LvCommon):
rc, out, err = cmdhandler.lv_remove(lv_name, remove_options)
if rc == 0:
cfg.om.remove_object(dbo, True)
cfg.load()
else:
# Need to work on error handling, need consistent
@@ -515,15 +514,9 @@ class Lv(LvCommon):
rc, out, err = cmdhandler.vg_lv_snapshot(
lv_name, snapshot_options, name, optional_size)
if rc == 0:
return_path = '/'
cfg.load()
full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
lvs = load_lvs([full_name], emit_signal=True)[0]
for l in lvs:
return_path = l.dbus_object_path()
# Refresh self and all included PVs
cfg.load(cache_refresh=False)
return return_path
return cfg.om.get_object_path_by_lvm_id(full_name)
else:
raise dbus.exceptions.DBusException(
LV_INTERFACE,
@@ -752,9 +745,8 @@ class LvThinPool(Lv):
lv_name, create_options, name, size_bytes)
if rc == 0:
full_name = "%s/%s" % (dbo.vg_name_lookup(), name)
lvs = load_lvs([full_name], emit_signal=True)[0]
for l in lvs:
lv_created = l.dbus_object_path()
cfg.load()
lv_created = cfg.om.get_object_path_by_lvm_id(full_name)
else:
raise dbus.exceptions.DBusException(
LV_INTERFACE,
@@ -816,8 +808,7 @@ class LvCachePool(Lv):
# When we cache an LV, the cache pool and the lv that is getting
# cached need to be removed from the object manager and
# re-created as their interfaces have changed!
cfg.om.remove_object(dbo, emit_signal=True)
cfg.om.remove_object(lv_to_cache, emit_signal=True)
mt_remove_dbus_objects((dbo, lv_to_cache))
cfg.load()
lv_converted = cfg.om.get_object_path_by_lvm_id(fcn)
@@ -879,8 +870,7 @@ class LvCacheLv(Lv):
if rc == 0:
# The cache pool gets removed as hidden and put back to
# visible, so lets delete
cfg.om.remove_object(cache_pool, emit_signal=True)
cfg.om.remove_object(dbo, emit_signal=True)
mt_remove_dbus_objects((cache_pool, dbo))
cfg.load()
uncached_lv_path = cfg.om.get_object_path_by_lvm_id(lv_name)

View File

@@ -22,7 +22,6 @@ from . import lvmdb
from gi.repository import GLib
from .fetch import load
from .manager import Manager
from .background import background_reaper
import traceback
import queue
from . import udevwatch
@@ -64,6 +63,7 @@ def _discard_pending_refreshes():
def process_request():
while cfg.run.value != 0:
# noinspection PyBroadException
try:
req = cfg.worker_q.get(True, 5)
@@ -85,7 +85,7 @@ def process_request():
log_debug(
"Inspect method %s for too many refreshes" %
(str(req.method)))
log_debug("Complete ")
log_debug("Method complete ")
except queue.Empty:
pass
except Exception:
@@ -156,14 +156,11 @@ def main():
cfg.db = lvmdb.DataStore(cfg.args.use_json)
# Start up thread to monitor pv moves
thread_list.append(
threading.Thread(target=background_reaper, name="pv_move_reaper"))
# Using a thread to process requests.
# Using a thread to process requests, we cannot hang the dbus library
# thread that is handling the dbus interface
thread_list.append(threading.Thread(target=process_request))
cfg.load(refresh=False, emit_signal=False)
cfg.load(refresh=False, emit_signal=False, need_main_thread=False)
cfg.loop = GLib.MainLoop()
for process in thread_list:

View File

@@ -42,12 +42,10 @@ class Manager(AutomatedProperties):
raise dbus.exceptions.DBusException(
MANAGER_INTERFACE, "PV Already exists!")
created_pv = []
rc, out, err = cmdhandler.pv_create(create_options, [device])
if rc == 0:
pvs = load_pvs([device], emit_signal=True)[0]
for p in pvs:
created_pv = p.dbus_object_path()
cfg.load()
created_pv = cfg.om.get_object_path_by_lvm_id(device)
else:
raise dbus.exceptions.DBusException(
MANAGER_INTERFACE,
@@ -80,20 +78,14 @@ class Manager(AutomatedProperties):
MANAGER_INTERFACE, 'object path = %s not found' % p)
rc, out, err = cmdhandler.vg_create(create_options, pv_devices, name)
created_vg = "/"
if rc == 0:
vgs = load_vgs([name], emit_signal=True)[0]
for v in vgs:
created_vg = v.dbus_object_path()
# Update the PVS
load_pvs(refresh=True, emit_signal=True, cache_refresh=False)
cfg.load()
return cfg.om.get_object_path_by_lvm_id(name)
else:
raise dbus.exceptions.DBusException(
MANAGER_INTERFACE,
'Exit code %s, stderr = %s' % (str(rc), err))
return created_vg
@dbus.service.method(
dbus_interface=MANAGER_INTERFACE,

View File

@@ -18,7 +18,7 @@ from .utils import vg_obj_path_generate, n, pv_obj_path_generate, \
from .loader import common
from .request import RequestEntry
from .state import State
from .utils import round_size
from .utils import round_size, mt_remove_dbus_objects
# noinspection PyUnusedLocal
@@ -140,7 +140,7 @@ class Pv(AutomatedProperties):
if dbo:
rc, out, err = cmdhandler.pv_remove(pv_name, remove_options)
if rc == 0:
cfg.om.remove_object(dbo, True)
mt_remove_dbus_objects((dbo,))
else:
# Need to work on error handling, need consistent
raise dbus.exceptions.DBusException(
@@ -174,7 +174,7 @@ class Pv(AutomatedProperties):
rc, out, err = cmdhandler.pv_resize(pv_name, new_size_bytes,
resize_options)
if rc == 0:
dbo.refresh()
cfg.load()
else:
raise dbus.exceptions.DBusException(
PV_INTERFACE,

View File

@@ -13,7 +13,7 @@ from gi.repository import GLib
from .job import Job
from . import cfg
import traceback
from .utils import log_error
from .utils import log_error, mt_async_result
class RequestEntry(object):
@@ -57,9 +57,9 @@ class RequestEntry(object):
self._job = Job(self, self._job_state)
cfg.om.register_object(self._job, True)
if self._return_tuple:
self.cb(('/', self._job.dbus_object_path()))
mt_async_result(self.cb, ('/', self._job.dbus_object_path()))
else:
self.cb(self._job.dbus_object_path())
mt_async_result(self.cb, self._job.dbus_object_path())
def run_cmd(self):
try:
@@ -110,9 +110,9 @@ class RequestEntry(object):
if error_rc == 0:
if self.cb:
if self._return_tuple:
self.cb((result, '/'))
mt_async_result(self.cb, (result, '/'))
else:
self.cb(result)
mt_async_result(self.cb, result)
else:
if self.cb_error:
if not error_exception:
@@ -123,7 +123,7 @@ class RequestEntry(object):
else:
error_exception = Exception(error_msg)
self.cb_error(error_exception)
mt_async_result(self.cb_error, error_exception)
else:
# We have a job and it's complete, indicate that it's done.
# TODO: We need to signal the job is done too.

View File

@@ -17,6 +17,8 @@ import datetime
import dbus
from lvmdbusd import cfg
from gi.repository import GLib
import threading
STDOUT_TTY = os.isatty(sys.stdout.fileno())
@@ -494,3 +496,64 @@ def validate_tag(interface, tag):
raise dbus.exceptions.DBusException(
interface, 'tag (%s) contains invalid character, allowable set(%s)'
% (tag, _ALLOWABLE_TAG_CH))
# The methods below which start with mt_* are used to execute the desired code
# on the the main thread of execution to alleviate any issues the dbus-python
# library with regards to multi-threaded access. Essentially, we are trying to
# ensure all dbus library interaction is done from the same thread!
def _async_result(call_back, results):
log_debug('Results = %s' % str(results))
call_back(results)
# Return result in main thread
def mt_async_result(call_back, results):
GLib.idle_add(_async_result, call_back, results)
# Run the supplied function and arguments on the main thread and wait for them
# to complete while allowing the ability to get the return value too.
#
# Example:
# result = MThreadRunner(foo, arg1, arg2).done()
#
class MThreadRunner(object):
@staticmethod
def runner(obj):
obj._run()
with obj.cond:
obj.function_complete = True
obj.cond.notify_all()
def __init__(self, function, *args):
self.f = function
self.rc = None
self.args = args
self.function_complete = False
self.cond = threading.Condition(threading.Lock())
def done(self):
GLib.idle_add(MThreadRunner.runner, self)
with self.cond:
if not self.function_complete:
self.cond.wait()
return self.rc
def _run(self):
if len(self.args):
self.rc = self.f(*self.args)
else:
self.rc = self.f()
def _remove_objects(dbus_objects_rm):
for o in dbus_objects_rm:
cfg.om.remove_object(o, emit_signal=True)
# Remove dbus objects from main thread
def mt_remove_dbus_objects(objs):
MThreadRunner(_remove_objects, objs).done()

View File

@@ -19,7 +19,7 @@ from .request import RequestEntry
from .loader import common
from .state import State
from . import background
from .utils import round_size
from .utils import round_size, mt_remove_dbus_objects
from .job import JobState
@@ -191,14 +191,7 @@ class Vg(AutomatedProperties):
rc, out, err = cmdhandler.vg_remove(vg_name, remove_options)
if rc == 0:
# Remove the VG
cfg.om.remove_object(dbo, True)
# If an LV has hidden LVs, things can get quite involved,
# especially if it's the last thin pool to get removed, so
# lets refresh all
cfg.load()
else:
# Need to work on error handling, need consistent
raise dbus.exceptions.DBusException(
@@ -605,9 +598,7 @@ class Vg(AutomatedProperties):
rc, out, err = create_method(
md.lv_full_name(), data.lv_full_name(), create_options)
if rc == 0:
cfg.om.remove_object(md, emit_signal=True)
cfg.om.remove_object(data, emit_signal=True)
mt_remove_dbus_objects((md, data))
cache_pool_lv = Vg.fetch_new_lv(vg_name, new_name)
else:
raise dbus.exceptions.DBusException(

View File

@@ -370,6 +370,11 @@ void activation_exit(void)
{
}
int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype)
{
return 1;
}
int lv_is_active(const struct logical_volume *lv)
{
return 0;
@@ -1489,6 +1494,26 @@ out:
return r || l;
}
/*
* Check if "raid4" @segtype is supported by kernel.
*
* if segment type is not raid4, return 1.
*/
int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype)
{
unsigned attrs;
if (segtype_is_raid4(segtype) &&
(!segtype->ops->target_present ||
!segtype->ops->target_present(cmd, NULL, &attrs) ||
!(attrs & RAID_FEATURE_RAID4))) {
log_error("RAID module does not support RAID4.");
return 0;
}
return 1;
}
int lv_is_active(const struct logical_volume *lv)
{
return _lv_is_active(lv, NULL, NULL, NULL);
@@ -1683,7 +1708,7 @@ int target_register_events(struct cmd_context *cmd, const char *dso, const struc
if (!r)
return_0;
log_info("%s %s for events", set ? "Monitored" : "Unmonitored", uuid);
log_very_verbose("%s %s for events", set ? "Monitored" : "Unmonitored", uuid);
return 1;
}

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -99,6 +99,7 @@ int target_present(struct cmd_context *cmd, const char *target_name,
int use_modprobe);
int target_version(const char *target_name, uint32_t *maj,
uint32_t *min, uint32_t *patchlevel);
int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype);
int lvm_dm_prefix_check(int major, int minor, const char *prefix);
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg,
struct dm_list *modules);

View File

@@ -2250,8 +2250,8 @@ bad:
return NULL;
}
static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
struct lv_segment *seg, int s)
static char *_add_error_or_zero_device(struct dev_manager *dm, struct dm_tree *dtree,
struct lv_segment *seg, int s, int use_zero)
{
char *dlid, *name;
char errid[32];
@@ -2262,13 +2262,15 @@ static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
uint64_t size = (uint64_t) seg->len * seg->lv->vg->extent_size;
dm_list_iterate_items(seg_i, &seg->lv->segments) {
if (seg == seg_i)
if (seg == seg_i) {
segno = i;
break;
}
++i;
}
if (segno < 0) {
log_error("_add_error_device called with bad segment");
log_error(INTERNAL_ERROR "_add_error_or_zero_device called with bad segment.");
return NULL;
}
@@ -2281,7 +2283,7 @@ static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
seg->lv->name, errid)))
return_NULL;
log_debug_activation("Getting device info for %s [%s]", name, dlid);
log_debug_activation("Getting device info for %s [%s].", name, dlid);
if (!_info(dm->cmd, dlid, 1, 0, &info, NULL, NULL)) {
log_error("Failed to get info for %s [%s].", name, dlid);
return 0;
@@ -2291,14 +2293,19 @@ static char *_add_error_device(struct dev_manager *dm, struct dm_tree *dtree,
/* Create new node */
if (!(node = dm_tree_add_new_dev(dtree, name, dlid, 0, 0, 0, 0, 0)))
return_NULL;
if (!dm_tree_node_add_error_target(node, size))
return_NULL;
if (use_zero) {
if (!dm_tree_node_add_zero_target(node, size))
return_NULL;
} else
if (!dm_tree_node_add_error_target(node, size))
return_NULL;
} else {
/* Already exists */
if (!dm_tree_add_dev(dtree, info.major, info.minor)) {
log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree",
log_error("Failed to add device (%" PRIu32 ":%" PRIu32") to dtree.",
info.major, info.minor);
return_NULL;
return NULL;
}
}
@@ -2310,14 +2317,15 @@ static int _add_error_area(struct dev_manager *dm, struct dm_tree_node *node,
{
char *dlid;
uint64_t extent_size = seg->lv->vg->extent_size;
int use_zero = !strcmp(dm->cmd->stripe_filler, TARGET_NAME_ZERO) ? 1 : 0;
if (!strcmp(dm->cmd->stripe_filler, TARGET_NAME_ERROR)) {
if (!strcmp(dm->cmd->stripe_filler, TARGET_NAME_ERROR) || use_zero) {
/*
* FIXME, the tree pointer is first field of dm_tree_node, but
* we don't have the struct definition available.
*/
struct dm_tree **tree = (struct dm_tree **) node;
if (!(dlid = _add_error_device(dm, *tree, seg, s)))
if (!(dlid = _add_error_or_zero_device(dm, *tree, seg, s, use_zero)))
return_0;
if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_le(seg, s)))
return_0;
@@ -2825,7 +2833,7 @@ static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
if (!(name = dm_build_dm_name(dm->mem, lv->vg->name, lv->name, layer)))
return_0;
/* Even unused thin-pool still needs to get layered UUID -suffix */
/* Even unused thin-pool still needs to get layered UUID -suffix */
if (!layer && lv_is_new_thin_pool(lv))
layer = lv_layer(lv);

View File

@@ -640,8 +640,8 @@ static int _process_config(struct cmd_context *cmd)
if (!strcmp(cmd->stripe_filler, "/dev/ioerror") &&
stat(cmd->stripe_filler, &st))
cmd->stripe_filler = "error";
if (strcmp(cmd->stripe_filler, "error")) {
else if (strcmp(cmd->stripe_filler, "error") &&
strcmp(cmd->stripe_filler, "zero")) {
if (stat(cmd->stripe_filler, &st)) {
log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
"is invalid,", cmd->stripe_filler);

View File

@@ -88,10 +88,9 @@ 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 *opt_arg_values;
struct arg_values *arg_values;
struct dm_list arg_value_groups;
/*

View File

@@ -1111,7 +1111,8 @@ cfg(activation_retry_deactivation_CFG, "retry_deactivation", activation_CFG_SECT
cfg(activation_missing_stripe_filler_CFG, "missing_stripe_filler", activation_CFG_SECTION, CFG_ADVANCED, CFG_TYPE_STRING, DEFAULT_STRIPE_FILLER, vsn(1, 0, 0), NULL, 0, NULL,
"Method to fill missing stripes when activating an incomplete LV.\n"
"Using 'error' will make inaccessible parts of the device return I/O\n"
"errors on access. You can instead use a device path, in which case,\n"
"errors on access. Using 'zero' will return success (and zero) on I/O\n"
"You can instead use a device path, in which case,\n"
"that device will be used in place of missing stripes. Using anything\n"
"other than 'error' with mirrored or snapshotted volumes is likely to\n"
"result in data corruption.\n")

View File

@@ -40,7 +40,7 @@ static int _extract_pattern(struct dm_pool *mem, const char *pat,
break;
default:
log_info("pattern must begin with 'a' or 'r'");
log_error("Pattern must begin with 'a' or 'r'.");
return 0;
}
pat++;
@@ -77,7 +77,7 @@ static int _extract_pattern(struct dm_pool *mem, const char *pat,
*/
ptr = r + strlen(r) - 1;
if (*ptr != sep) {
log_info("invalid separator at end of regex");
log_error("Invalid separator at end of regex.");
return 0;
}
*ptr = '\0';

View File

@@ -168,7 +168,7 @@ static int _parse_dev(const char *file, FILE *fp, dev_t *result)
}
if (sscanf(buffer, "%u:%u", &major, &minor) != 2) {
log_info("sysfs device file not correct format");
log_error("Incorrect format for sysfs device file: %s.", file);
return 0;
}

View File

@@ -140,18 +140,18 @@ static struct labeller *_find_labeller(struct device *dev, char *buf,
sector + scan_sector);
}
if (xlate64(lh->sector_xl) != sector + scan_sector) {
log_info("%s: Label for sector %" PRIu64
" found at sector %" PRIu64
" - ignoring", dev_name(dev),
(uint64_t)xlate64(lh->sector_xl),
sector + scan_sector);
log_very_verbose("%s: Label for sector %" PRIu64
" found at sector %" PRIu64
" - ignoring", dev_name(dev),
(uint64_t)xlate64(lh->sector_xl),
sector + scan_sector);
continue;
}
if (calc_crc(INITIAL_CRC, (uint8_t *)&lh->offset_xl, LABEL_SIZE -
((uint8_t *) &lh->offset_xl - (uint8_t *) lh)) !=
xlate32(lh->crc_xl)) {
log_info("Label checksum incorrect on %s - "
"ignoring", dev_name(dev));
log_very_verbose("Label checksum incorrect on %s - "
"ignoring", dev_name(dev));
continue;
}
if (found)
@@ -243,8 +243,8 @@ int label_remove(struct device *dev)
}
if (wipe) {
log_info("%s: Wiping label at sector %" PRIu64,
dev_name(dev), sector);
log_very_verbose("%s: Wiping label at sector %" PRIu64,
dev_name(dev), sector);
if (!dev_write(dev, sector << SECTOR_SHIFT, LABEL_SIZE,
buf)) {
log_error("Failed to remove label from %s at "
@@ -333,9 +333,9 @@ int label_write(struct device *dev, struct label *label)
if (!dev_open(dev))
return_0;
log_info("%s: Writing label to sector %" PRIu64 " with stored offset %"
PRIu32 ".", dev_name(dev), label->sector,
xlate32(lh->offset_xl));
log_very_verbose("%s: Writing label to sector %" PRIu64 " with stored offset %"
PRIu32 ".", dev_name(dev), label->sector,
xlate32(lh->offset_xl));
if (!dev_write(dev, label->sector << SECTOR_SHIFT, LABEL_SIZE, buf)) {
log_debug_devs("Failed to write label to %s", dev_name(dev));
r = 0;

View File

@@ -67,7 +67,7 @@ struct log_stream_item {
char *buffer;
};
struct log_stream {
static struct log_stream {
struct log_stream_item out;
struct log_stream_item err;
struct log_stream_item report;
@@ -476,9 +476,9 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
int bufused, n;
const char *trformat; /* Translated format string */
char *newbuf;
int use_stderr = level & _LOG_STDERR;
int log_once = level & _LOG_ONCE;
int log_bypass_report = level & _LOG_BYPASS_REPORT;
int use_stderr = log_stderr(level);
int log_once = log_once(level);
int log_bypass_report = log_bypass_report(level);
int fatal_internal_error = 0;
size_t msglen;
const char *indent_spaces = "";
@@ -489,7 +489,7 @@ static void _vprint_log(int level, const char *file, int line, int dm_errno_or_c
struct dm_report *orig_report;
int logged_via_report = 0;
level &= ~(_LOG_STDERR|_LOG_ONCE|_LOG_BYPASS_REPORT);
level = log_level(level);
if (_abort_on_internal_errors_env_present < 0) {
if ((env_str = getenv("DM_ABORT_ON_INTERNAL_ERRORS"))) {
@@ -715,8 +715,8 @@ void print_log_libdm(int level, const char *file, int line, int dm_errno_or_clas
* LOG_WARN level and it's not going to stderr (so we're
* printing common message that is not an error/warning).
*/
if (!(level & _LOG_STDERR) &&
((level & ~(_LOG_STDERR|_LOG_ONCE|_LOG_BYPASS_REPORT)) == _LOG_WARN))
if (!log_stderr(level) &&
(log_level(level) == _LOG_WARN))
level |= _LOG_BYPASS_REPORT;
_log_stream.out.stream = report_stream;

View File

@@ -50,6 +50,10 @@
#define _LOG_STDERR 0x0080 /* force things to go to stderr, even if loglevel would make them go to stdout */
#define _LOG_ONCE 0x0100 /* downgrade to NOTICE if this has been already logged */
#define _LOG_BYPASS_REPORT 0x0200 /* do not log through report even if report available */
#define log_level(x) ((x) & 0x0f) /* obtain message level */
#define log_stderr(x) ((x) & _LOG_STDERR) /* obtain stderr bit */
#define log_once(x) ((x) & _LOG_ONCE) /* obtain once bit */
#define log_bypass_report(x) ((x) & _LOG_BYPASS_REPORT)/* obtain bypass bit */
#define INTERNAL_ERROR "Internal error: "

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -1418,6 +1418,7 @@ int lv_active_change(struct cmd_context *cmd, struct logical_volume *lv,
enum activation_change activate, int needs_exclusive)
{
const char *ay_with_mode = NULL;
struct lv_segment *seg = first_seg(lv);
if (activate == CHANGE_ASY)
ay_with_mode = "sh";
@@ -1454,6 +1455,9 @@ deactivate:
break;
case CHANGE_ALY:
case CHANGE_AAY:
if (!raid4_is_supported(cmd, seg->segtype))
goto no_raid4;
if (needs_exclusive || _lv_is_exclusive(lv)) {
log_verbose("Activating logical volume %s exclusively locally.",
display_lvname(lv));
@@ -1468,6 +1472,9 @@ deactivate:
break;
case CHANGE_AEY:
exclusive:
if (!raid4_is_supported(cmd, seg->segtype))
goto no_raid4;
log_verbose("Activating logical volume %s exclusively.",
display_lvname(lv));
if (!activate_lv_excl(cmd, lv))
@@ -1476,6 +1483,9 @@ exclusive:
case CHANGE_ASY:
case CHANGE_AY:
default:
if (!raid4_is_supported(cmd, seg->segtype))
goto no_raid4;
if (needs_exclusive || _lv_is_exclusive(lv))
goto exclusive;
log_verbose("Activating logical volume %s.", display_lvname(lv));
@@ -1488,6 +1498,10 @@ exclusive:
log_error("Failed to unlock logical volume %s.", display_lvname(lv));
return 1;
no_raid4:
log_error("Failed to activate %s LV %s", lvseg_name(seg), display_lvname(lv));
return 0;
}
char *lv_active_dup(struct dm_pool *mem, const struct logical_volume *lv)

View File

@@ -3844,6 +3844,7 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
uint32_t fa, s;
int clear_metadata = 0;
uint32_t area_multiple = 1;
int fail;
if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
@@ -3917,45 +3918,60 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
if (!vg_write(lv->vg) || !vg_commit(lv->vg))
return_0;
for (s = 0; s < seg->area_count; s++) {
meta_lv = seg_metalv(seg, s);
if (test_mode())
log_verbose("Test mode: Skipping wiping of metadata areas.");
else {
fail = 0;
/* Activate all rmeta devices locally first (more efficient) */
for (s = 0; !fail && s < seg->area_count; s++) {
meta_lv = seg_metalv(seg, s);
if (test_mode()) {
lv_set_hidden(meta_lv);
continue;
if (!activate_lv_local(meta_lv->vg->cmd, meta_lv)) {
log_error("Failed to activate %s for clearing.",
display_lvname(meta_lv));
fail = 1;
}
}
/* For clearing, simply activate locally */
if (!activate_lv_local(meta_lv->vg->cmd, meta_lv)) {
log_error("Failed to activate %s/%s for clearing",
meta_lv->vg->name, meta_lv->name);
return 0;
/* Clear all rmeta devices */
for (s = 0; !fail && s < seg->area_count; s++) {
meta_lv = seg_metalv(seg, s);
log_verbose("Clearing metadata area of %s.",
display_lvname(meta_lv));
/*
* Rather than wiping meta_lv->size, we can simply
* wipe '1' to remove the superblock of any previous
* RAID devices. It is much quicker.
*/
if (!wipe_lv(meta_lv, (struct wipe_params)
{ .do_zero = 1, .zero_sectors = 1 })) {
stack;
fail = 1;
}
}
log_verbose("Clearing metadata area of %s",
display_lvname(meta_lv));
/*
* Rather than wiping meta_lv->size, we can simply
* wipe '1' to remove the superblock of any previous
* RAID devices. It is much quicker.
*/
if (!wipe_lv(meta_lv, (struct wipe_params)
{ .do_zero = 1, .zero_sectors = 1 })) {
log_error("Failed to zero %s/%s",
meta_lv->vg->name, meta_lv->name);
return 0;
/* Deactivate all rmeta devices */
for (s = 0; s < seg->area_count; s++) {
meta_lv = seg_metalv(seg, s);
if (!deactivate_lv(meta_lv->vg->cmd, meta_lv)) {
log_error("Failed to deactivate %s after clearing.",
display_lvname(meta_lv));
fail = 1;
}
/* Wipe any temporary tags required for activation. */
str_list_wipe(&meta_lv->tags);
}
if (!deactivate_lv(meta_lv->vg->cmd, meta_lv)) {
log_error("Failed to deactivate %s/%s",
meta_lv->vg->name, meta_lv->name);
return 0;
}
lv_set_hidden(meta_lv);
/* Wipe any temporary tags required for activation. */
str_list_wipe(&meta_lv->tags);
if (fail)
/* Fail, after trying to deactivate all we could */
return_0;
}
for (s = 0; s < seg->area_count; s++)
lv_set_hidden(seg_metalv(seg, s));
}
seg->area_len += extents / area_multiple;

View File

@@ -1208,8 +1208,8 @@ int lv_raid_convert(struct logical_volume *lv,
const uint32_t new_region_size,
struct dm_list *allocate_pvs);
int lv_raid_rebuild(struct logical_volume *lv, struct dm_list *rebuild_pvs);
int lv_raid_replace(struct logical_volume *lv, struct dm_list *remove_pvs,
struct dm_list *allocate_pvs);
int lv_raid_replace(struct logical_volume *lv, int force,
struct dm_list *remove_pvs, struct dm_list *allocate_pvs);
int lv_raid_remove_missing(struct logical_volume *lv);
int partial_raid_lv_supports_degraded_activation(const struct logical_volume *lv);
/* -- metadata/raid_manip.c */

View File

@@ -266,19 +266,16 @@ static int _deactivate_and_remove_lvs(struct volume_group *vg, struct dm_list *r
*
* Returns: 1 if in-sync, 0 otherwise.
*/
#define _RAID_IN_SYNC_RETRIES 6
static int _raid_in_sync(struct logical_volume *lv)
{
int retries = _RAID_IN_SYNC_RETRIES;
dm_percent_t sync_percent;
if (seg_is_striped(first_seg(lv)))
return 1;
if (!lv_raid_percent(lv, &sync_percent)) {
log_error("Unable to determine sync status of %s/%s.",
lv->vg->name, lv->name);
return 0;
}
if (sync_percent == DM_PERCENT_0) {
do {
/*
* FIXME We repeat the status read here to workaround an
* unresolved kernel bug when we see 0 even though the
@@ -290,14 +287,34 @@ static int _raid_in_sync(struct logical_volume *lv)
lv->vg->name, lv->name);
return 0;
}
if (sync_percent == DM_PERCENT_100)
if (sync_percent > DM_PERCENT_0)
break;
if (retries == _RAID_IN_SYNC_RETRIES)
log_warn("WARNING: Sync status for %s is inconsistent.",
display_lvname(lv));
}
usleep(500000);
} while (--retries);
return (sync_percent == DM_PERCENT_100) ? 1 : 0;
}
/* Check if RaidLV @lv is synced or any raid legs of @lv are not synced */
static int _raid_devs_sync_healthy(struct logical_volume *lv)
{
char *raid_health;
if (!_raid_in_sync(lv))
return 0;
if (!seg_is_raid1(first_seg(lv)))
return 1;
if (!lv_raid_dev_health(lv, &raid_health))
return_0;
return (strchr(raid_health, 'a') || strchr(raid_health, 'D')) ? 0 : 1;
}
/*
* _raid_remove_top_layer
* @lv
@@ -1039,10 +1056,10 @@ static int _extract_image_components(struct lv_segment *seg, uint32_t idx,
seg_metatype(seg, idx) = AREA_UNASSIGNED;
/* FIXME Remove duplicated prefix? */
if (!(data_lv->name = _generate_raid_name(data_lv, "_extracted", -1)))
if (!(data_lv->name = _generate_raid_name(data_lv, "extracted", -1)))
return_0;
if (!(meta_lv->name = _generate_raid_name(meta_lv, "_extracted", -1)))
if (!(meta_lv->name = _generate_raid_name(meta_lv, "extracted", -1)))
return_0;
*extracted_rmeta = meta_lv;
@@ -1054,6 +1071,7 @@ static int _extract_image_components(struct lv_segment *seg, uint32_t idx,
/*
* _raid_extract_images
* @lv
* @force: force a replacement in case of primary mirror leg
* @new_count: The absolute count of images (e.g. '2' for a 2-way mirror)
* @target_pvs: The list of PVs that are candidates for removal
* @shift: If set, use _shift_and_rename_image_components().
@@ -1068,7 +1086,8 @@ static int _extract_image_components(struct lv_segment *seg, uint32_t idx,
*
* Returns: 1 on success, 0 on failure
*/
static int _raid_extract_images(struct logical_volume *lv, uint32_t new_count,
static int _raid_extract_images(struct logical_volume *lv,
int force, uint32_t new_count,
struct dm_list *target_pvs, int shift,
struct dm_list *extracted_meta_lvs,
struct dm_list *extracted_data_lvs)
@@ -1136,11 +1155,16 @@ static int _raid_extract_images(struct logical_volume *lv, uint32_t new_count,
!lv_is_on_pvs(seg_metalv(seg, s), target_pvs))
continue;
if (!_raid_in_sync(lv) &&
(!seg_is_mirrored(seg) || (s == 0))) {
/*
* Kernel may report raid LV in-sync but still
* image devices may not be in-sync or faulty.
*/
if (!_raid_devs_sync_healthy(lv) &&
(!seg_is_mirrored(seg) || (s == 0 && !force))) {
log_error("Unable to extract %sRAID image"
" while RAID array is not in-sync",
seg_is_mirrored(seg) ? "primary " : "");
" while RAID array is not in-sync%s",
seg_is_mirrored(seg) ? "primary " : "",
seg_is_mirrored(seg) ? " (use --force option to replace)" : "");
return 0;
}
}
@@ -1185,7 +1209,7 @@ static int _raid_remove_images(struct logical_volume *lv,
if (!removal_lvs)
removal_lvs = &removed_lvs;
if (!_raid_extract_images(lv, new_count, allocate_pvs, 1,
if (!_raid_extract_images(lv, 0, new_count, allocate_pvs, 1,
removal_lvs, removal_lvs)) {
log_error("Failed to extract images from %s/%s",
lv->vg->name, lv->name);
@@ -1375,7 +1399,7 @@ int lv_raid_split(struct logical_volume *lv, const char *split_name,
return_0;
}
if (!_raid_extract_images(lv, new_count, splittable_pvs, 1,
if (!_raid_extract_images(lv, 0, new_count, splittable_pvs, 1,
&removal_lvs, &data_list)) {
log_error("Failed to extract images from %s/%s",
lv->vg->name, lv->name);
@@ -2459,7 +2483,7 @@ static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv,
0 /* chunk_size */,
0 /* seg->region_size */, 0u /* extents_copied */ ,
NULL /* pvmove_source_seg */))) {
log_error("Failed to allocate new raid0 segement for LV %s.", display_lvname(lv));
log_error("Failed to allocate new raid0 segment for LV %s.", display_lvname(lv));
return NULL;
}
@@ -2519,42 +2543,51 @@ static struct possible_takeover_reshape_type _possible_takeover_reshape_types[]
{ .current_types = SEG_STRIPED_TARGET, /* linear, i.e. seg->area_count = 1 */
.possible_types = SEG_RAID1,
.current_areas = 1,
.options = ALLOW_NONE },
.options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
{ .current_types = SEG_STRIPED_TARGET, /* linear, i.e. seg->area_count = 1 */
.possible_types = SEG_RAID0|SEG_RAID0_META,
.current_areas = 1,
.options = ALLOW_STRIPE_SIZE },
{ .current_types = SEG_STRIPED_TARGET, /* striped, i.e. seg->area_count > 1 */
{ .current_types = SEG_STRIPED_TARGET, /* striped -> raid0*, i.e. seg->area_count > 1 */
.possible_types = SEG_RAID0|SEG_RAID0_META,
.current_areas = ~0U,
.options = ALLOW_NONE },
{ .current_types = SEG_STRIPED_TARGET, /* striped -> raid4 , i.e. seg->area_count > 1 */
.possible_types = SEG_RAID4,
.current_areas = ~0U,
.options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
/* raid0* -> */
{ .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count = 1 */
.possible_types = SEG_RAID1,
.current_areas = 1,
.options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
{ .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0* -> striped, i.e. seg->area_count > 1 */
.possible_types = SEG_STRIPED_TARGET,
.current_areas = ~0U,
.options = ALLOW_NONE },
{ .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count > 1 */
{ .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0* -> raid0*, i.e. seg->area_count > 1 */
.possible_types = SEG_RAID0_META|SEG_RAID0,
.current_areas = ~0U,
.options = ALLOW_NONE },
{ .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0* -> raid4, i.e. seg->area_count > 1 */
.possible_types = SEG_RAID4,
.current_areas = ~0U,
.options = ALLOW_NONE },
{ .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0 striped, i.e. seg->area_count > 0 */
.options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
/* raid4 -> -> */
{ .current_types = SEG_RAID4, /* raid4 ->striped/raid0*, i.e. seg->area_count > 1 */
.possible_types = SEG_STRIPED_TARGET|SEG_RAID0|SEG_RAID0_META,
.current_areas = ~0U,
.options = ALLOW_NONE },
/* raid1 -> */
/* raid1 -> mirror */
{ .current_types = SEG_RAID1,
.possible_types = SEG_RAID1|SEG_MIRROR,
.possible_types = SEG_MIRROR,
.current_areas = ~0U,
.options = ALLOW_NONE },
.options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
/* mirror -> raid1 with arbitrary number of legs */
{ .current_types = SEG_MIRROR,
.possible_types = SEG_MIRROR|SEG_RAID1,
.possible_types = SEG_RAID1,
.current_areas = ~0U,
.options = ALLOW_NONE },
{ .current_types = SEG_RAID4,
.possible_types = SEG_STRIPED_TARGET|SEG_RAID0|SEG_RAID0_META,
.current_areas = ~0U,
.options = ALLOW_NONE },
.options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */
/* END */
{ .current_types = 0 }
@@ -2861,9 +2894,176 @@ static int _raid1_to_mirrored_wrapper(TAKEOVER_FN_ARGS)
allocate_pvs, 1, &removal_lvs);
}
/*
* HM Helper: (raid0_meta -> raid4)
*
* To convert raid0_meta to raid4, which involves shifting the
* parity device to lv segment area 0 and thus changing MD
* array roles, detach the MetaLVs and reload as raid0 in
* order to wipe them then reattach and set back to raid0_meta.
*/
static int _clear_meta_lvs(struct logical_volume *lv)
{
uint32_t s;
struct lv_segment *seg = first_seg(lv);
struct lv_segment_area *tmp_areas;
const struct segment_type *tmp_segtype;
struct dm_list meta_lvs;
struct lv_list *lvl_array, *lvl;
/* Reject non-raid0_meta segment types cautiously */
if (!seg_is_raid0_meta(seg) ||
!seg->meta_areas)
return_0;
if (!(lvl_array = dm_pool_alloc(lv->vg->vgmem, seg->area_count * sizeof(*lvl_array))))
return_0;
dm_list_init(&meta_lvs);
tmp_areas = seg->meta_areas;
/* Extract all MetaLVs listing them on @meta_lvs */
log_debug_metadata("Extracting all MetaLVs of %s to activate as raid0",
display_lvname(lv));
if (!_extract_image_component_sublist(seg, RAID_META, 0, seg->area_count, &meta_lvs, 0))
return_0;
/* Memorize meta areas and segtype to set again after initializing. */
seg->meta_areas = NULL;
tmp_segtype = seg->segtype;
if (!(seg->segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID0)) ||
!lv_update_and_reload(lv))
return_0;
/*
* Now deactivate the MetaLVs before clearing, so
* that _clear_lvs() will activate them visible.
*/
log_debug_metadata("Deactivating pulled out MetaLVs of %s before initializing.",
display_lvname(lv));
dm_list_iterate_items(lvl, &meta_lvs)
if (!deactivate_lv(lv->vg->cmd, lvl->lv))
return_0;
log_debug_metadata("Clearing allocated raid0_meta metadata LVs for conversion to raid4");
if (!_clear_lvs(&meta_lvs)) {
log_error("Failed to initialize metadata LVs");
return 0;
}
/* Set memorized meta areas and raid0_meta segtype */
seg->meta_areas = tmp_areas;
seg->segtype = tmp_segtype;
log_debug_metadata("Adding metadata LVs back into %s", display_lvname(lv));
s = 0;
dm_list_iterate_items(lvl, &meta_lvs) {
lv_set_hidden(lvl->lv);
if (!set_lv_segment_area_lv(seg, s++, lvl->lv, 0, RAID_META))
return 0;
}
return 1;
}
/*
* HM Helper: (raid0* <-> raid4)
*
* Rename SubLVs (pairs) allowing to shift names w/o collisions with active ones.
*/
#define SLV_COUNT 2
static int _rename_area_lvs(struct logical_volume *lv, const char *suffix)
{
uint32_t s;
size_t sz = strlen("rimage") + (suffix ? strlen(suffix) : 0) + 1;
char *sfx[SLV_COUNT] = { NULL, NULL };
struct lv_segment *seg = first_seg(lv);
/* Create _generate_raid_name() suffixes w/ or w/o passed in @suffix */
for (s = 0; s < SLV_COUNT; s++)
if (!(sfx[s] = dm_pool_alloc(lv->vg->cmd->mem, sz)) ||
dm_snprintf(sfx[s], sz, suffix ? "%s%s" : "%s", s ? "rmeta" : "rimage", suffix) < 0)
return_0;
/* Change names (temporarily) to be able to shift numerical name suffixes */
for (s = 0; s < seg->area_count; s++) {
if (!(seg_lv(seg, s)->name = _generate_raid_name(lv, sfx[0], s)))
return_0;
if (seg->meta_areas &&
!(seg_metalv(seg, s)->name = _generate_raid_name(lv, sfx[1], s)))
return_0;
}
for (s = 0; s < SLV_COUNT; s++)
dm_pool_free(lv->vg->cmd->mem, sfx[s]);
return 1;
}
/*
* HM Helper: (raid0* <-> raid4)
*
* Switch area LVs in lv segment @seg indexed by @s1 and @s2
*/
static void _switch_area_lvs(struct lv_segment *seg, uint32_t s1, uint32_t s2)
{
struct logical_volume *lvt;
lvt = seg_lv(seg, s1);
seg_lv(seg, s1) = seg_lv(seg, s2);
seg_lv(seg, s2) = lvt;
/* Be cautious */
if (seg->meta_areas) {
lvt = seg_metalv(seg, s1);
seg_metalv(seg, s1) = seg_metalv(seg, s2);
seg_metalv(seg, s2) = lvt;
}
}
/*
* HM Helper:
*
* shift range of area LVs in @seg in range [ @s1, @s2 ] up if @s1 < @s2,
* else down bubbling the parity SubLVs up/down whilst shifting.
*/
static void _shift_area_lvs(struct lv_segment *seg, uint32_t s1, uint32_t s2)
{
uint32_t s;
if (s1 < s2)
/* Forward shift n+1 -> n */
for (s = s1; s < s2; s++)
_switch_area_lvs(seg, s, s + 1);
else
/* Reverse shift n-1 -> n */
for (s = s1; s > s2; s--)
_switch_area_lvs(seg, s, s - 1);
}
/*
* Switch position of first and last area lv within
* @lv to move parity SubLVs from end to end.
*
* Direction depends on segment type raid4 / raid0_meta.
*/
static int _shift_parity_dev(struct lv_segment *seg)
{
if (seg_is_raid0_meta(seg))
_shift_area_lvs(seg, seg->area_count - 1, 0);
else if (seg_is_raid4(seg))
_shift_area_lvs(seg, 0, seg->area_count - 1);
else
return 0;
return 1;
}
/* raid45 -> raid0* / striped */
static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
{
int rename_sublvs = 0;
struct lv_segment *seg = first_seg(lv);
struct dm_list removal_lvs;
@@ -2879,10 +3079,39 @@ static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
if (!_raid_in_sync(lv))
return 0;
if (!yes && yes_no_prompt("Are you sure you want to convert \"%s\" LV %s to \"%s\" "
"type losing all resilience? [y/n]: ",
lvseg_name(seg), display_lvname(lv), new_segtype->name) == 'n') {
log_error("Logical volume %s NOT converted to \"%s\"",
display_lvname(lv), new_segtype->name);
return 0;
}
if (sigint_caught())
return_0;
/* Archive metadata */
if (!archive(lv->vg))
return_0;
/*
* raid4 (which actually gets mapped to raid5/dedicated first parity disk)
* needs shifting of SubLVs to move the parity SubLV pair in the first area
* to the last one before conversion to raid0[_meta]/striped to allow for
* SubLV removal from the end of the areas arrays.
*/
if (seg_is_raid4(seg)) {
/* Shift parity SubLV pair "PDD..." -> "DD...P" to be able to remove it off the end */
if (!_shift_parity_dev(seg))
return 0;
if (segtype_is_any_raid0(new_segtype) &&
!(rename_sublvs = _rename_area_lvs(lv, "_"))) {
log_error("Failed to rename %s LV %s MetaLVs", lvseg_name(seg), display_lvname(lv));
return 0;
}
}
/* Remove meta and data LVs requested */
if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, &removal_lvs, 0, 0))
return 0;
@@ -2902,7 +3131,19 @@ static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS)
seg->region_size = 0;
return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs);
if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs))
return_0;
if (rename_sublvs) {
if (!_rename_area_lvs(lv, NULL)) {
log_error("Failed to rename %s LV %s MetaLVs", lvseg_name(seg), display_lvname(lv));
return 0;
}
if (!lv_update_and_reload(lv))
return_0;
}
return 1;
}
static int _striped_to_raid0_wrapper(struct logical_volume *lv,
@@ -2930,6 +3171,9 @@ static int _striped_to_raid0_wrapper(struct logical_volume *lv,
static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
{
struct lv_segment *seg = first_seg(lv);
struct dm_list removal_lvs;
dm_list_init(&removal_lvs);
if (seg_is_raid10(seg))
return _takeover_unsupported_yet(lv, new_stripes, new_segtype);
@@ -2944,6 +3188,13 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
return 0;
}
/* FIXME: restricted to raid4 for the time being... */
if (!segtype_is_raid4(new_segtype)) {
/* Can't convert striped/raid0* to e.g. raid10_offset */
log_error("Can't convert %s to %s", display_lvname(lv), new_segtype->name);
return 0;
}
/* Archive metadata */
if (!archive(lv->vg))
return_0;
@@ -2961,7 +3212,10 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
log_debug_metadata("Adding metadata LVs to %s", display_lvname(lv));
if (!_raid0_add_or_remove_metadata_lvs(lv, 1 /* update_and_reload */, allocate_pvs, NULL))
return 0;
}
/* raid0_meta -> raid4 needs clearing of MetaLVs in order to avoid raid disk role cahnge issues in the kernel */
} else if (segtype_is_raid4(new_segtype) &&
!_clear_meta_lvs(lv))
return 0;
/* Add the additional component LV pairs */
log_debug_metadata("Adding %" PRIu32 " component LV pair(s) to %s", new_image_count - lv_raid_image_count(lv),
@@ -2969,8 +3223,9 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, NULL, 0, 1))
return 0;
if (!segtype_is_raid4(new_segtype)) {
/* Can't convert striped/raid0* to e.g. raid10_offset */
if (segtype_is_raid4(new_segtype) &&
(!_shift_parity_dev(seg) ||
!_rename_area_lvs(lv, "_"))) {
log_error("Can't convert %s to %s", display_lvname(lv), new_segtype->name);
return 0;
}
@@ -2987,6 +3242,14 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS)
if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, NULL))
return_0;
if (segtype_is_raid4(new_segtype)) {
/* We had to rename SubLVs because of collision free sgifting, rename back... */
if (!_rename_area_lvs(lv, NULL))
return 0;
if (!lv_update_and_reload(lv))
return_0;
}
return 1;
}
@@ -3630,6 +3893,7 @@ has_enough_space:
* new SubLVS are allocated on PVs on list @allocate_pvs.
*/
static int _lv_raid_rebuild_or_replace(struct logical_volume *lv,
int force,
struct dm_list *remove_pvs,
struct dm_list *allocate_pvs,
int rebuild)
@@ -3804,7 +4068,8 @@ try_again:
* supplied - knowing that only the image with the error target
* will be affected.
*/
if (!_raid_extract_images(lv, raid_seg->area_count - match_count,
if (!_raid_extract_images(lv, force,
raid_seg->area_count - match_count,
partial_segment_removed ?
&lv->vg->pvs : remove_pvs, 0,
&old_lvs, &old_lvs)) {
@@ -3909,7 +4174,7 @@ skip_alloc:
int lv_raid_rebuild(struct logical_volume *lv,
struct dm_list *rebuild_pvs)
{
return _lv_raid_rebuild_or_replace(lv, rebuild_pvs, NULL, 1);
return _lv_raid_rebuild_or_replace(lv, 0, rebuild_pvs, NULL, 1);
}
/*
@@ -3922,10 +4187,11 @@ int lv_raid_rebuild(struct logical_volume *lv,
* allocating new SubLVs from PVs on list @allocate_pvs.
*/
int lv_raid_replace(struct logical_volume *lv,
int force,
struct dm_list *remove_pvs,
struct dm_list *allocate_pvs)
{
return _lv_raid_rebuild_or_replace(lv, remove_pvs, allocate_pvs, 0);
return _lv_raid_rebuild_or_replace(lv, force, remove_pvs, allocate_pvs, 0);
}
int lv_raid_remove_missing(struct logical_volume *lv)

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -268,6 +268,7 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd,
#define RAID_FEATURE_RAID10 (1U << 0) /* version 1.3 */
#define RAID_FEATURE_RAID0 (1U << 1) /* version 1.7 */
#define RAID_FEATURE_RESHAPING (1U << 2) /* version 1.8 */
#define RAID_FEATURE_RAID4 (1U << 3) /* ! version 1.8 or 1.9.0 */
#ifdef RAID_INTERNAL
int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved.
* Copyright (C) 2011-2016 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -366,7 +366,7 @@ static int _raid_target_present(struct cmd_context *cmd,
static int _raid_checked = 0;
static int _raid_present = 0;
static int _raid_attrs = 0;
static unsigned _raid_attrs = 0;
uint32_t maj, min, patchlevel;
unsigned i;
@@ -389,6 +389,12 @@ static int _raid_target_present(struct cmd_context *cmd,
else
log_very_verbose("Target raid does not support %s.",
_features[i].feature);
if (!(maj == 1 && (min == 8 || (min == 9 && patchlevel == 0))))
_raid_attrs |= RAID_FEATURE_RAID4;
else
log_very_verbose("Target raid does not support %s.",
SEG_TYPE_NAME_RAID4);
}
if (attributes)

View File

@@ -114,9 +114,9 @@ static void _default_log_line(int level,
const char *f, va_list ap)
{
static int _abort_on_internal_errors = -1;
FILE *out = (level & _LOG_STDERR) ? stderr : stdout;
FILE *out = log_stderr(level) ? stderr : stdout;
level &= ~(_LOG_STDERR | _LOG_BYPASS_REPORT);
level = log_level(level);
if (level <= _LOG_WARN || _verbose) {
if (level < _LOG_WARN)
@@ -137,8 +137,7 @@ static void _default_log_line(int level,
__attribute__((format(printf, 5, 6)))
static void _default_log_with_errno(int level,
const char *file __attribute__((unused)),
int line __attribute__((unused)), int dm_errno_or_class,
const char *file, int line, int dm_errno_or_class,
const char *f, ...)
{
va_list ap;
@@ -162,29 +161,75 @@ static void _default_log(int level, const char *file,
dm_log_fn dm_log = _default_log;
dm_log_with_errno_fn dm_log_with_errno = _default_log_with_errno;
/*
* Wrapper function to reformat new messages to and
* old style logging which had not used errno parameter
*
* As we cannot simply pass '...' to old function we
* need to process arg list locally and just pass '%s' + buffer
*/
__attribute__((format(printf, 5, 6)))
static void _log_to_default_log(int level,
const char *file, int line, int dm_errno_or_class,
const char *f, ...)
{
va_list ap;
char buf[2 * PATH_MAX + 256]; /* big enough for most messages */
va_start(ap, f);
vsnprintf(buf, sizeof(buf), f, ap);
va_end(ap);
dm_log(level, file, line, "%s", buf);
}
/*
* Wrapper function take 'old' style message without errno
* and log it via new logging function with errno arg
*
* This minor case may happen if new libdm is used with old
* recompiled tool that would decided to use new logging,
* but still would like to use old binary plugins.
*/
__attribute__((format(printf, 4, 5)))
static void _log_to_default_log_with_errno(int level,
const char *file, int line, const char *f, ...)
{
va_list ap;
char buf[2 * PATH_MAX + 256]; /* big enough for most messages */
va_start(ap, f);
vsnprintf(buf, sizeof(buf), f, ap);
va_end(ap);
dm_log_with_errno(level, file, line, 0, "%s", buf);
}
void dm_log_init(dm_log_fn fn)
{
if (fn)
if (fn) {
dm_log = fn;
else
dm_log_with_errno = _log_to_default_log;
} else {
dm_log = _default_log;
dm_log_with_errno = _default_log_with_errno;
dm_log_with_errno = _default_log_with_errno;
}
}
int dm_log_is_non_default(void)
{
return (dm_log == _default_log) ? 0 : 1;
return (dm_log == _default_log && dm_log_with_errno == _default_log_with_errno) ? 0 : 1;
}
void dm_log_with_errno_init(dm_log_with_errno_fn fn)
{
if (fn)
if (fn) {
dm_log = _log_to_default_log_with_errno;
dm_log_with_errno = fn;
else
} else {
dm_log = _default_log;
dm_log_with_errno = _default_log_with_errno;
dm_log = _default_log;
}
}
void dm_log_init_verbose(int level)

View File

@@ -3881,7 +3881,7 @@ merge:
continue;
if (_extents_overlap(ext, next)) {
log_warn("Warning: region IDs " FMTu64 " and "
log_warn("WARNING: region IDs " FMTu64 " and "
FMTu64 " overlap. Some events will be "
"counted twice.", ext->id, next->id);
/* merge larger extent into smaller */
@@ -4002,11 +4002,11 @@ int dm_stats_create_group(struct dm_stats *dms, const char *members,
}
if (precise && (precise != count))
log_warn("Grouping regions with different clock resolution: "
"precision may be lost");
log_warn("WARNING: Grouping regions with different clock resolution: "
"precision may be lost.");
if (!_stats_group_check_overlap(dms, regions, count))
log_info("Creating group with overlapping regions");
log_very_verbose("Creating group with overlapping regions.");
if (!_stats_create_group(dms, regions, alias, group_id))
goto bad;
@@ -4048,7 +4048,7 @@ int dm_stats_delete_group(struct dm_stats *dms, uint64_t group_id,
if (dm_bit(regions, i)) {
dm_bit_clear(regions, i);
if (remove_regions && !dm_stats_delete_region(dms, i))
log_warn("Failed to delete region "
log_warn("WARNING: Failed to delete region "
FMTu64 " on %s.", i, dms->name);
}
}
@@ -4142,7 +4142,7 @@ static int _stats_group_file_regions(struct dm_stats *dms, uint64_t *region_ids,
* returned by FIEMAP imply a kernel bug or a corrupt fs.
*/
if (!_stats_group_check_overlap(dms, regions, count))
log_info("Creating group with overlapping regions.");
log_very_verbose("Creating group with overlapping regions.");
if (!_stats_create_group(dms, regions, alias, &group_id))
goto bad;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -18,16 +18,10 @@
#include "libdevmapper.h"
extern dm_log_fn dm_log;
extern dm_log_with_errno_fn dm_log_with_errno;
#define LOG_MESG(l, f, ln, e, x...) \
do { \
if (dm_log_is_non_default()) \
dm_log(l, f, ln, ## x); \
else \
dm_log_with_errno(l, f, ln, e, ## x); \
} while (0)
dm_log_with_errno(l, f, ln, e, ## x)
#define LOG_LINE(l, x...) LOG_MESG(l, __FILE__, __LINE__, 0, ## x)
#define LOG_LINE_WITH_ERRNO(l, e, x...) LOG_MESG(l, __FILE__, __LINE__, e, ## x)

View File

@@ -365,6 +365,9 @@ See corresponding operation --splitmirrors.
VG/RaidLV
.br
\[bu]
Options \-\-background, \-\-interval.
.br
\[bu]
Replace failed PVs in RaidLV.
.B lvconvert \-\-replace
@@ -502,6 +505,9 @@ Change the type of log used by MirrorLV.
VG/MirrorLV
.br
\[bu]
Options \-\-background, \-\-interval.
.br
\[bu]
Replace failed PVs in MirrorLV.
.B lvconvert \-\-type linear

View File

@@ -34,6 +34,7 @@ TOOL=blkdeactivate
DEV_DIR='/dev'
SYS_BLK_DIR='/sys/block'
MOUNTPOINT="/bin/mountpoint"
UMOUNT="/bin/umount"
DMSETUP="@sbindir@/dmsetup"
LVM="@sbindir@/lvm"
@@ -157,9 +158,11 @@ device_umount_one() {
echo -n " [UMOUNT]: unmounting $name ($kname) mounted on $mnt... "
if eval $UMOUNT $UMOUNT_OPTS "$(printf "%s" "$mnt")" $OUT $ERR; then
echo "done"
else
elif $MOUNTPOINT -q "$mnt"; then
echo "skipping"
add_device_to_skip_list
else
echo "already unmounted"
fi
else
echo " [SKIP]: unmount of $name ($kname) mounted on $mnt"

View File

@@ -14,7 +14,7 @@
# on those systems.
# A macro to pull in an include file from an appropriate location.
%define import() %include %(test -e %{S:%1} && echo %{S:%1} || echo %{_sourcedir}/%1)
%global import() %%include %%(test -e %%{S:%%1} && echo %%{S:%%1} || echo %%{_sourcedir}/%%1)
%import source.inc

View File

@@ -14,70 +14,73 @@
%global rhel 0
%endif
%define enableif() \
%global configure_flags %{?configure_flags} --%(if test %1 -gt 0; then echo enable-%2; else echo disable-%2; fi)
# TODO: This will disable feature, even though configure could enable it if requirements were met:
# SUGGESTION: rename this to enableiff - "if and only if" and use weaker enableif not producing disable flag
# NOTE: It is in some cases guarded by another if, so may not produce anything...
%global enableif() \
%%global configure_flags %%{?configure_flags} --%%(if test %%1 -gt 0; then echo enable-%%2; else echo disable-%%2; fi)
%define with() \
%global configure_flags %(echo -n "%{?configure_flags} " | sed -e "s,--with-%1=[^ ]*,,"; test -n "%{?2}" && echo --with-%1=%2) \
%global with_flags %(echo -n "%{?with_flags} " | sed -e "s,%1,,"; test -n "%{?2}" && test "%{?2}" != none && echo %1)
%global with() \
%%global configure_flags %%(echo -n "%%{?configure_flags} " | sed -e "s,--with-%%1=[^ ]*,,"; test -n "%%{?2}" && echo --with-%%1=%%2) \
%%global with_flags %%(echo -n "%%{?with_flags} " | sed -e "s,%%1,,"; test -n "%%{?2}" && test "%%{?2}" != none && echo %%1)
%global services monitor
%define service() \
%global services %(echo -n "%{?services} " | sed -e s,%1,,; test "%2" = 1 && echo %1)
%global service() \
%%global services %%(echo -n "%%{?services} " | sed -e s,%%1,,; test "%%2" = 1 && echo %%1)
%define maybe() \
%if %(test -n "%{?2}" && echo 1 || echo 0) \
%* \
%endif
%global maybe() \
%%if %%(test -n "%%{?2}" && echo 1 || echo 0) \
%%* \
%%endif
%define have_with() %(if echo %{with_flags} | grep -q %1; then echo 1; else echo 0; fi)
%define have_service() %(if echo %{services} | grep -q %1; then echo 1; else echo 0; fi)
%global have_with() %%(if echo %%{with_flags} | grep -q %%1; then echo 1; else echo 0; fi)
%global have_service() %%(if echo %%{services} | grep -q %%1; then echo 1; else echo 0; fi)
%define daemon_reload \
%if %{enable_systemd} \
%global daemon_reload \
%%if %%{enable_systemd} \
systemctl daemon-reload > /dev/null 2>&1 || : \
%endif \
%%endif \
: \
%{nil}
%%{nil}
%define enable(s:t:) \
%if %{have_service %{-s*}} \
%if %{enable_systemd} \
%global enable(s:t:) \
%%if %%{have_service %%{-s*}} \
%%if %%{enable_systemd} \
if [ $1 = 1 ]; then \
systemctl preset lvm2-%{-s*}.%{-t*} > /dev/null 2>&1 || : \
systemctl preset lvm2-%%{-s*}.%%{-t*} > /dev/null 2>&1 || : \
fi \
%else \
/sbin/chkconfig --add lvm2-%{-s*} \
%endif \
%endif \
%%else \
/sbin/chkconfig --add lvm2-%%{-s*} \
%%endif \
%%endif \
: \
%{nil}
%%{nil}
%define disable(s:t:) \
%if %{have_service %{-s*}} \
%if %{enable_systemd} \
%global disable(s:t:) \
%%if %%{have_service %%{-s*}} \
%%if %%{enable_systemd} \
if [ $1 = 0 ]; then \
systemctl --no-reload disable lvm2-%{-s*}.%{-t*} > /dev/null 2>&1 || : \
%if %{-t*} == socket \
systemctl --no-reload disable lvm2-%{-s*}.service > /dev/null 2>&1 || : \
%endif \
systemctl stop lvm2-%{-s*}.%{-t*} > /dev/null 2>&1 || : \
%if %{-t*} == socket \
systemctl stop lvm2-%{-s*}.service > /dev/null 2>&1 || : \
%endif \
systemctl --no-reload disable lvm2-%%{-s*}.%%{-t*} > /dev/null 2>&1 || : \
%%if %%{-t*} == socket \
systemctl --no-reload disable lvm2-%%{-s*}.service > /dev/null 2>&1 || : \
%%endif \
systemctl stop lvm2-%%{-s*}.%%{-t*} > /dev/null 2>&1 || : \
%%if %%{-t*} == socket \
systemctl stop lvm2-%%{-s*}.service > /dev/null 2>&1 || : \
%%endif \
fi \
%else \
/sbin/chkconfig --del lvm2-%{-s*} \
%endif \
%endif \
%%else \
/sbin/chkconfig --del lvm2-%%{-s*} \
%%endif \
%%endif \
: \
%{nil}
%%{nil}
%define try_restart(s:t:) \
%if %{have_service %{-s*}} && %{enable_systemd} \
%global try_restart(s:t:) \
%%if %%{have_service %%{-s*}} && %%{enable_systemd} \
if [ $1 = 1 ]; then \
systemctl try-restart lvm2-%{-s*}.%{-t*} > /dev/null 2>&1 || : \
systemctl try-restart lvm2-%%{-s*}.%%{-t*} > /dev/null 2>&1 || : \
fi \
%endif \
%%endif \
: \
%{nil}
%%{nil}

View File

@@ -176,13 +176,13 @@ fi
%attr(644, -, -) %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/lvm.conf
%attr(644, -, -) %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/lvmlocal.conf
%dir %{_sysconfdir}/lvm/profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/command_profile_template.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/metadata_profile_template.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/thin-generic.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/thin-performance.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/cache-mq.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/cache-smq.profile
%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/lvm/profile/lvmdbusd.profile
%{_sysconfdir}/lvm/profile/command_profile_template.profile
%{_sysconfdir}/lvm/profile/metadata_profile_template.profile
%{_sysconfdir}/lvm/profile/thin-generic.profile
%{_sysconfdir}/lvm/profile/thin-performance.profile
%{_sysconfdir}/lvm/profile/cache-mq.profile
%{_sysconfdir}/lvm/profile/cache-smq.profile
%{_sysconfdir}/lvm/profile/lvmdbusd.profile
%dir %{_sysconfdir}/lvm/backup
%dir %{_sysconfdir}/lvm/cache
%dir %{_sysconfdir}/lvm/archive

View File

@@ -12,6 +12,7 @@
%global enable_udev 1
%global enable_systemd 1
%global enable_cmirror 1
# enable_lvmlockd is redefined in spec/build.inc, so are other :-/
%global enable_lvmlockd 1
%global enable_lvmetad 1
%global enable_lvmpolld 1
@@ -48,23 +49,28 @@
%global req_udev udev >= 181-1
%if %{fedora} >= 22 || %{rhel} >= 7
%if %{fedora} >= 24 || %{rhel} >= 7
%service lvmlockd 1
%define sanlock_version 3.2.4-1
%define enable_lockd_dlm 1
%define enable_lockd_sanlock 1
%global sanlock_version 3.3.0-1
%global enable_lockd_dlm 1
%global enable_lockd_sanlock 1
%if %{rhel}
%ifarch i686 x86_64 s390x
%global buildreq_lockd_dlm dlm-devel >= %{dlm_version}
%else
%define enable_lockd_dlm 0
%global enable_lockd_dlm 0
%endif
%ifarch x86_64 ppc64le ppc64 aarch64
%global buildreq_lockd_sanlock sanlock-devel >= %{sanlock_version}
%else
%define enable_lockd_sanlock 0
%global enable_lockd_sanlock 0
%endif
%endif
%else
%if %{fedora} >= 22
%service lvmlockd 1
%global enable_lockd_dlm 1
%endif
%endif
##############################################################
@@ -140,7 +146,7 @@
# same as FC 16 above, only with older udev
%if %{rhel} == 6
%define req_udev udev >= 147-2
%global req_udev udev >= 147-2
%global req_dm_persistent device-mapper-persistent-data >= 0.1.4
%endif
@@ -149,7 +155,7 @@
# Do not reset Release to 1 unless both lvm2 and device-mapper
# versions are increased together.
%define device_mapper_version 1.02.97
%global device_mapper_version 1.02.97
Summary: Userland logical volume management tools
Name: lvm2

View File

@@ -77,6 +77,9 @@ help:
@echo " check_cluster Run tests with cluster daemon."
@echo " check_lvmetad Run tests with lvmetad daemon."
@echo " check_lvmpolld Run tests with lvmpolld daemon."
@echo " check_cluster_lvmpolld Run tests with clvmd and lvmpolld daemon."
@echo " check_lvmetad_lvmpolld Run tests with lvmetad and lvmpolld daemon."
@echo " check_all_lvmpolld Run all tests with lvmpolld daemon."
@echo " check_lvmlockd_sanlock Run tests with lvmlockd and sanlock."
@echo " check_lvmlockd_dlm Run tests with lvmlockd and dlm."
@echo " check_lvmlockd_test Run tests with lvmlockd --test."
@@ -144,6 +147,21 @@ endif
ifeq ("@BUILD_LVMPOLLD@", "yes")
check_lvmpolld: .tests-stamp
VERBOSE=$(VERBOSE) ./lib/runner \
--testdir . --outdir results \
--flavours ndev-lvmpolld --only $(T) --skip $(S)
check_cluster_lvmpolld: .tests-stamp
VERBOSE=$(VERBOSE) ./lib/runner \
--testdir . --outdir results \
--flavours ndev-cluster-lvmpolld --only $(T) --skip $(S)
check_lvmetad_lvmpolld: .tests-stamp
VERBOSE=$(VERBOSE) ./lib/runner \
--testdir . --outdir results \
--flavours ndev-lvmetad-lvmpolld --only $(T) --skip $(S)
check_all_lvmpolld: .tests-stamp
VERBOSE=$(VERBOSE) ./lib/runner \
--testdir . --outdir results \
--flavours ndev-lvmpolld,ndev-cluster-lvmpolld,ndev-lvmetad-lvmpolld --only $(T) --skip $(S)

View File

@@ -1376,6 +1376,15 @@ have_raid() {
esac
}
have_raid4 () {
local r=1
have_raid 1 8 0 && r=0
have_raid 1 9 1 && r=1
return $r
}
have_cache() {
test "$CACHE" = shared -o "$CACHE" = internal || {
echo "Cache is not built-in." >&2

View File

@@ -16,7 +16,7 @@ TEST_RAID=raid456
aux raid456_replace_works || skip
aux have_raid 1 5 2 || skip
run_types raid4 -i 2 "$dev1" "$dev2" "$dev3" "$dev4"
aux have_raid4 && run_types raid4 -i 2 "$dev1" "$dev2" "$dev3" "$dev4"
run_types raid5 -i 2 "$dev1" "$dev2" "$dev3" "$dev4"
run_types raid6 -i 3 "$dev1" "$dev2" "$dev3" "$dev4" "$dev5"

View File

@@ -16,6 +16,9 @@ SKIP_WITH_LVMPOLLD=1
aux have_raid 1 9 0 || skip
correct_raid4_layout=0
aux have_raid 1 9 1 && correct_raid4_layout=1
aux prepare_vg 9 288
# Delay 1st leg so that rebuilding status characters
@@ -78,22 +81,61 @@ aux wait_for_sync $vg $lv1
# Clean up
lvremove --yes $vg/$lv1
# Create 3-way raid0
lvcreate -y -aey --type raid0 -i 3 -L 64M -n $lv1 $vg
check lv_field $vg/$lv1 segtype "raid0"
# Create 3-way striped
lvcreate -y -aey --type striped -i 3 -L 64M -n $lv1 $vg
check lv_field $vg/$lv1 segtype "striped"
check lv_field $vg/$lv1 stripes 3
echo y | mkfs -t ext4 /dev/mapper/$vg-$lv1
fsck -fn /dev/mapper/$vg-$lv1
# Convert raid0 -> raid4
# Create 3-way raid0
lvcreate -y -aey --type raid0 -i 3 -L 64M -n $lv2 $vg
check lv_field $vg/$lv2 segtype "raid0"
check lv_field $vg/$lv2 stripes 3
echo y | mkfs -t ext4 /dev/mapper/$vg-$lv2
fsck -fn /dev/mapper/$vg-$lv2
# Create 3-way raid0_meta
lvcreate -y -aey --type raid0_meta -i 3 -L 64M -n $lv3 $vg
check lv_field $vg/$lv3 segtype "raid0_meta"
check lv_field $vg/$lv3 stripes 3
echo y | mkfs -t ext4 /dev/mapper/$vg-$lv3
fsck -fn /dev/mapper/$vg-$lv3
if [ $correct_raid4_layout -eq 1 ]
then
# Create 3-way raid4
lvcreate -y -aey --type raid4 -i 3 -L 64M -n $lv4 $vg
check lv_field $vg/$lv4 segtype "raid4"
check lv_field $vg/$lv4 stripes 4
echo y | mkfs -t ext4 /dev/mapper/$vg-$lv4
fsck -fn /dev/mapper/$vg-$lv4
aux wait_for_sync $vg $lv4
fsck -fn /dev/mapper/$vg-$lv4
# Convert raid4 -> striped (correct raid4 mapping test!)
lvconvert -y --ty striped $vg/$lv4
check lv_field $vg/$lv4 segtype "striped"
check lv_field $vg/$lv4 stripes 3
fsck -fn /dev/mapper/$vg-$lv4
# Convert striped -> raid4
lvconvert -y --ty raid4 $vg/$lv1
lvchange --refresh $vg/$lv1
check lv_field $vg/$lv1 segtype "raid4"
check lv_field $vg/$lv1 stripes 4
fsck -fn /dev/mapper/$vg-$lv1
aux wait_for_sync $vg $lv1
fsck -fn /dev/mapper/$vg-$lv1
# Convert raid0 -> raid4
lvconvert -y --ty raid4 $vg/$lv2
check lv_field $vg/$lv2 segtype "raid4"
check lv_field $vg/$lv2 stripes 4
fsck -fn /dev/mapper/$vg-$lv2
aux wait_for_sync $vg $lv2
fsck -fn /dev/mapper/$vg-$lv2
# Convert raid4 -> raid0_meta
lvconvert -y --ty raid0_meta $vg/$lv1
check lv_field $vg/$lv1 segtype "raid0_meta"
@@ -116,11 +158,24 @@ fsck -fn /dev/mapper/$vg-$lv1
# Convert raid0 -> raid4
lvconvert -y --ty raid4 $vg/$lv1
lvchange --refresh $vg/$lv1
check lv_field $vg/$lv1 segtype "raid4"
check lv_field $vg/$lv1 stripes 4
fsck -fn /dev/mapper/$vg-$lv1
aux wait_for_sync $vg $lv1
fsck -fn /dev/mapper/$vg-$lv1
# Convert raid4 -> striped
lvconvert -y --ty striped $vg/$lv1
check lv_field $vg/$lv1 segtype "striped"
check lv_field $vg/$lv1 stripes 3
fsck -fn /dev/mapper/$vg-$lv1
else
not lvcreate -y -aey --type raid4 -i 3 -L 64M -n $lv4 $vg
not lvconvert -y --ty raid4 $vg/$lv1
not lvconvert -y --ty raid4 $vg/$lv2
fi
vgremove -ff $vg

View File

@@ -31,8 +31,11 @@ aux have_raid 1 3 0 || skip
aux prepare_pvs 7 # 7 devices for 2 dev replacement of 5-dev RAID6
vgcreate -s 256k $vg $(cat DEVICES)
levels="5 6"
aux have_raid4 && levels="4 5 6"
# RAID 4/5/6 (can replace up to 'parity' devices)
for i in 4 5 6; do
for i in $levels; do
lvcreate --type raid$i -i 3 -l 3 -n $lv1 $vg
if [ $i -eq 6 ]; then

View File

@@ -25,7 +25,8 @@ which "$FSCK" || skip
#
# Main
#
aux have_cache 1 5 0 || skip
# older versions of cache target reported unreliably write failures
aux have_cache 1 7 0 || skip
aux prepare_vg 4

View File

@@ -53,7 +53,8 @@ delay 50
# RAID1 triple-leg single replace during initial sync
lvcreate --type raid1 -m 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3"
aux disable_dev "$dev2" "$dev3"
not lvconvert -y --repair $vg/$lv1
# FIXME 2016/11/04 AGK: Disabled next line as it fails to guarantee it is not already in sync.
#not lvconvert -y --repair $vg/$lv1
aux wait_for_sync $vg $lv1
lvconvert -y --repair $vg/$lv1
vgreduce --removemissing $vg

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

@@ -21,6 +21,9 @@ aux can_use_16T || skip
aux have_raid 1 3 0 || skip
segtypes="raid5"
aux have_raid4 && segtypes="raid4 raid5"
# Prepare 5x ~1P sized devices
aux prepare_pvs 5 1000000000
@@ -53,7 +56,7 @@ check raid_leg_status $vg1 $lv1 "AA"
lvremove -ff $vg1
# 750 TiB raid4/5
for segtype in raid4 raid5; do
for segtype in $segtypes; do
lvcreate --type $segtype -i 3 -L 750T -n $lv1 $vg1 --nosync
check lv_field $vg1/$lv1 size "750.00t"
check raid_leg_status $vg1 $lv1 "AAAA"

View File

@@ -16,17 +16,20 @@ SKIP_WITH_LVMPOLLD=1
aux have_raid 1 7 0 || skip
segtypes=raid5
aux have_raid4 && segtypes="raid4 raid5"
aux prepare_vg 6
# Delay 1st leg so that rebuilding status characters
# can be read before resync finished too quick.
aux delay_dev "$dev1" 0 10 $(get first_extent_sector "$dev1")
aux delay_dev "$dev1" 0 50 $(get first_extent_sector "$dev1")
# raid0/raid0_meta don't support resynchronization
for r in raid0 raid0_meta
do
lvcreate --yes --type raid0 -i 3 -l 1 -n $lv1 $vg
lvcreate --yes --type $r -i 3 -l 1 -n $lv1 $vg
check raid_leg_status $vg $lv1 "AAA"
lvremove --yes $vg/$lv1
done
@@ -43,8 +46,8 @@ lvcreate --yes --type raid1 --nosync -m 2 -l 1 -n $lv1 $vg
check raid_leg_status $vg $lv1 "AAA"
lvremove --yes $vg/$lv1
for r in raid4 raid5
do
for r in $segtypes
do
# raid4/5 support resynchronization
lvcreate --yes --type $r -i 3 -l 2 -n $lv1 $vg
check raid_leg_status $vg $lv1 "aaaa"

View File

@@ -23,6 +23,9 @@ lv_devices() {
########################################################
aux have_raid 1 3 0 || skip
RAID4=""
aux have_raid4 && RAID4=raid4
aux prepare_pvs 6 20 # 6 devices for RAID10 (2-mirror,3-stripe) test
vgcreate -s 512k $vg $(cat DEVICES)
@@ -54,7 +57,7 @@ aux wait_for_sync $vg $lv1
lvremove -ff $vg
# Create RAID 4/5/6 (explicit 3-stripe + parity devs)
for i in raid4 \
for i in $RAID4 \
raid5 raid5_ls raid5_la raid5_rs raid5_ra \
raid6 raid6_zr raid6_nr raid6_nc; do
@@ -64,7 +67,7 @@ for i in raid4 \
done
# Create RAID 4/5/6 (explicit 3-stripe + parity devs) - Set min/max recovery
for i in raid4 \
for i in $RAID4 \
raid5 raid5_ls raid5_la raid5_rs raid5_ra \
raid6 raid6_zr raid6_nr raid6_nc; do

View File

@@ -24,6 +24,28 @@ pvscan --cache
vgs | grep $vg1
# Check that an LV cannot be activated by lvchange while VG is exported
lvcreate -n $lv1 -l 4 -a n $vg1
check lv_exists $vg1
vgexport $vg1
fail lvs $vg1
fail lvchange -ay $vg1/$lv1
vgimport $vg1
check lv_exists $vg1
check lv_field $vg/$lv1 lv_active ""
# Check that an LV cannot be activated by pvscan while VG is exported
vgexport $vg1
pvscan --cache -aay "$dev1"
pvscan --cache -aay "$dev2"
vgimport $vg1
check lv_exists $vg1
check lv_field $vg1/$lv1 lv_active ""
pvscan --cache -aay "$dev1"
pvscan --cache -aay "$dev2"
check lv_field $vg1/$lv1 lv_active "active"
lvchange -an $vg1/$lv1
# When MDA is ignored on PV, do not read any VG
# metadata from such PV as it may contain old
# metadata which hasn't been updated for some

View File

@@ -16,6 +16,9 @@ SKIP_WITH_LVMPOLLD=1
aux have_raid 1 3 0 || skip
levels="5 6"
aux have_raid4 && levels="4 5 6"
aux prepare_pvs 6 80
vgcreate -s 256K $vg $(cat DEVICES)
@@ -37,7 +40,7 @@ for deactivate in true false; do
#check raid_images_contiguous $vg $lv1
# Extend and reduce 3-striped RAID 4/5/6
for i in 4 5 6 ; do
for i in $levels ; do
lvcreate --type raid$i -i 3 -l 3 -n $lv2 $vg
test $deactivate && {
@@ -59,7 +62,7 @@ done
# Bug 1005434
# Ensure extend is contiguous
lvcreate --type raid4 -l 2 -i 2 -n $lv1 $vg "$dev4" "$dev5" "$dev6"
lvcreate --type raid5 -l 2 -i 2 -n $lv1 $vg "$dev4" "$dev5" "$dev6"
lvextend -l +2 --alloc contiguous $vg/$lv1
check lv_tree_on $vg $lv1 "$dev4" "$dev5" "$dev6"

View File

@@ -40,13 +40,14 @@ snap_and_merge() {
kill $SLEEP_PID
aux delay_dev "$dev1" 0 200 $(get first_extent_sector "$dev1"):
lvchange --refresh $vg/$lv1
lvchange --poll n --refresh $vg/$lv1
dmsetup table
lvs -a -o+lv_merging,lv_merge_failed $vg
sleep 1
check lv_attr_bit state $vg/$lv1 "a"
check lv_attr_bit state $vg/$lv2 "a"
aux error_dev "$dev2" $(get first_extent_sector "$dev2"):
aux enable_dev "$dev1"
# delay to let snapshot merge 'discover' failing COW device
sleep 1
sync
@@ -56,7 +57,7 @@ snap_and_merge() {
check lv_attr_bit state $vg/$lv2 "m"
# device OK and running in full speed
aux enable_dev "$dev1" "$dev2"
aux enable_dev "$dev2"
# reactivate so merge can finish
lvchange -an $vg

View File

@@ -23,6 +23,7 @@ lvcreate -l 1 -n lv1 $vg "$dev1"
invalid vgextend
# --metadatacopies => use --pvmetadatacopies
invalid vgextend --metadatacopies 3 $vg "$dev1" 2>&1 | tee out
grep -- "use --pvmetadatacopies" out
# VG name should exist
fail vgextend --restoremissing $vg-invalid "$dev1"

View File

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

View File

@@ -17,214 +17,215 @@
* Put all long args that don't have a corresponding short option first.
*/
/* *INDENT-OFF* */
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", pvmetadatacopies_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", vgmetadatacopies_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)
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)
/* Allow some variations */
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)
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)
/*
* ... and now the short args.
*/
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)
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)
/* this should always be last */
arg(ARG_COUNT, '-', "", 0, 0, 0)
arg(ARG_COUNT, '-', "", NULL, 0, 0)
/* *INDENT-ON* */

File diff suppressed because it is too large Load Diff

View File

@@ -1,170 +0,0 @@
/*
* 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
#define CMD_FLAG_SECONDARY_SYNTAX 2
/* 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

File diff suppressed because it is too large Load Diff

View File

@@ -1611,7 +1611,7 @@ static int _udevcomplete_all(CMD_ARGS)
}
if (!_switches[YES_ARG]) {
log_warn("This operation will destroy all semaphores %s%.0d%swith keys "
log_warn("WARNING: This operation will destroy all semaphores %s%.0d%swith keys "
"that have a prefix %" PRIu16 " (0x%" PRIx16 ").",
age ? "older than " : "", age, age ? " minutes " : "",
DM_COOKIE_MAGIC, DM_COOKIE_MAGIC);
@@ -2707,6 +2707,9 @@ static int _add_dep(CMD_ARGS)
/*
* Create and walk dependency tree
*
* An incomplete _dtree may still be used by the caller,
* but the error must be reported.
*/
static int _build_whole_deptree(const struct command *cmd)
{
@@ -2724,12 +2727,14 @@ static int _build_whole_deptree(const struct command *cmd)
static int _display_tree(CMD_ARGS)
{
if (!_build_whole_deptree(cmd))
return_0;
int r;
_display_tree_walk_children(dm_tree_find_node(_dtree, 0, 0), 0);
r = _build_whole_deptree(cmd);
return 1;
if (_dtree)
_display_tree_walk_children(dm_tree_find_node(_dtree, 0, 0), 0);
return r;
}
/*
@@ -4471,9 +4476,14 @@ static int _report_init(const struct command *cmd, const char *subcommand)
selection, NULL, NULL)))
goto_out;
if ((_report_type & DR_TREE) && cmd && !_build_whole_deptree(cmd)) {
err("Internal device dependency tree creation failed.");
goto out;
r = 1;
if ((_report_type & DR_TREE) && cmd) {
r = _build_whole_deptree(cmd);
if (!_dtree) {
err("Internal device dependency tree creation failed.");
goto out;
}
}
if (!_switches[INTERVAL_ARG])
@@ -4484,8 +4494,6 @@ static int _report_init(const struct command *cmd, const char *subcommand)
if (field_prefixes)
dm_report_set_output_field_name_prefix(_report, "dm_");
r = 1;
out:
if (len)
dm_free(options);
@@ -5270,6 +5278,8 @@ static int _stats_delete(CMD_ARGS)
name = argv[0];
}
if (_switches[PROGRAM_ID_ARG])
program_id = _string_args[PROGRAM_ID_ARG];
if (_switches[ALL_PROGRAMS_ARG])
program_id = DM_STATS_ALL_PROGRAMS;
@@ -5313,7 +5323,7 @@ static int _stats_delete(CMD_ARGS)
log_error("Could not delete statistics region");
goto out;
}
log_info("Deleted statistics region " FMTu64 ".\n", region_id);
log_info("Deleted statistics region " FMTu64 ".", region_id);
}
r = 1;
@@ -6782,8 +6792,15 @@ unknown:
argc--, argv++;
}
if (_switches[COLS_ARG] && !_report_init(cmd, subcommand))
goto_out;
/* Default to success */
ret = 0;
if (_switches[COLS_ARG]) {
if (!_report_init(cmd, subcommand))
ret = 1;
if (ret || !_report)
goto_out;
}
if (_switches[COUNT_ARG])
_count = ((uint32_t)_int_args[COUNT_ARG]) ? : UINT32_MAX;
@@ -6795,14 +6812,17 @@ unknown:
&_disp_units);
if (!_disp_factor) {
log_error("Invalid --units argument.");
ret = 1;
goto out;
}
}
/* Start interval timer. */
if (_count > 1)
if (!_start_timer())
if (!_start_timer()) {
ret = 1;
goto_out;
}
doit:
multiple_devices = (cmd->repeatable_cmd && argc != 1 &&
@@ -6819,18 +6839,19 @@ doit:
if (_count > 1 && r) {
printf("\n");
/* wait for --interval and update timestamps */
if (!_do_report_wait())
if (!_do_report_wait()) {
ret = 1;
goto_out;
}
}
}
if (!r)
if (!r) {
ret = 1;
goto_out;
}
} while (--_count);
/* Success */
ret = 0;
out:
if (_report)
dm_report_free(_report);
@@ -6843,5 +6864,5 @@ out:
if (_initial_timestamp)
dm_timestamp_destroy(_initial_timestamp);
return ret;
return (_switches[HELP_ARG] || _switches[VERSION_ARG]) ? 0 : ret;
}

View File

@@ -1436,286 +1436,3 @@ 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

@@ -37,19 +37,72 @@
* deprecated. (The same is still needed for --merge.)
*/
typedef enum {
/* Merge:
* If merge_snapshot is also set:
* merge thin snapshot LV into its origin
* merge old snapshot COW into its origin
* or if merge_mirror is also set
* merge LV previously split from mirror back into mirror
*/
CONV_MERGE = 1,
/* Split:
* For a snapshot, split it apart into COW and origin for future recombination
* For a cached LV, split it apart into the cached LV and its pool
* For a mirrored or raid LV, split mirror into two mirrors, optionally tracking
* future changes to the main mirror to allow future recombination.
*/
CONV_SPLIT = 2,
CONV_SPLIT_SNAPSHOT = 3,
CONV_SPLIT_CACHE = 4,
CONV_SPLIT_MIRRORS = 5,
/* Start to cache an LV */
CONV_CACHE = 6,
/* Destroy the cache attached to a cached LV */
CONV_UNCACHE = 7,
/* Reconstruct a snapshot from its origin and COW */
CONV_SNAPSHOT = 8,
/* Replace devices in a raid LV with alternatives */
CONV_REPLACE = 9,
/* Repair a mirror, raid or thin LV */
CONV_REPAIR = 10,
/* Convert normal LV into one in a thin pool */
CONV_THIN = 11,
/* Every other segment type or mirror log conversion we haven't separated out */
CONV_OTHER = 12,
} conversion_type_t;
struct lvconvert_params {
/* Exactly one of these 12 command categories is determined */
int merge; /* Either merge_snapshot or merge_mirror is also set */
int cache;
int keep_mimages; /* --splitmirrors */
int repair;
int replace;
int snapshot;
int split;
int splitcache;
int splitsnapshot;
int thin;
int uncache;
int merge; /* 1 */
int split; /* 2 */
int splitsnapshot; /* 3 */
int splitcache; /* 4 */
int keep_mimages; /* 5 */ /* --splitmirrors */
int cache; /* 6 */
int uncache; /* 7 */
int snapshot; /* 8 */
int replace; /* 9 */
int repair; /* 10 */
int thin; /* 11 */
/* other */ /* 12 */
/* FIXME Eliminate all cases where more than one of the above are set then use conv_type instead */
conversion_type_t conv_type;
int merge_snapshot; /* CONV_MERGE is set */
int merge_mirror; /* CONV_MERGE is set */
int track_changes; /* CONV_SPLIT_MIRRORS is set */
int corelog; /* Equivalent to --mirrorlog core */
int mirrorlog; /* Only one of corelog and mirrorlog may be set */
@@ -59,11 +112,6 @@ struct lvconvert_params {
const struct segment_type *segtype; /* Holds what segment type you will get */
int merge_snapshot; /* merge is also set */
int merge_mirror; /* merge is also set */
int track_changes; /* keep_mimages is also set (--splitmirrors) */
int poolmetadataspare;
int force;
int yes;
@@ -124,6 +172,15 @@ struct convert_poll_id_list {
unsigned is_merging_origin_thin:1;
};
/* FIXME Temporary function until the enum replaces the separate variables */
static void _set_conv_type(struct lvconvert_params *lp, int conv_type)
{
if (lp->conv_type != CONV_OTHER)
log_error(INTERNAL_ERROR "Changing conv_type from %d to %d.", lp->conv_type, conv_type);
lp->conv_type = conv_type;
}
static int _lvconvert_validate_names(struct lvconvert_params *lp)
{
unsigned i, j;
@@ -472,23 +529,18 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
-1))
return_0;
lp->merge = 1;
}
/* If --repair, check for incompatible args. */
if (arg_is_set(cmd, repair_ARG)) {
_set_conv_type(lp, CONV_MERGE);
} else if (arg_is_set(cmd, repair_ARG)) {
if (arg_outside_list_is_set(cmd, "cannot be used with --repair",
repair_ARG,
alloc_ARG, usepolicies_ARG,
background_ARG, interval_ARG,
force_ARG, noudevsync_ARG, test_ARG,
-1))
return_0;
lp->repair = 1;
}
if (arg_is_set(cmd, replace_ARG))
lp->replace = 1;
if (arg_is_set(cmd, split_ARG)) {
_set_conv_type(lp, CONV_REPAIR);
} else if (arg_is_set(cmd, split_ARG)) {
if (arg_outside_list_is_set(cmd, "cannot be used with --split",
split_ARG,
name_ARG,
@@ -496,40 +548,40 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
-1))
return_0;
lp->split = 1;
}
if (arg_is_set(cmd, splitcache_ARG)) {
_set_conv_type(lp, CONV_SPLIT);
} else if (arg_is_set(cmd, splitcache_ARG)) {
if (arg_outside_list_is_set(cmd, "cannot be used with --splitcache",
splitcache_ARG,
force_ARG, noudevsync_ARG, test_ARG,
-1))
return_0;
lp->splitcache = 1;
}
if (arg_is_set(cmd, splitsnapshot_ARG)) {
_set_conv_type(lp, CONV_SPLIT_CACHE);
} else if (arg_is_set(cmd, splitsnapshot_ARG)) {
if (arg_outside_list_is_set(cmd, "cannot be used with --splitsnapshot",
splitsnapshot_ARG,
force_ARG, noudevsync_ARG, test_ARG,
-1))
return_0;
lp->splitsnapshot = 1;
}
if (arg_is_set(cmd, trackchanges_ARG))
lp->track_changes = 1;
if (arg_is_set(cmd, uncache_ARG)) {
_set_conv_type(lp, CONV_SPLIT_SNAPSHOT);
} else if (arg_is_set(cmd, uncache_ARG)) {
if (arg_outside_list_is_set(cmd, "cannot be used with --uncache",
uncache_ARG,
force_ARG, noudevsync_ARG, test_ARG,
-1))
return_0;
lp->uncache = 1;
_set_conv_type(lp, CONV_UNCACHE);
} else if (arg_is_set(cmd, replace_ARG)) {
lp->replace = 1;
_set_conv_type(lp, CONV_REPLACE);
}
if (arg_is_set(cmd, cache_ARG))
if (arg_is_set(cmd, cache_ARG)) {
lp->cache = 1;
_set_conv_type(lp, CONV_CACHE);
}
if (!strcmp(lp->type_str, SEG_TYPE_NAME_CACHE))
lp->cache = 1;
@@ -541,8 +593,10 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
lp->type_str = SEG_TYPE_NAME_CACHE;
}
if (arg_is_set(cmd, thin_ARG))
if (arg_is_set(cmd, thin_ARG)) {
lp->thin = 1;
_set_conv_type(lp, CONV_THIN);
}
if (!strcmp(lp->type_str, SEG_TYPE_NAME_THIN))
lp->thin = 1;
@@ -554,6 +608,9 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
lp->type_str = SEG_TYPE_NAME_THIN;
}
if (arg_is_set(cmd, trackchanges_ARG))
lp->track_changes = 1;
if (!_read_pool_params(cmd, &argc, &argv, lp))
return_0;
@@ -563,6 +620,7 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
return 0;
}
lp->snapshot = 1;
_set_conv_type(lp, CONV_SNAPSHOT);
}
if (lp->split) {
@@ -588,6 +646,7 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
lp->lv_split_name = arg_str_value(cmd, name_ARG, NULL);
lp->keep_mimages = 1;
_set_conv_type(lp, CONV_SPLIT_MIRRORS);
lp->mirrors = arg_uint_value(cmd, splitmirrors_ARG, 0);
lp->mirrors_sign = SIGN_MINUS;
} else {
@@ -642,6 +701,7 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
return 0;
}
/*
* Final checking of each case:
* lp->merge
@@ -658,23 +718,18 @@ 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 */
;
else if (lp->splitsnapshot) /* Destroy snapshot retaining cow as separate LV */
;
else if (lp->splitcache)
;
else if (lp->split)
;
else if (lp->uncache)
;
else if (lp->cache)
;
else if (lp->thin)
;
else if (lp->keep_mimages) /* --splitmirrors */
;
else if (lp->snapshot) { /* Snapshot creation from pre-existing cow */
switch(lp->conv_type) {
case CONV_MERGE: /* Snapshot or mirror merge */
case CONV_SPLIT:
case CONV_SPLIT_CACHE:
case CONV_SPLIT_MIRRORS:
case CONV_SPLIT_SNAPSHOT: /* Destroy snapshot retaining cow as separate LV */
case CONV_CACHE:
case CONV_UNCACHE:
case CONV_THIN:
case CONV_REPAIR:
break;
case CONV_SNAPSHOT: /* Snapshot creation from pre-existing cow */
if (!argc) {
log_error("Please provide logical volume path for snapshot origin.");
return 0;
@@ -708,8 +763,9 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
log_verbose("Setting chunk size to %s.", display_size(cmd, lp->chunk_size));
lp->type_str = SEG_TYPE_NAME_SNAPSHOT;
break;
} else if (lp->replace) { /* RAID device replacement */
case CONV_REPLACE: /* RAID device replacement */
lp->replace_pv_count = arg_count(cmd, replace_ARG);
lp->replace_pvs = dm_pool_alloc(cmd->mem, sizeof(char *) * lp->replace_pv_count);
if (!lp->replace_pvs)
@@ -729,72 +785,73 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
tmp_str)))
return_0;
}
} else if (lp->repair)
;
else if (_mirror_or_raid_type_requested(cmd, lp->type_str) ||
lp->mirrorlog || lp->corelog) { /* Mirrors (and some RAID functions) */
if (arg_is_set(cmd, chunksize_ARG)) {
log_error("--chunksize is only available with snapshots or pools.");
return 0;
}
break;
if (arg_is_set(cmd, zero_ARG)) {
log_error("--zero is only available with snapshots or thin pools.");
return 0;
}
/*
* --regionsize is only valid if converting an LV into a mirror.
* Checked when we know the state of the LV being converted.
*/
if (arg_is_set(cmd, regionsize_ARG)) {
if (arg_sign_value(cmd, regionsize_ARG, SIGN_NONE) ==
SIGN_MINUS) {
log_error("Negative regionsize is invalid.");
case CONV_OTHER:
if (_mirror_or_raid_type_requested(cmd, lp->type_str) ||
lp->mirrorlog || lp->corelog) { /* Mirrors (and some RAID functions) */
if (arg_is_set(cmd, chunksize_ARG)) {
log_error("--chunksize is only available with snapshots or pools.");
return 0;
}
lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0);
} else {
region_size = get_default_region_size(cmd);
if (region_size < 0) {
log_error("Negative regionsize in "
"configuration file is invalid.");
if (arg_is_set(cmd, zero_ARG)) {
log_error("--zero is only available with snapshots or thin pools.");
return 0;
}
lp->region_size = region_size;
}
if (lp->region_size % (pagesize >> SECTOR_SHIFT)) {
log_error("Region size (%" PRIu32 ") must be "
"a multiple of machine memory "
"page size (%d).",
lp->region_size, pagesize >> SECTOR_SHIFT);
return 0;
}
/*
* --regionsize is only valid if converting an LV into a mirror.
* Checked when we know the state of the LV being converted.
*/
if (arg_is_set(cmd, regionsize_ARG)) {
if (arg_sign_value(cmd, regionsize_ARG, SIGN_NONE) ==
SIGN_MINUS) {
log_error("Negative regionsize is invalid.");
return 0;
}
lp->region_size = arg_uint_value(cmd, regionsize_ARG, 0);
} else {
region_size = get_default_region_size(cmd);
if (region_size < 0) {
log_error("Negative regionsize in "
"configuration file is invalid.");
return 0;
}
lp->region_size = region_size;
}
if (!is_power_of_2(lp->region_size)) {
log_error("Region size (%" PRIu32
") must be a power of 2.", lp->region_size);
return 0;
}
if (lp->region_size % (pagesize >> SECTOR_SHIFT)) {
log_error("Region size (%" PRIu32 ") must be "
"a multiple of machine memory "
"page size (%d).",
lp->region_size, pagesize >> SECTOR_SHIFT);
return 0;
}
if (!lp->region_size) {
log_error("Non-zero region size must be supplied.");
return 0;
}
if (!is_power_of_2(lp->region_size)) {
log_error("Region size (%" PRIu32
") must be a power of 2.", lp->region_size);
return 0;
}
/* FIXME man page says in one place that --type and --mirrors can't be mixed */
if (lp->mirrors_supplied && !lp->mirrors)
/* down-converting to linear/stripe? */
lp->type_str = SEG_TYPE_NAME_STRIPED;
if (!lp->region_size) {
log_error("Non-zero region size must be supplied.");
return 0;
}
} else if (_raid0_type_requested(lp->type_str) || _striped_type_requested(lp->type_str)) { /* striped or linear or raid0 */
if (arg_from_list_is_set(cmd, "cannot be used with --type raid0 or --type striped or --type linear",
chunksize_ARG, corelog_ARG, mirrors_ARG, mirrorlog_ARG, regionsize_ARG, zero_ARG,
-1))
return_0;
/* FIXME man page says in one place that --type and --mirrors can't be mixed */
if (lp->mirrors_supplied && !lp->mirrors)
/* down-converting to linear/stripe? */
lp->type_str = SEG_TYPE_NAME_STRIPED;
} /* else segtype will default to current type */
} else if (_raid0_type_requested(lp->type_str) || _striped_type_requested(lp->type_str)) { /* striped or linear or raid0 */
if (arg_from_list_is_set(cmd, "cannot be used with --type raid0 or --type striped or --type linear",
chunksize_ARG, corelog_ARG, mirrors_ARG, mirrorlog_ARG, regionsize_ARG, zero_ARG,
-1))
return_0;
} /* else segtype will default to current type */
}
lp->force = arg_count(cmd, force_ARG);
lp->yes = arg_count(cmd, yes_ARG);
@@ -1828,6 +1885,25 @@ static void _lvconvert_raid_repair_ask(struct cmd_context *cmd,
}
}
/* Check for dm-raid target supporting raid4 conversion properly. */
static int _raid4_conversion_supported(struct logical_volume *lv, struct lvconvert_params *lp)
{
int ret = 1;
struct lv_segment *seg = first_seg(lv);
if (seg_is_raid4(seg))
ret = raid4_is_supported(lv->vg->cmd, seg->segtype);
else if (segtype_is_raid4(lp->segtype))
ret = raid4_is_supported(lv->vg->cmd, lp->segtype);
if (ret)
return 1;
log_error("Cannot convert %s LV %s to %s.",
lvseg_name(seg), display_lvname(lv), lp->segtype->name);
return 0;
}
static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *lp)
{
int replace = 0, image_count = 0;
@@ -1944,13 +2020,24 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
if ((seg_is_linear(seg) || seg_is_striped(seg) || seg_is_mirrored(seg) || lv_is_raid(lv)) &&
(lp->type_str && lp->type_str[0])) {
/* Activation is required later which precludes existing unsupported raid0 segment */
if (segtype_is_any_raid0(lp->segtype) &&
/* Activation is required later which precludes existing supported raid0 segment */
if ((seg_is_any_raid0(seg) || segtype_is_any_raid0(lp->segtype)) &&
!(lp->target_attr & RAID_FEATURE_RAID0)) {
log_error("RAID module does not support RAID0.");
return 0;
}
/* Activation is required later which precludes existing supported raid4 segment */
if (!_raid4_conversion_supported(lv, lp))
return 0;
/* Activation is required later which precludes existing supported raid10 segment */
if ((seg_is_raid10(seg) || segtype_is_raid10(lp->segtype)) &&
!(lp->target_attr & RAID_FEATURE_RAID10)) {
log_error("RAID module does not support RAID10.");
return 0;
}
if (!arg_is_set(cmd, stripes_long_ARG))
lp->stripes = 0;
@@ -1964,7 +2051,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
}
if (lp->replace)
return lv_raid_replace(lv, lp->replace_pvh, lp->pvh);
return lv_raid_replace(lv, lp->force, lp->replace_pvh, lp->pvh);
if (lp->repair) {
if (!lv_is_active_exclusive_locally(lv_lock_holder(lv))) {
@@ -1987,7 +2074,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
if (!(failed_pvs = _failed_pv_list(lv->vg)))
return_0;
if (!lv_raid_replace(lv, failed_pvs, lp->pvh)) {
if (!lv_raid_replace(lv, lp->force, failed_pvs, lp->pvh)) {
log_error("Failed to replace faulty devices in %s.",
display_lvname(lv));
return 0;
@@ -2008,6 +2095,9 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l
try_new_takeover_or_reshape:
if (!_raid4_conversion_supported(lv, lp))
return 0;
/* FIXME This needs changing globally. */
if (!arg_is_set(cmd, stripes_long_ARG))
lp->stripes = 0;
@@ -4660,6 +4750,7 @@ int lvconvert(struct cmd_context * cmd, int argc, char **argv)
int poll_ret, ret;
struct convert_poll_id_list *idl;
struct lvconvert_params lp = {
.conv_type = CONV_OTHER,
.target_attr = ~0,
.idls = DM_LIST_HEAD_INIT(lp.idls),
};

View File

@@ -1054,6 +1054,12 @@ static int _lvcreate_params(struct cmd_context *cmd,
return 0;
}
if (segtype_is_raid4(lp->segtype) &&
!(lp->target_attr & RAID_FEATURE_RAID4)) {
log_error("RAID module does not support RAID4.");
return 0;
}
if (segtype_is_raid10(lp->segtype) && !(lp->target_attr & RAID_FEATURE_RAID10)) {
log_error("RAID module does not support RAID10.");
return 0;

View File

@@ -45,9 +45,9 @@ static char *_list_cmds(const char *text, int state)
len = strlen(text);
}
while (i < _cmdline->num_command_names)
if (!strncmp(text, _cmdline->command_names[i++].name, len))
return strdup(_cmdline->command_names[i - 1].name);
while (i < _cmdline->num_commands)
if (!strncmp(text, _cmdline->commands[i++].name, len))
return strdup(_cmdline->commands[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_name *cname;
static struct command *com;
/* 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;
cname = NULL;
com = NULL;
len = strlen(text);
/* Find start of first word in line buffer */
while (isspace(*s))
s++;
/* Look for word in list of command names */
for (j = 0; j < _cmdline->num_command_names; j++) {
/* Look for word in list of commands */
for (j = 0; j < _cmdline->num_commands; j++) {
const char *p;
char *q = s;
p = _cmdline->command_names[j].name;
p = _cmdline->commands[j].name;
while (*p == *q) {
p++;
q++;
}
if ((!*p) && *q == ' ') {
cname = _cmdline->command_names + j;
com = _cmdline->commands + j;
break;
}
}
}
if (!cname)
if (!com)
return NULL;
/* Short form arguments */
if (len < 3) {
while (match_no < cname->num_args) {
while (match_no < com->num_args) {
char s[3];
char c;
if (!(c = (_cmdline->arg_props +
cname->valid_args[match_no++])->short_arg))
com->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 < cname->num_args)
match_no = cname->num_args;
if (match_no < com->num_args)
match_no = com->num_args;
while (match_no - cname->num_args < cname->num_args) {
while (match_no - com->num_args < com->num_args) {
const char *l;
l = (_cmdline->arg_props +
cname->valid_args[match_no++ - cname->num_args])->long_arg;
com->valid_args[match_no++ - com->num_args])->long_arg;
if (*(l + 2) && !strncmp(text, l, len))
return strdup(l);
}

View File

@@ -19,11 +19,10 @@
struct cmd_context;
struct cmdline_context {
struct arg_props *arg_props;
struct command *commands;
int num_commands;
struct command_name *command_names;
int num_command_names;
struct arg_props *arg_props;
struct command *commands;
int num_commands;
int commands_size;
};
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

@@ -194,6 +194,9 @@ static int _pvscan_autoactivate_single(struct cmd_context *cmd, const char *vg_n
if (vg_is_clustered(vg))
return ECMD_PROCESSED;
if (vg_is_exported(vg))
return ECMD_PROCESSED;
if (is_lockd_type(vg->lock_type))
return ECMD_PROCESSED;

View File

@@ -801,7 +801,10 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd,
return 0;
}
if (arg_is_set(cmd, vgmetadatacopies_ARG))
if (arg_is_set(cmd, metadatacopies_ARG))
vp_new->vgmetadatacopies = arg_int_value(cmd, metadatacopies_ARG,
DEFAULT_VGMETADATACOPIES);
else if (arg_is_set(cmd, vgmetadatacopies_ARG))
vp_new->vgmetadatacopies = arg_int_value(cmd, vgmetadatacopies_ARG,
DEFAULT_VGMETADATACOPIES);
else
@@ -2347,12 +2350,8 @@ 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;
uint32_t lv_types;
struct logical_volume *lv;
struct lv_segment *seg;
log_set_report_object_type(LOG_REPORT_OBJECT_TYPE_LV);
@@ -2361,7 +2360,6 @@ 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;
@@ -2455,7 +2453,6 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
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;
}
@@ -2503,68 +2500,6 @@ 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);
@@ -4001,6 +3936,11 @@ int pvcreate_params_from_args(struct cmd_context *cmd, struct pvcreate_params *p
if (pp->pva.pvmetadatacopies < 0)
pp->pva.pvmetadatacopies = find_config_tree_int(cmd, metadata_pvmetadatacopies_CFG, NULL);
if (pp->pva.pvmetadatacopies > 2) {
log_error("Metadatacopies may only be 0, 1 or 2");
return 0;
}
pp->pva.ba_size = arg_uint64_value(cmd, bootloaderareasize_ARG, pp->pva.ba_size);
return 1;

View File

@@ -50,27 +50,20 @@
#define CMD_LEN 256
#define MAX_ARGS 64
/* define the enums for the values accepted by command line --options */
enum {
#define val(a, b, c, d) a ,
#include "vals.h"
#undef val
};
/* command functions */
typedef int (*command_fn) (struct cmd_context * cmd, int argc, char **argv);
/* define the enums for the command line --options */
#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 */
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 */
@@ -86,13 +79,13 @@ struct arg_values {
/* void *ptr; // Currently not used. */
};
/* a global table of possible --option's */
/* a global table of possible arguments */
struct arg_props {
int arg_enum; /* foo_ARG from args.h */
const char short_arg;
char _padding[7];
const char *long_arg;
int val_enum; /* foo_VAL from vals.h */
int (*fn) (struct cmd_context *cmd, struct arg_values *av);
uint32_t flags;
uint32_t prio;
};
@@ -103,14 +96,6 @@ 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. */
@@ -133,6 +118,19 @@ struct val_props {
#define ENABLE_DUPLICATE_DEVS 0x00000400
/* Command does not accept tags as args. */
#define DISALLOW_TAG_ARGS 0x00000800
/* 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);
@@ -159,8 +157,6 @@ int segtype_arg(struct cmd_context *cmd, struct arg_values *av);
int alloc_arg(struct cmd_context *cmd, struct arg_values *av);
int locktype_arg(struct cmd_context *cmd, struct arg_values *av);
int readahead_arg(struct cmd_context *cmd, struct arg_values *av);
int vgmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
int pvmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
int metadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av);
/* we use the enums to access the switches */

View File

@@ -1,137 +0,0 @@
/*
* 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(vgmetadatacopies_VAL, vgmetadatacopies_arg, "MetadataCopiesVG", "all|unmanaged|Number")
val(pvmetadatacopies_VAL, pvmetadatacopies_arg, "MetadataCopiesPV", "0|1|2")
val(metadatacopies_VAL, metadatacopies_arg, "unused", "unused")
/* 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
*/

View File

@@ -482,9 +482,6 @@ static int _vgchange_metadata_copies(struct cmd_context *cmd,
{
uint32_t mda_copies = arg_uint_value(cmd, vgmetadatacopies_ARG, DEFAULT_VGMETADATACOPIES);
log_warn("vgchange_metadata_copies new %u vg_mda_copies %u D %u",
mda_copies, vg_mda_copies(vg), DEFAULT_VGMETADATACOPIES);
if (mda_copies == vg_mda_copies(vg)) {
if (vg_mda_copies(vg) == VGMETADATACOPIES_UNMANAGED)
log_warn("Number of metadata copies for VG %s is already unmanaged.",

View File

@@ -157,12 +157,24 @@ int vgconvert(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
if (arg_is_set(cmd, metadatacopies_ARG)) {
log_error("Invalid option --metadatacopies, "
"use --pvmetadatacopies instead.");
return EINVALID_CMD_LINE;
}
if (!(cmd->fmt->features & FMT_MDAS) &&
arg_is_set(cmd, pvmetadatacopies_ARG)) {
(arg_is_set(cmd, pvmetadatacopies_ARG) ||
arg_is_set(cmd, metadatasize_ARG))) {
log_error("Metadata parameters only apply to text format");
return EINVALID_CMD_LINE;
}
if (arg_is_set(cmd, pvmetadatacopies_ARG) &&
arg_int_value(cmd, pvmetadatacopies_ARG, -1) > 2) {
log_error("Metadatacopies may only be 0, 1 or 2");
return EINVALID_CMD_LINE;
}
if (!(cmd->fmt->features & FMT_BAS) &&
arg_is_set(cmd, bootloaderareasize_ARG)) {
log_error("Bootloader area parameters only apply to text format");

View File

@@ -136,6 +136,12 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
if (arg_is_set(cmd, metadatacopies_ARG)) {
log_error("Invalid option --metadatacopies, "
"use --pvmetadatacopies instead.");
return EINVALID_CMD_LINE;
}
vg_name = skip_dev_dir(cmd, argv[0], NULL);
argc--;
argv++;