1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-11-20 20:24:02 +03:00

Compare commits

..

57 Commits

Author SHA1 Message Date
Zdenek Kabelac
ec19a5905c make: generate 2025-11-20 16:50:44 +01:00
Zdenek Kabelac
12ce9ac97c revert "debug dmevent"
Unwanted.
2025-11-20 16:50:13 +01:00
Zdenek Kabelac
6b04f24f41 debug dmevent 2025-11-20 16:05:10 +01:00
Zdenek Kabelac
9c3f376000 test: umounting by dmeventd
Correct and simplify test.
Use LVM_BINARY for path to lvm binary used by script.
2025-11-20 16:05:10 +01:00
Zdenek Kabelac
e0a8648828 test: aux updates
Ssend eval stderr to null as there is no need for extra trace
of eval values in teardown.

Drop passing args to lvmpoll_dump.
2025-11-20 16:04:50 +01:00
Zdenek Kabelac
d9da68b9b2 test: show lvmlockd debug info in testing 2025-11-20 11:07:31 +01:00
Zdenek Kabelac
921d1fa339 lvmlockd: reduce require of two SIGTERM signals in shutdown
When lvmlockd received SIGTERM, for_each_lockspace() would signal
lockspace threads to stop and then immediately check if they were
done. Due to scheduling, threads often hadn't finished yet, causing
for_each_lockspace() to return a non-zero count, which reset
daemon_quit to 0. This required a second SIGTERM to actually exit,
adding delays to daemon shutdown in tests.

Two issues were fixed:

1. Fixed mutex synchronization for thread_done flag:
   The lockspace thread was setting ls->thread_done while holding
   only lockspaces_mutex, but for_each_lockspace() was reading it
   while holding only ls->mutex, creating a race condition. Now
   thread_done is set while holding both mutexes in the correct
   order (lockspaces_mutex first, then ls->mutex).

2. Added wait loop during daemon shutdown:
   When daemon_quit is set and threads are signaled to stop,
   for_each_lockspace() now waits up to 100ms (checking every 1ms)
   for threads to actually finish before checking their status.
   This wait only activates during daemon shutdown to avoid adding
   delays to normal lockspace operations.

In practice, threads finish in 1-2ms, so shutdown completes quickly
with a single SIGTERM.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 11:07:31 +01:00
David Teigland
13e56a6b6c deviced_ids: extended refresh period
If an automatic device ID refresh is triggered, and does not find
some device IDs, then extend the refresh behavior for a number of
seconds, configured in lvm.conf:

device_ids_refresh=<seconds>  accepts 10-600 seconds

Previous settings remain the same:

device_ids_refresh=0  disables automatic refresh
device_ids_refresh=1  enables one refresh

While the refresh period is extended, a new line appears in
system.devices: REFRESH_UNTIL=<YYYYMMDDHHMMSS>

The timestamp is written by the first lvm command to trigger the
refresh, and is set to current time + device_ids_refresh seconds.
REFRESH_UNTIL is removed when all devices are found, or when the
time expires.
2025-11-19 15:46:22 -06:00
Zdenek Kabelac
0a896f1ca1 test: tune slowdown
Here we have some tricky case - ATM we are using suspend with
flushing when changing DM tables for cache volume - but this
can take too much time with our delayed device.
So trying to minimize chance to hit this race on very fast machines.
2025-11-19 19:03:21 +01:00
Zdenek Kabelac
2d1b88a7c2 test: improve lvmpolld_talk error messages
Refactor lvmpolld_talk() to provide clearer diagnostics when connection
fails. Previously misreported socket failures as "nc not available".
Now distinguishes between missing tools, missing socket, and connection
errors with actual error details.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 19:03:21 +01:00
Zdenek Kabelac
4be1c8b0e3 test: enhance _check_size
Grab lv_size as the first thing.
Make tests easier and drop '_not' variants.
2025-11-19 19:03:21 +01:00
Zdenek Kabelac
44c0eb935b cache: add debug message 2025-11-19 19:02:58 +01:00
Zdenek Kabelac
60aae15eb3 libdaemon: log which signal triggered daemon shutdown
Capture and log the signal number that triggers daemon shutdown.
This helps diagnose unexpected daemon terminations during testing.
2025-11-18 23:47:30 +01:00
Zdenek Kabelac
aef860fa69 test: add more debug for abort case
Improve logging to better capture lvconvert problem.
2025-11-18 12:07:30 +01:00
Zdenek Kabelac
933d8944aa dmeventd: drop unused var
fdd no longer needed.
2025-11-18 12:07:30 +01:00
Zdenek Kabelac
b2bc16591a signals: rename interruptible_usleep to sigint_usleep
The interruptible_usleep() function returned 1 on interruption (error)
and 0 on success, opposite to LVM2 convention where 1=success, 0=failure.

Changes:
- Rename to sigint_usleep() to align with sigint_*() function family
- Invert return: 1 if sleep completed, 0 if interrupted
- Update all call sites to use ! operator for error checking

This makes the API more intuitive as ! clearly indicates error path
and return values match standard LVM2 conventions.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 12:07:30 +01:00
Peter Rajnoha
e8109843e0 WHATS_NEW 2025-11-18 09:59:02 +01:00
Peter Rajnoha
dceab4902a make: generate 2025-11-18 09:54:24 +01:00
Peter Rajnoha
f200096eb3 lvmconfig: make it possible to print various config types in list mode
For example:

❯  lvmconfig --type diff
report {
	compact_output=1
	headings=2
}
activation {
	polling_interval=1
}

❯  lvmconfig --type diff --list
report/compact_output=1
report/headings=2
activation/polling_interval=1
2025-11-18 09:52:22 +01:00
Peter Rajnoha
154a42bdae config: add support for list mode for all cfg_def_tree_t types
Before, we printed only CFG_DEF_TREE_LIST as a list instead of
structured tree. But we can also print all the other types as lists
if needed which might be more suitable.

This patch adds a 'listmode' switch to struct config_def_tree_spec
so that the config printing functions (_out_prefix_fn, _out_line_fn,
_out_suffix_fn) can then decide on the actual format.
2025-11-18 09:46:34 +01:00
Zdenek Kabelac
c7a45237aa test: use 4k blocks for fs 2025-11-17 19:15:43 +01:00
Zdenek Kabelac
2c5f135482 test: correcting wait shell vars 2025-11-17 19:15:43 +01:00
Zdenek Kabelac
dd03db75ac test: just skip test if there are suspended devices 2025-11-17 17:34:48 +01:00
Zdenek Kabelac
c8960be7d3 test: use should for a while 2025-11-17 16:17:38 +01:00
Zdenek Kabelac
2660e92c06 test: aux type
Removed extra '/'.
2025-11-17 14:46:56 +01:00
Zdenek Kabelac
492a5a070f test: missed removal of clvmd testing 2025-11-17 14:46:56 +01:00
Zdenek Kabelac
a3cd838e5c dmfilemap: stray close code reuse
Reuse header file from libdaemon directory here.
It has better code to close stray descriptors - since there
are systems with very high numbers of supported opened descriptors.

In case project would ever split header file would need to be copied.

Also use >=  check for valid file descriptor.
2025-11-17 14:44:48 +01:00
Zdenek Kabelac
332fa080de WHATS_NEW: update 2025-11-17 13:55:27 +01:00
Zdenek Kabelac
a3072d7241 test: aux rename wait variable 2025-11-17 13:53:25 +01:00
Zdenek Kabelac
81892cb4ef test: rework bare wait commands
Replace bare 'wait' commands with specific PID waiting to prevent
test hangs when base shell runs process in the background.

When tests use 'wait' without arguments, it waits for ALL background
processes. This may causes tests to hang indefinitely.
Fix by capturing background job PIDs and waiting
only for those specific processes.

Pattern changed from:
  some_command &
  wait

To:
  some_command &
  SOME_PID=$!
  wait "$SOME_PID" || true

The '|| true' handles cases where the process has already exited.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 13:53:25 +01:00
Zdenek Kabelac
bbc14aafa8 test: aux kill_sleep_kill 2025-11-17 13:53:25 +01:00
Zdenek Kabelac
52cc897902 test: remove clvmd testing infrastructure
Remove all clvmd-related test code since clvmd was removed from lvm2.
This includes prepare_clvmd(), SKIP_WITH/WITHOUT_CLVMD variables,
LOCAL_CLVMD conditional blocks, and outdated comments. Tests now run
unconditionally with non-cluster behavior.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 13:53:25 +01:00
Zdenek Kabelac
b2ed0609bc test: simplify corrupt_dev() function
Replace strings+grep with grep -oba for byte pattern search. This is
more direct and efficient - grep finds the byte offset, we extract it
with cut, and use dd to overwrite at that position. Also add
conv=notrunc to prevent truncation.
2025-11-17 13:53:25 +01:00
Zdenek Kabelac
018c4c1ace test: aux easier code for building config
For older bash use more simple code.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 13:53:15 +01:00
Zdenek Kabelac
648b86a09f daemonize: fix file descriptor leaks on error paths
Fix resource leaks in daemonization code across multiple daemons by
properly closing /dev/null file descriptor on all error paths.

Changes across all daemonizing code:
- Skip dup2() when fd already equals target (no-op optimization)
- Close fd on error paths before exit (prevents leak)
- Add Coverity annotations on both error and success paths
- Use consistent == -1 pattern for dup2() error checks
- Remove explicit close(0/1/2) in cmirrord (dup2 handles atomically)

This eliminates resource leak warnings from static analyzers while
maintaining correct daemonization behavior.
2025-11-17 13:52:34 +01:00
Zdenek Kabelac
49e3a16003 lvmpolld: signal child processes before pthread_cancel
Fix lvmpolld shutdown to properly terminate child lvpoll processes
before cancelling monitoring threads.

Previously, pthread_cancel was called on monitoring threads while
their child processes were still running. This could leave orphaned
lvpoll processes and cause shutdown delays.

Now send SIGTERM to child lvpoll processes first, then immediately
cancel the monitoring threads which will reap the children during
their cleanup.

This significantly reduces shutdown time in tests with lvmpolld.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 13:52:34 +01:00
Zdenek Kabelac
ffab693183 libdaemon: improve graceful shutdown of client threads
Optimize daemon shutdown to allow client threads to exit quickly
without blocking on socket operations, and refactor code to improve
maintainability.

Functional improvements:

1. Close listening socket BEFORE waiting for client threads
   - Prevents new connections during shutdown
   - Unlinks socket file earlier in shutdown sequence

2. Shutdown all client sockets with SHUT_RDWR
   - Interrupts blocking read() calls in client threads
   - Allows threads to exit immediately instead of hanging
   - Uses shutdown() to wake blocked threads, not just close()

3. Add early exit check in client thread loop
   - Check _shutdown_requested at start of while loop
   - Allows threads to exit gracefully when shutdown is initiated

Code organization improvements:

4. Eliminate goto statement
   - Replace "goto out" with direct function calls
   - Improves code readability and control flow clarity
   - Both daemon_main and daemon_init paths now follow same pattern

5. Extract _shutdown_sockets() helper function
   - Centralizes all socket shutdown logic in one place
   - Handles both listening socket close and client socket shutdown
   - Respects _systemd_activation flag for socket file unlinking
   - Includes comprehensive logging for shutdown operations

6. Extract _daemon_cleanup() helper function
   - Common cleanup path for both daemon_main and normal execution
   - Handles daemon_fini callback, logging, pidfile removal
   - Eliminates code duplication between execution paths

This allows daemon to shutdown cleanly without client threads
blocking on socket operations, enabling faster test execution and
cleaner shutdown sequences.

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 13:52:34 +01:00
Zdenek Kabelac
3edc6eeb4e cov: missing free
With recent commit f7a308d2e7
we missed to relase allocated idname.
2025-11-17 13:52:04 +01:00
Zdenek Kabelac
704e8f482a dmeventd: fix missing lock when reading _timeout_thread_id
Acquire _timeout_mutex before reading _timeout_thread_id to match
the locking pattern used when writing this variable. While the
variable is only written once and never changed, static analyzers
flag the inconsistent lock usage.

Release mutex before pthread_join() to avoid holding locks during
blocking operations.
2025-11-17 13:25:05 +01:00
Zdenek Kabelac
0ebea8ec6a make: generate 2025-11-14 11:19:15 +01:00
Zdenek Kabelac
7ff5ff5c85 test: we need fs on origin as well
Last commit made fs only on snapshot - but it's needed also on origin.
2025-11-14 11:06:19 +01:00
Zdenek Kabelac
5dbb1854c3 test: bash clenaups
Various improvemetns to make shellcheck less complaining.
2025-11-14 10:18:17 +01:00
Zdenek Kabelac
9dc6d0c948 test: check simplified
We do not need to use 5 second sleep here for checking
opened device cannot be removed - just check with mounted
snapshot - which will also be seen as opened device - but
with known holder - thus 5sec retry loop is avoided.
2025-11-14 10:16:23 +01:00
Zdenek Kabelac
c2b85e2f29 test: require newer target 2025-11-14 10:14:28 +01:00
Zdenek Kabelac
e2cf605037 man: update pvmove for pvmove_max_segment_size_mb 2025-11-14 10:14:28 +01:00
Zdenek Kabelac
2cb0f6598b dmeventd: cleanup
Show help options in alphabetic order.
2025-11-14 10:14:28 +01:00
David Teigland
4b9cd637d6 vgchange: limit persist stop in lockstop
"vgchange --lockstop --persist stop" should skip the
persist_stop() on a VG without PR required, otherwise
it hits errors attempting to stop PR on VGs where it's
not used.
2025-11-13 13:55:08 -06:00
Peter Rajnoha
3fe8dd6254 test: select-report: fix checking of failure scenarios 2025-11-13 09:53:36 +01:00
David Teigland
9cccfe9c69 man: update lvmdevices refresh info 2025-11-12 15:25:53 -06:00
Zdenek Kabelac
4190e73c1b test: fix lots of not usage
Added lots of FIXME - since these tests
are not working properly - but ATM it's unclear
what they are supposed to test.
2025-11-12 13:47:47 +01:00
Zdenek Kabelac
8744c086ee test: fix use of not mimages|mirrorlog.... 2025-11-12 13:47:47 +01:00
Zdenek Kabelac
44db4ebbbd test: fix use of not is_lv_opened_
Correct the test and wait till dmeventd really umounts directory.
2025-11-12 13:47:47 +01:00
Zdenek Kabelac
3d011ab3df test: fix typo group to grep
We actually want to use 'not grep'.
2025-11-12 13:47:47 +01:00
Zdenek Kabelac
0f3cbac7ec test: fix use of not sel
Looks like we need to fix 101%.
2025-11-12 13:47:47 +01:00
Zdenek Kabelac
0d25d18504 test: fix use of not test
Fixing 'not ' and making it more readable.
Handle blkid error code 2.
2025-11-12 13:47:47 +01:00
Zdenek Kabelac
f3424d7edf test: fix use of not fill 2025-11-12 13:47:47 +01:00
Zdenek Kabelac
704ed0cdcd make: generate 2025-11-12 13:47:47 +01:00
94 changed files with 1953 additions and 885 deletions

View File

@@ -1,5 +1,7 @@
Version 2.03.37 -
==================
Support output in list mode for all lvmconfig --typeconfig types with --list.
Enhance shutdown performance of daemons using libdaemon.
Add missing synchronization while converting cachevols.
Warn on classic snapshot on raid creation and error on activation + test.
Translate udev device paths in lvmdbusd for test environments.

View File

@@ -179,10 +179,16 @@ devices {
# If PVs are restored or moved to a new system with new devices, but
# an old system.devices remains with old device IDs, then search for
# the PVIDs on new devices and update the device IDs in system.devices.
# The original device IDs must also not be found on the new system.
# See device_ids_refresh_check for conditions that trigger the refresh.
# Set to 1 to enable a single automatic refresh attempt when a trigger
# condition is detected. Set to 0 to disable automatic refresh.
# Set to a value between 10 and 600 (in seconds) to enable an extended
# refresh period during which missing PVs will be located using the PVID,
# and the system.devices device ID updated if the PV is found on a new device.
# An extended refresh period may be useful if devices require refresh,
# but are attached to the system some time the initial refresh.
# This configuration option has an automatic default value.
# device_ids_refresh = 1
# device_ids_refresh = 10
# Configuration option devices/device_ids_refresh_checks.
# Conditions that trigger device_ids_refresh to locate PVIDs on new devices.

View File

@@ -228,16 +228,15 @@ static void daemonize(void)
umask(0);
if (close(0) || close(1) || close(2)) {
LOG_ERROR("Failed to close terminal FDs");
if (((devnull != STDIN_FILENO) && (dup2(devnull, STDIN_FILENO) == -1)) ||
((devnull != STDOUT_FILENO) && (dup2(devnull, STDOUT_FILENO) == -1)) ||
((devnull != STDERR_FILENO) && (dup2(devnull, STDERR_FILENO) == -1))) {
if (devnull > STDERR_FILENO)
(void) close(devnull);
/* coverity[leaked_handle] devnull is stdin/stdout/stderr */
exit(EXIT_FAILURE);
}
if ((dup2(devnull, 0) < 0) || /* reopen stdin */
(dup2(devnull, 1) < 0) || /* reopen stdout */
(dup2(devnull, 2) < 0)) /* reopen stderr */
exit(EXIT_FAILURE);
if ((devnull > STDERR_FILENO) && close(devnull)) {
LOG_ERROR("Failed to close descriptor %d: %s",
devnull, strerror(errno));
@@ -245,7 +244,7 @@ static void daemonize(void)
}
LOG_OPEN("cmirrord", LOG_PID, LOG_DAEMON);
/* coverity[leaked_handle] devnull cannot leak here */
/* coverity[leaked_handle] devnull is stdin/stdout/stderr */
}
/*

View File

@@ -2478,17 +2478,21 @@ static void _daemonize(void)
if ((null_fd = open("/dev/null", O_RDWR)) < 0)
exit(EXIT_DESC_OPEN_FAILURE);
if ((dup2(null_fd, STDIN_FILENO) == -1) ||
(dup2(null_fd, STDOUT_FILENO) == -1) ||
(dup2(null_fd, STDERR_FILENO) == -1))
if (((null_fd != STDIN_FILENO) && (dup2(null_fd, STDIN_FILENO) == -1)) ||
((null_fd != STDOUT_FILENO) && (dup2(null_fd, STDOUT_FILENO) == -1)) ||
((null_fd != STDERR_FILENO) && (dup2(null_fd, STDERR_FILENO) == -1))) {
if (null_fd > STDERR_FILENO)
(void) close(null_fd);
/* coverity[leaked_handle] null_fd is stdin/stdout/stderr */
exit(EXIT_DESC_OPEN_FAILURE);
}
if ((null_fd > STDERR_FILENO) && close(null_fd))
exit(EXIT_DESC_CLOSE_FAILURE);
setsid();
/* coverity[leaked_handle] 'null_fd' handle is not leaking */
/* coverity[leaked_handle] 'null_fd' is stdin/stdout/stderr */
}
static int _reinstate_registrations(struct dm_event_fifos *fifos)
@@ -2725,11 +2729,11 @@ bad:
static void _usage(char *prog, FILE *file)
{
fprintf(file, "Usage:\n"
"%s [-d [-d [-d]]] [-e path] [-g seconds] [-f] [-h] [i] [-l] [-R] [-V] [-?]\n\n"
"%s [-d [-d [-d]]] [-e path] [-f] [-g seconds] [-h] [i] [-l] [-R] [-V] [-?]\n\n"
" -d Log debug messages to syslog (-d, -dd, -ddd)\n"
" -e Select a file path checked on exit\n"
" -g Grace period for thread cleanup (0-300 seconds, default: %d)\n"
" -f Don't fork, run in the foreground\n"
" -g Grace period for thread cleanup (0-300 seconds, default: %d)\n"
" -h Show this help information\n"
" -i Query running instance of dmeventd for info\n"
" -l Log to stdout,stderr instead of syslog\n"
@@ -2758,17 +2762,8 @@ int main(int argc, char *argv[])
optarg = (char*) "";
while ((opt = getopt(argc, argv, ":?e:g:fhiVdlR")) != EOF) {
switch (opt) {
case 'h':
_usage(argv[0], stdout);
return EXIT_SUCCESS;
case '?':
_usage(argv[0], stderr);
return EXIT_SUCCESS;
case 'i':
info++;
break;
case 'R':
restart++;
case 'd':
debug_level++;
break;
case 'e':
if (strchr(optarg, '"')) {
@@ -2777,6 +2772,9 @@ int main(int argc, char *argv[])
}
_exit_on=optarg;
break;
case 'f':
_foreground++;
break;
case 'g':
_grace_period = atoi(optarg);
if (_grace_period < 0 || _grace_period > 300) {
@@ -2784,15 +2782,22 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
break;
case 'f':
_foreground++;
break;
case 'd':
debug_level++;
case 'h':
_usage(argv[0], stdout);
return EXIT_SUCCESS;
case 'i':
info++;
break;
case 'l':
use_syslog = 0;
break;
case '?':
/* getopt() returns '?' for unknown option */
_usage(argv[0], stderr);
return EXIT_SUCCESS;
case 'R':
restart++;
break;
case 'V':
printf("dmeventd version: %s\n", DM_LIB_VERSION);
return EXIT_SUCCESS;
@@ -2933,12 +2938,15 @@ int main(int argc, char *argv[])
}
/* Terminate timeout thread if it exists */
if (_timeout_thread_id) {
pthread_mutex_lock(&_timeout_mutex);
if (!_timeout_thread_id)
pthread_mutex_unlock(&_timeout_mutex);
else {
pthread_t thread_id = _timeout_thread_id;
_exit_now = DM_EXITING;
pthread_mutex_lock(&_timeout_mutex);
pthread_cond_signal(&_timeout_cond); /* Wake it up to check exit */
pthread_mutex_unlock(&_timeout_mutex);
if (pthread_join(_timeout_thread_id, NULL))
if (pthread_join(thread_id, NULL))
log_sys_debug("pthread_join", "timeout thread");
}

View File

@@ -3353,7 +3353,9 @@ out_act:
pthread_mutex_unlock(&client_mutex);
pthread_mutex_lock(&lockspaces_mutex);
pthread_mutex_lock(&ls->mutex);
ls->thread_done = 1;
pthread_mutex_unlock(&ls->mutex);
if (ls->lm_type == LD_LM_DLM && !strcmp(ls->name, gl_lsname_dlm))
global_dlm_lockspace_exists = 0;
@@ -3858,6 +3860,41 @@ static int count_lockspace_starting(uint32_t client_id)
* returns sum of the previous two
*/
/*
* Wait briefly for lockspace threads to finish after being signaled to stop.
* lockspaces_mutex must be held by caller.
* Returns number of milliseconds waited.
*/
static void wait_for_lockspace_threads(void)
{
const struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; /* 1ms */
struct lockspace *ls;
int all_done, waited;
/* wait up to 100ms for threads to finish */
for (waited = 0; waited < 100; waited++) {
all_done = 1;
list_for_each_entry(ls, &lockspaces, list) {
pthread_mutex_lock(&ls->mutex);
if (ls->thread_stop && !ls->thread_done)
all_done = 0;
pthread_mutex_unlock(&ls->mutex);
}
if (all_done)
break;
pthread_mutex_unlock(&lockspaces_mutex);
nanosleep(&ts, NULL);
pthread_mutex_lock(&lockspaces_mutex);
}
if (waited)
log_debug("waited %d ms for lockspace threads to finish", waited);
}
static int for_each_lockspace(int do_stop, int do_free, int do_force)
{
struct lockspace *ls, *safe;
@@ -3893,6 +3930,15 @@ static int for_each_lockspace(int do_stop, int do_free, int do_force)
}
}
/*
* If we signaled threads to stop during daemon shutdown, give them
* a brief time to finish to avoid the race where daemon_quit is reset
* because threads haven't finished yet. During normal operations, the
* caller handles async lockspace cleanup appropriately.
*/
if (daemon_quit && do_stop && do_free && stop_count)
wait_for_lockspace_threads();
if (do_free) {
list_for_each_entry_safe(ls, safe, &lockspaces, list) {

View File

@@ -307,10 +307,16 @@ void pdst_locked_send_cancel(const struct lvmpolld_store *pdst)
struct lvmpolld_lv *pdlv;
struct dm_hash_node *n;
/* Signal child processes and cancel monitoring threads */
dm_hash_iterate(n, pdst->store) {
pdlv = dm_hash_get_data(pdst->store, n);
if (!pdlv_locked_polling_finished(pdlv))
if (!pdlv_locked_polling_finished(pdlv)) {
/* Signal child lvpoll process to terminate */
if (pdlv->cmd_pid > 0)
kill(pdlv->cmd_pid, SIGTERM);
/* Cancel monitoring thread (which will reap the child) */
pthread_cancel(pdlv->tid);
}
}
}

View File

@@ -984,7 +984,7 @@ int lv_check_not_in_use(const struct logical_volume *lv, int error_if_used)
open_count_check_retries = retry_deactivation() ? OPEN_COUNT_CHECK_RETRIES : 1;
while (open_count_check_retries--) {
if (interruptible_usleep(OPEN_COUNT_CHECK_USLEEP_DELAY))
if (!sigint_usleep(OPEN_COUNT_CHECK_USLEEP_DELAY))
break; /* interrupted */
log_debug_activation("Retrying open_count check for %s.",
@@ -2089,7 +2089,7 @@ int monitor_dev_for_events(struct cmd_context *cmd, const struct logical_volume
break;
log_very_verbose("%s %smonitoring still pending: waiting...",
display_lvname(lv), monitor ? "" : "un");
if (interruptible_usleep(10000 * i)) {
if (!sigint_usleep(10000 * i)) {
stack;
r = 0;
break;

View File

@@ -18,7 +18,6 @@
#include "lib/commands/toolcontext.h"
#include "lib/metadata/metadata.h"
#include "lib/config/defaults.h"
#include "lib/config/config.h"
#include "lib/misc/lvm-string.h"
#include "lib/activate/activate.h"
#include "lib/filters/filter.h"
@@ -34,7 +33,6 @@
#include "lib/format_text/archiver.h"
#include "lib/lvmpolld/lvmpolld-client.h"
#include "lib/device/device_id.h"
#include "include/lvm-version.h"
#include <locale.h>
#include <sys/stat.h>
@@ -616,7 +614,7 @@ static int _init_system_id(struct cmd_context *cmd)
return 1;
}
static void _init_device_ids_refresh(struct cmd_context *cmd)
static int _init_device_ids_refresh(struct cmd_context *cmd)
{
const struct dm_config_node *cn;
const struct dm_config_value *cv;
@@ -624,14 +622,21 @@ static void _init_device_ids_refresh(struct cmd_context *cmd)
int check_hostname = 0;
char path[PATH_MAX];
char uuid[128] = { 0 };
int val;
cmd->device_ids_check_product_uuid = 0;
cmd->device_ids_check_hostname = 0;
if (!find_config_tree_bool(cmd, devices_device_ids_refresh_CFG, NULL))
return;
if (!(val = find_config_tree_int(cmd, devices_device_ids_refresh_CFG, NULL)))
return 1;
if (!(cn = find_config_tree_array(cmd, devices_device_ids_refresh_checks_CFG, NULL)))
return;
return 1;
/* 0 disables, 1 enables single refresh, 10-600 enables refresh period */
if ((val > 1 && val < 10) || (val > 600)) {
log_error("Invalid device_ids_refresh value %u", val);
return 0;
}
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != DM_CFG_STRING)
@@ -645,7 +650,7 @@ static void _init_device_ids_refresh(struct cmd_context *cmd)
if (check_product_uuid) {
const char *sysfs_dir = cmd->device_id_sysfs_dir ?: dm_sysfs_dir();
if (dm_snprintf(path, sizeof(path), "%sdevices/virtual/dmi/id/product_uuid", sysfs_dir) < 0)
return;
return_0;
if (get_sysfs_value(path, uuid, sizeof(uuid), 0) && uuid[0])
cmd->product_uuid = dm_pool_strdup(cmd->libmem, uuid);;
if (cmd->product_uuid)
@@ -654,43 +659,7 @@ static void _init_device_ids_refresh(struct cmd_context *cmd)
if (check_hostname && cmd->hostname)
cmd->device_ids_check_hostname = 1;
}
void log_debug_config(struct cmd_context *cmd)
{
struct config_def_tree_spec tree_spec = {0};
struct cft_check_handle *handle = NULL;
unsigned int major, minor, patchlevel;
/* Parse version from LVM_VERSION string */
if (sscanf(LVM_VERSION, "%u.%u.%u", &major, &minor, &patchlevel) != 3) {
major = 0;
minor = 0;
patchlevel = 0;
}
tree_spec.cmd = cmd;
tree_spec.type = CFG_DEF_TREE_CURRENT;
tree_spec.current_cft = cmd->cft;
tree_spec.version = vsn(major, minor, patchlevel);
tree_spec.log_debug = 1;
/* Check config to mark differences from defaults */
if (!(handle = get_config_tree_check_handle(cmd, cmd->cft)))
return;
handle->force_check = 1;
handle->suppress_messages = 1;
handle->skip_if_checked = 0;
handle->check_diff = 1;
if (!config_def_check(handle))
return;
tree_spec.check_status = handle->status;
/* Write config via log_debug */
config_write(cmd->cft, &tree_spec, NULL, 0, NULL);
return 1;
}
static int _process_config(struct cmd_context *cmd)
@@ -873,7 +842,8 @@ static int _process_config(struct cmd_context *cmd)
if (!_init_system_id(cmd))
return_0;
_init_device_ids_refresh(cmd);
if (!_init_device_ids_refresh(cmd))
return_0;
init_io_memory_size(find_config_tree_int(cmd, global_io_memory_size_CFG, NULL));

View File

@@ -224,6 +224,7 @@ struct cmd_context {
unsigned device_ids_refresh_trigger:1;
unsigned device_ids_invalid:1;
unsigned device_ids_auto_import:1;
unsigned device_ids_read_refresh:1; /* device_ids_read found REFRESH_UNTIL */
unsigned get_vgname_from_options:1; /* used by lvconvert */
unsigned vg_write_validates_vg:1;
unsigned disable_pr_required:1;
@@ -236,6 +237,7 @@ struct cmd_context {
const char *md_component_checks;
const char *search_for_devnames; /* config file setting */
struct dm_list device_ids_check_serial;
uint64_t device_ids_refresh_until; /* timestamp of YYYYMMDDHHMMSS */
const char *devicesfile; /* from --devicesfile option */
struct dm_list deviceslist; /* from --devices option, struct dm_str_list */
@@ -316,8 +318,6 @@ int init_filters(struct cmd_context *cmd, unsigned load_persistent_cache);
int init_connections(struct cmd_context *cmd);
int init_run_by_dmeventd(struct cmd_context *cmd);
void log_debug_config(struct cmd_context *cmd);
/*
* A config context is a very light weight cmd struct that
* is only used for reading config settings from lvm.conf,

View File

@@ -1693,57 +1693,6 @@ struct out_baton {
#define MAX_COMMENT_LINE 512
static void _out_line(struct out_baton *out, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
static void _out_line(struct out_baton *out, const char *fmt, ...)
{
va_list ap;
char buf[4096];
const char *p;
size_t len;
va_start(ap, fmt);
if (out->tree_spec->log_debug) {
if (vsnprintf(buf, sizeof(buf), fmt, ap) >= 0) {
/* Skip section headers and brackets for log_debug output */
p = buf;
/* Skip leading whitespace */
while (*p == ' ' || *p == '\t')
p++;
/* Skip empty lines */
if (*p == '\0' || *p == '\n')
goto out;
/* Skip closing brackets */
if (*p == '}') {
va_end(ap);
return;
}
/* Skip lines ending with opening bracket (section headers) */
len = strlen(p);
if (len > 0 && p[len - 1] == '\n')
len--;
while (len > 0 && (p[len - 1] == ' ' || p[len - 1] == '\t'))
len--;
if (len > 1 && p[len - 1] == '{')
goto out;
/* Print without leading whitespace and without trailing newline */
if (len > 0 && p[len] == '\n')
log_debug("%.*s", (int)len, p);
else
log_debug("%s", p);
}
} else {
vfprintf(out->fp, fmt, ap);
}
out:
va_end(ap);
}
static int _copy_one_line(const char *comment, char *line, int *pos, int len)
{
int p;
@@ -1804,7 +1753,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
if (cn->id <= 0)
return 1;
if (out->tree_spec->type == CFG_DEF_TREE_LIST)
if (out->tree_spec->listmode)
return 1;
if ((out->tree_spec->type == CFG_DEF_TREE_DIFF) &&
@@ -1817,11 +1766,11 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
if (out->tree_spec->withsummary || out->tree_spec->withcomments) {
_cfg_def_make_path(path, sizeof(path), cfg_def->id, cfg_def, 1);
_out_line(out, "\n");
_out_line(out, "%s# Configuration %s %s.\n", line, node_type_name, path);
fprintf(out->fp, "\n");
fprintf(out->fp, "%s# Configuration %s %s.\n", line, node_type_name, path);
if (out->tree_spec->withcomments && is_deprecated && cfg_def->deprecation_comment)
_out_line(out, "%s# %s", line, cfg_def->deprecation_comment);
fprintf(out->fp, "%s# %s", line, cfg_def->deprecation_comment);
if (cfg_def->comment) {
int pos = 0;
@@ -1831,7 +1780,7 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
continue;
commentline[0] = '\0';
}
_out_line(out, "%s#%s%s\n", line, commentline[0] ? " " : "", commentline);
fprintf(out->fp, "%s#%s%s\n", line, commentline[0] ? " " : "", commentline);
/* withsummary prints only the first comment line. */
if (!out->tree_spec->withcomments)
break;
@@ -1839,37 +1788,37 @@ static int _out_prefix_fn(const struct dm_config_node *cn, const char *line, voi
}
if (is_deprecated)
_out_line(out, "%s# This configuration %s is deprecated.\n", line, node_type_name);
fprintf(out->fp, "%s# This configuration %s is deprecated.\n", line, node_type_name);
if (cfg_def->flags & CFG_ADVANCED)
_out_line(out, "%s# This configuration %s is advanced.\n", line, node_type_name);
fprintf(out->fp, "%s# This configuration %s is advanced.\n", line, node_type_name);
if (cfg_def->flags & CFG_UNSUPPORTED)
_out_line(out, "%s# This configuration %s is not officially supported.\n", line, node_type_name);
fprintf(out->fp, "%s# This configuration %s is not officially supported.\n", line, node_type_name);
if (cfg_def->flags & CFG_NAME_VARIABLE)
_out_line(out, "%s# This configuration %s has variable name.\n", line, node_type_name);
fprintf(out->fp, "%s# This configuration %s has variable name.\n", line, node_type_name);
if (cfg_def->flags & CFG_DEFAULT_UNDEFINED)
_out_line(out, "%s# This configuration %s does not have a default value defined.\n", line, node_type_name);
fprintf(out->fp, "%s# This configuration %s does not have a default value defined.\n", line, node_type_name);
if (cfg_def->flags & CFG_DEFAULT_COMMENTED)
_out_line(out, "%s# This configuration %s has an automatic default value.\n", line, node_type_name);
fprintf(out->fp, "%s# This configuration %s has an automatic default value.\n", line, node_type_name);
if ((out->tree_spec->type == CFG_DEF_TREE_FULL) &&
(out->tree_spec->check_status[cn->id] & CFG_USED))
_out_line(out, "%s# Value defined in existing configuration has been used for this setting.\n", line);
fprintf(out->fp, "%s# Value defined in existing configuration has been used for this setting.\n", line);
}
if (out->tree_spec->withversions) {
if (!_get_config_node_version(cfg_def->since_version, version))
return_0;
_out_line(out, "%s# Available since version %s.\n", line, version);
fprintf(out->fp, "%s# Available since version %s.\n", line, version);
if (is_deprecated) {
if (!_get_config_node_version(cfg_def->deprecated_since_version, version))
return_0;
_out_line(out, "%s# Deprecated since version %s.\n", line, version);
fprintf(out->fp, "%s# Deprecated since version %s.\n", line, version);
}
}
@@ -1886,50 +1835,55 @@ static int _should_print_cfg_with_undef_def_val(struct out_baton *out, const cfg
return out->tree_spec->check_status && (out->tree_spec->check_status[cn->id] & CFG_USED);
}
static int _out_line_fn(const struct dm_config_node *cn, const char *line, void *baton)
static int _out_line_list(const struct dm_config_node *cn, const char *line, struct out_baton *out)
{
struct out_baton *out = baton;
const struct cfg_def_item *cfg_def;
char config_path[CFG_PATH_MAX_LEN];
char summary[MAX_COMMENT_LINE+1];
char version[9];
const struct cfg_def_item *cfg_def;
int pos = 0;
char *val = NULL;
cfg_def = cfg_def_get_item_p(cn->id);
if (cfg_def->type & CFG_TYPE_SECTION)
return 1;
if (!_cfg_def_make_path(config_path, CFG_PATH_MAX_LEN, cfg_def->id, cfg_def, 1))
return_0;
if (out->tree_spec->withversions && !_get_config_node_version(cfg_def->since_version, version))
return_0;
summary[0] = '\0';
if (out->tree_spec->withsummary && cfg_def->comment)
_copy_one_line(cfg_def->comment, summary, &pos, strlen(cfg_def->comment));
if (out->tree_spec->type != CFG_DEF_TREE_LIST) {
if (!(val = strrchr(line, '=')))
return 0;
}
fprintf(out->fp, "%s%s%s%s%s%s%s%s\n", config_path, val ? val : "",
*summary || out->tree_spec->withversions ? " - ": "",
*summary ? summary : "",
*summary ? " " : "",
out->tree_spec->withversions ? "[" : "",
out->tree_spec->withversions ? version : "",
out->tree_spec->withversions ? "]" : "");
return 1;
}
static int _out_line_tree(const struct dm_config_node *cn, const char *line, struct out_baton *out)
{
const struct cfg_def_item *cfg_def;
int space_prefix_len = 0;
const char *p;
size_t len;
if ((out->tree_spec->type == CFG_DEF_TREE_DIFF) &&
(!(out->tree_spec->check_status[cn->id] & CFG_DIFF)))
return 1;
cfg_def = cfg_def_get_item_p(cn->id);
if (out->tree_spec->type == CFG_DEF_TREE_LIST) {
/* List view with node paths and summary. */
if (cfg_def->type & CFG_TYPE_SECTION)
return 1;
if (!_cfg_def_make_path(config_path, CFG_PATH_MAX_LEN, cfg_def->id, cfg_def, 1))
return_0;
if (out->tree_spec->withversions && !_get_config_node_version(cfg_def->since_version, version))
return_0;
summary[0] = '\0';
if (out->tree_spec->withsummary && cfg_def->comment)
_copy_one_line(cfg_def->comment, summary, &pos, strlen(cfg_def->comment));
_out_line(out, "%s%s%s%s%s%s%s\n", config_path,
*summary || out->tree_spec->withversions ? " - ": "",
*summary ? summary : "",
*summary ? " " : "",
out->tree_spec->withversions ? "[" : "",
out->tree_spec->withversions ? version : "",
out->tree_spec->withversions ? "]" : "");
return 1;
}
/* Usual tree view with nodes and their values. */
if (out->tree_spec->valuesonly && !(cfg_def->type & CFG_TYPE_SECTION)) {
if ((space_prefix_len = strspn(line, "\t "))) {
len = strlen(line);
@@ -1958,7 +1912,7 @@ static int _out_line_fn(const struct dm_config_node *cn, const char *line, void
/* print with # at the front to comment out the line */
if (_should_print_cfg_with_undef_def_val(out, cfg_def, cn)) {
space_prefix_len = strspn(line, "\t ");
_out_line(out, "%.*s%s%s\n", space_prefix_len, line, "# ",
fprintf(out->fp, "%.*s%s%s\n", space_prefix_len, line, "# ",
line + space_prefix_len);
}
return 1;
@@ -1966,12 +1920,27 @@ static int _out_line_fn(const struct dm_config_node *cn, const char *line, void
/* print the line as it is */
if (_should_print_cfg_with_undef_def_val(out, cfg_def, cn))
_out_line(out, "%s\n", line);
fprintf(out->fp, "%s\n", line);
if (out->tree_spec->valuesonly && !(cfg_def->type & CFG_TYPE_SECTION) && space_prefix_len)
dm_pool_free(out->mem, (char *) line);
return 1;
}
static int _out_line_fn(const struct dm_config_node *cn, const char *line, void *baton)
{
struct out_baton *out = baton;
if ((out->tree_spec->type == CFG_DEF_TREE_DIFF) &&
(!(out->tree_spec->check_status[cn->id] & CFG_DIFF)))
return 1;
if (out->tree_spec->listmode)
return _out_line_list(cn, line, out);
return _out_line_tree(cn, line, out);
}
static int _out_suffix_fn(const struct dm_config_node *cn, const char *line, void *baton)
@@ -1996,11 +1965,7 @@ int config_write(struct dm_config_tree *cft,
int free_fp = 1;
int r = 1;
if (tree_spec->log_debug) {
/* When using log_debug, we don't need a file pointer */
baton.fp = NULL;
free_fp = 0;
} else if (!file) {
if (!file) {
baton.fp = stdout;
file = "stdout";
free_fp = 0;
@@ -2009,13 +1974,12 @@ int config_write(struct dm_config_tree *cft,
return 0;
}
if (!tree_spec->log_debug)
log_verbose("Dumping configuration to %s", file);
log_verbose("Dumping configuration to %s", file);
if (tree_spec->withgeneralpreamble)
_out_line(&baton, CFG_PREAMBLE_GENERAL);
fprintf(baton.fp, CFG_PREAMBLE_GENERAL);
if (tree_spec->withlocalpreamble)
_out_line(&baton, CFG_PREAMBLE_LOCAL);
fprintf(baton.fp, CFG_PREAMBLE_LOCAL);
if (!argc) {
if (!dm_config_write_node_out(cft->root, &_out_spec, &baton)) {

View File

@@ -177,7 +177,7 @@ struct config_def_tree_spec {
unsigned withgeneralpreamble:1; /* include preamble for a general config file */
unsigned withlocalpreamble:1; /* include preamble for a local config file */
unsigned valuesonly:1; /* print only values without keys */
unsigned log_debug:1; /* use log_debug() instead of file output */
unsigned listmode:1; /* print in list mode instead of structured tree mode */
uint8_t *check_status; /* status of last tree check (currently needed for CFG_DEF_TREE_MISSING only) */
};

View File

@@ -324,13 +324,19 @@ cfg(devices_search_for_devnames_CFG, "search_for_devnames", devices_CFG_SECTION,
"at other devices, but only those that are likely to have the PV.\n"
"If \"all\", lvm will look at all devices on the system.\n")
cfg(devices_device_ids_refresh_CFG, "device_ids_refresh", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 1, vsn(2, 3, 23), NULL, 0, NULL,
cfg(devices_device_ids_refresh_CFG, "device_ids_refresh", devices_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_INT, DEFAULT_DEVICE_IDS_REFRESH, vsn(2, 3, 23), NULL, 0, NULL,
"Find PVs on new devices and update the device IDs in the devices file.\n"
"If PVs are restored or moved to a new system with new devices, but\n"
"an old system.devices remains with old device IDs, then search for\n"
"the PVIDs on new devices and update the device IDs in system.devices.\n"
"The original device IDs must also not be found on the new system.\n"
"See device_ids_refresh_check for conditions that trigger the refresh.\n")
"See device_ids_refresh_check for conditions that trigger the refresh.\n"
"Set to 1 to enable a single automatic refresh attempt when a trigger\n"
"condition is detected. Set to 0 to disable automatic refresh.\n"
"Set to a value between 10 and 600 (in seconds) to enable an extended\n"
"refresh period during which missing PVs will be located using the PVID,\n"
"and the system.devices device ID updated if the PV is found on a new device.\n"
"An extended refresh period may be useful if devices require refresh,\n"
"but are attached to the system some time the initial refresh.\n")
cfg_array(devices_device_ids_refresh_checks_CFG, "device_ids_refresh_checks", devices_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "#Sproduct_uuid#Shostname", vsn(2, 3, 23), NULL, 0, NULL,
"Conditions that trigger device_ids_refresh to locate PVIDs on new devices.\n"

View File

@@ -348,4 +348,6 @@
#define DEFAULT_DEVICESFILE_BACKUP_LIMIT 50
#define DEFAULT_DEVICE_IDS_REFRESH 10
#endif /* _LVM_DEFAULTS_H */

View File

@@ -54,6 +54,50 @@ static const char _searched_file_dir[] = DEFAULT_RUN_DIR;
char devices_file_hostname_orig[PATH_MAX];
char devices_file_product_uuid_orig[PATH_MAX];
static uint64_t _get_refresh_timestamp(unsigned int add_seconds)
{
time_t now;
struct tm *tm;
uint64_t timestamp;
time(&now);
now += add_seconds;
tm = gmtime(&now);
/* YYYYMMDDHHMMSS as a uint64_t */
timestamp = (uint64_t)tm->tm_year + 1900;
timestamp = timestamp * 100 + (tm->tm_mon + 1);
timestamp = timestamp * 100 + tm->tm_mday;
timestamp = timestamp * 100 + tm->tm_hour;
timestamp = timestamp * 100 + tm->tm_min;
timestamp = timestamp * 100 + tm->tm_sec;
return timestamp;
}
static uint64_t _new_refresh_timestamp(struct cmd_context *cmd)
{
unsigned int val;
/*
* val:
* 0: refresh trigger disabled (this function will not be called)
* 1: single refresh enabled, no extended period (return 0)
* 10-600: refresh period enabled for the specified number of seconds
* (return a new refresh_until timestamp: the current time
* plus the configured number of seconds for the refresh period)
* other values: treated like 1 (return 0)
*/
if (!(val = find_config_tree_int(cmd, devices_device_ids_refresh_CFG, NULL)))
return_0;
if (val >= 10 && val <= 600)
return _get_refresh_timestamp(val);
return 0;
}
/*
* The input string pvid may be of any length, it's often
* read from system.devices, which can be edited.
@@ -1311,6 +1355,8 @@ int device_ids_read(struct cmd_context *cmd)
log_debug("Devices file hostname %s vs local %s.",
check_id[0] ? check_id : "none", cmd->hostname ?: "none");
cmd->device_ids_refresh_trigger = 1;
cmd->device_ids_refresh_until = _new_refresh_timestamp(cmd);
log_debug("Devices file refresh until %llu new", (unsigned long long)cmd->device_ids_refresh_until);
}
continue;
}
@@ -1332,10 +1378,31 @@ int device_ids_read(struct cmd_context *cmd)
log_debug("Devices file product_uuid %s vs local %s.",
check_id[0] ? check_id : "none", cmd->product_uuid ?: "none");
cmd->device_ids_refresh_trigger = 1;
cmd->device_ids_refresh_until = _new_refresh_timestamp(cmd);
log_debug("Devices file refresh until %llu new", (unsigned long long)cmd->device_ids_refresh_until);
}
continue;
}
if (!strncmp(line, "REFRESH_UNTIL", 13)) {
uint64_t refresh_until = 0;
_copy_idline_str(line, check_id, sizeof(check_id));
log_debug("read devices file refresh_until %s", check_id);
if (check_id[0] && find_config_tree_int(cmd, devices_device_ids_refresh_CFG, NULL))
refresh_until = strtoull(check_id, NULL, 0);
if (refresh_until == ULLONG_MAX)
refresh_until = 0;
/* device_ids_read_refresh=1 means system.devices contains a REFRESH_UNTIL line */
cmd->device_ids_read_refresh = 1;
cmd->device_ids_refresh_until = refresh_until;
if (refresh_until && (_get_refresh_timestamp(0) < refresh_until))
cmd->device_ids_refresh_trigger = 1;
log_debug("Devices file refresh until %llu old trigger %d",
(unsigned long long)cmd->device_ids_refresh_until, cmd->device_ids_refresh_trigger);
continue;
}
if (!strncmp(line, "VERSION", 7)) {
_copy_idline_str(line, _devices_file_version, sizeof(_devices_file_version));
log_debug("read devices file version %s", _devices_file_version);
@@ -1771,6 +1838,15 @@ int device_ids_write(struct cmd_context *cmd)
if (dm_snprintf(version_buf, VERSION_LINE_MAX, "VERSION=%u.%u.%u", DEVICES_FILE_MAJOR, DEVICES_FILE_MINOR, df_counter+1) < 0)
goto_out;
if (cmd->device_ids_refresh_until && cmd->device_ids_refresh_trigger) {
num = snprintf(fb + pos, len - pos, "REFRESH_UNTIL=%llu\n", (unsigned long long)cmd->device_ids_refresh_until);
if (num >= len - pos) {
log_warn("Failed to write buffer for devices file content.");
goto out;
}
pos += num;
}
num = snprintf(fb + pos, len - pos, "%s\n", version_buf);
if (num >= len - pos) {
log_warn("Failed to write buffer for devices file content.");
@@ -3155,6 +3231,7 @@ int device_id_system_list(struct cmd_context *cmd, struct device *dev, uint16_t
log_print("%s", idname);
else
log_print("%-16s %s", idtype_to_str(idtype), idname);
free(idname);
found++;
}
}
@@ -3610,6 +3687,20 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
}
}
/*
* If device_ids_search() will be called (device_ids_invalid is set,
* or device_ids_refresh_trigger is set), then let that function
* decide about updating the devices file refresh_until.
*
* If search will not be called, refresh_until is set in the file,
* but refresh_until is not active, then remove it from the file.
*/
if (!cmd->device_ids_invalid && !cmd->device_ids_refresh_trigger && cmd->device_ids_read_refresh) {
log_debug("Validate device ids: update to remove refresh_until");
cmd->device_ids_refresh_until = 0;
update_file = 1;
}
/*
* When info in the devices file has become incorrect,
* try another search for PVIDs on renamed devices.
@@ -4306,6 +4397,30 @@ void device_ids_search(struct cmd_context *cmd, struct dm_list *new_devs,
}
out:
/*
* Remove REFRESH_UNTIL if it was set in the file,
* and all devices have been found.
* Add REFRESH_UNTIL if it was not set in the file,
* and all devices have not been found, and the
* refresh_until interval is active.
*/
if (cmd->device_ids_read_refresh && !not_found) {
log_debug("Search for PVIDs remove refresh_until");
cmd->device_ids_refresh_until = 0;
update_file = 1;
}
if (!cmd->device_ids_read_refresh && not_found && cmd->device_ids_refresh_until) {
log_debug("Search for PVIDs add refresh_until not_found %d", not_found);
update_file = 1;
}
/*
* If the devices file is already being updated, don't include
* REFRESH_UNTIL if all devices are found.
*/
if (!not_found)
cmd->device_ids_refresh_until = 0;
/*
* try lock and device_ids_write(), the update is not required and will
* be done by a subsequent command if it's not done here.
@@ -4359,8 +4474,8 @@ void device_ids_search(struct cmd_context *cmd, struct dm_list *new_devs,
* It does not suppress searches for missing PVIDs when done for
* refresh, where PVIDs of any idtype are searched for.
*/
if (!cmd->device_ids_refresh_trigger && !all_ids && not_found && !found &&
strcmp(cmd->name, "lvmdevices"))
if (!cmd->device_ids_refresh_trigger && !cmd->device_ids_refresh_until &&
!all_ids && not_found && !found && strcmp(cmd->name, "lvmdevices"))
_searched_devnames_create(cmd, search_pvids_count, search_pvids_hash,
search_devs_count, search_devs_hash);
}

View File

@@ -465,7 +465,7 @@ int lv_cache_wait_for_clean(struct logical_volume *cache_lv, int *is_clean)
//FIXME: use polling to do this...
for (;;) {
if (cleaner_policy && interruptible_usleep(500000)) {
if (cleaner_policy && !sigint_usleep(500000)) {
log_error("Flushing of %s aborted.", display_lvname(cache_lv));
if (cache_seg->cleaner_policy) {
cache_seg->cleaner_policy = 0;
@@ -493,8 +493,10 @@ int lv_cache_wait_for_clean(struct logical_volume *cache_lv, int *is_clean)
dm_pool_destroy(status->mem);
/* Only clear when policy is Clear or mode != writeback */
if (!dirty_blocks && (cleaner_policy || !writeback))
if (!dirty_blocks && (cleaner_policy || !writeback)) {
log_debug("Flush complete.");
break;
}
log_print_unless_silent("Flushing " FMTu64 " blocks for cache %s.",
dirty_blocks, display_lvname(cache_lv));

View File

@@ -421,7 +421,7 @@ static int _raid_in_sync(const struct logical_volume *lv)
if (retries == _RAID_IN_SYNC_RETRIES)
log_warn("WARNING: Sync status for %s is inconsistent.",
display_lvname(lv));
if (interruptible_usleep(500000))
if (!sigint_usleep(500000))
return_0;
} while (--retries);

View File

@@ -136,6 +136,19 @@ void sigint_restore(void)
log_sys_debug("sigaction", _ar_sigs[i].name);
}
/* usleep for specified microseconds with SIGINT handling enabled.
* Returns 1 if sleep completed, 0 if interrupted by signal. */
int sigint_usleep(useconds_t usec)
{
int r;
sigint_allow();
r = usleep(usec);
sigint_restore();
return (sigint_caught() || r) ? 0 : 1;
}
void block_signals(uint32_t flags __attribute__((unused)))
{
sigset_t set;
@@ -175,16 +188,3 @@ void unblock_signals(void)
_signals_blocked = 0;
}
/* usleep with enabled signal handler.
* Returns 1 when there was interruption */
int interruptible_usleep(useconds_t usec)
{
int r;
sigint_allow();
r = usleep(usec);
sigint_restore();
return (sigint_caught() || r) ? 1 : 0;
}

View File

@@ -27,9 +27,8 @@ void sigint_allow(void);
int sigint_caught(void);
void sigint_restore(void);
void sigint_clear(void);
int sigint_usleep(useconds_t usec);
void block_signals(uint32_t flags);
void unblock_signals(void);
int interruptible_usleep(useconds_t usec);
#endif

View File

@@ -48,9 +48,9 @@ static int _pthread_create(pthread_t *t, void *(*fun)(void *), void *arg, int st
static volatile sig_atomic_t _shutdown_requested = 0;
static int _systemd_activation = 0;
static void _exit_handler(int sig __attribute__((unused)))
static void _exit_handler(int sig)
{
_shutdown_requested = 1;
_shutdown_requested = sig;
}
#define EXIT_ALREADYRUNNING 13
@@ -343,6 +343,7 @@ static void _daemonize(daemon_state s)
sigemptyset(&my_sigset);
if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) {
fprintf(stderr, "Unable to restore signals.\n");
(void) close(fd);
exit(EXIT_FAILURE);
}
signal(SIGTERM, &_exit_handler);
@@ -350,6 +351,7 @@ static void _daemonize(daemon_state s)
switch (pid = fork()) {
case -1:
perror("fork failed:");
(void) close(fd);
exit(EXIT_FAILURE);
case 0: /* Child */
@@ -380,13 +382,17 @@ static void _daemonize(daemon_state s)
if (chdir("/")) {
perror("Cannot chdir to /");
(void) close(fd);
exit(1);
}
if ((dup2(fd, STDIN_FILENO) == -1) ||
(dup2(fd, STDOUT_FILENO) == -1) ||
(dup2(fd, STDERR_FILENO) == -1)) {
if (((fd != STDIN_FILENO) && (dup2(fd, STDIN_FILENO) == -1)) ||
((fd != STDOUT_FILENO) && (dup2(fd, STDOUT_FILENO) == -1)) ||
((fd != STDERR_FILENO) && (dup2(fd, STDERR_FILENO) == -1))) {
perror("Error setting terminal FDs to /dev/null");
if (fd > STDERR_FILENO)
(void) close(fd);
/* coverity[leaked_handle] fd is stdin/stdout/stderr */
exit(2);
}
@@ -399,7 +405,7 @@ static void _daemonize(daemon_state s)
setsid();
/* coverity[leaked_handle] 'fd' handle is not leaking */
/* coverity[leaked_handle] 'fd' is stdin/stdout/stderr */
}
response daemon_reply_simple(const char *id, ...)
@@ -446,7 +452,8 @@ static void *_client_thread(void *state)
buffer_init(&req.buffer);
while (1) {
/* Exit early if shutdown is requested */
while (!_shutdown_requested) {
if (!buffer_read(ts->client.socket_fd, &req.buffer))
goto fail;
@@ -559,6 +566,50 @@ static void _reap(daemon_state s, int waiting)
}
}
static void _shutdown_sockets(daemon_state *s)
{
thread_state *ts;
/*
* Close the listening socket BEFORE shutting down client sockets.
* This prevents new connections during shutdown.
*/
if (s->socket_fd >= 0) {
INFO(s, "%s closing listening socket", s->name);
if (!_systemd_activation && s->socket_path && unlink(s->socket_path))
perror("unlink error");
if (close(s->socket_fd))
perror("socket close");
s->socket_fd = -1;
}
/*
* Shutdown all client sockets to interrupt any blocking read() calls.
* This allows client threads to exit quickly instead of waiting
* for data that will never arrive.
*/
for (ts = s->threads->next; ts; ts = ts->next)
if (ts->client.socket_fd >= 0) {
INFO(s, "%s closing client socket fd %d", s->name, ts->client.socket_fd);
shutdown(ts->client.socket_fd, SHUT_RDWR);
}
}
static void _daemon_cleanup(daemon_state s, int failed)
{
if (s.daemon_fini)
if (!s.daemon_fini(&s))
failed = 1;
INFO(&s, "%s shutting down", s.name);
closelog(); /* FIXME */
if (s.pidfile)
_remove_lockfile(s.pidfile);
if (failed)
exit(1);
}
void daemon_start(daemon_state s)
{
int failed = 0;
@@ -635,14 +686,17 @@ void daemon_start(daemon_state s)
if (!s.foreground)
kill(getppid(), SIGTERM);
/* * Use daemon_main for daemon-specific init and polling, or
/*
* Use daemon_main for daemon-specific init and polling, or
* use daemon_init for daemon-specific init and generic lib polling.
*/
if (s.daemon_main) {
if (!s.daemon_main(&s))
failed = 1;
goto out;
_shutdown_sockets(&s);
_daemon_cleanup(s, failed);
return;
}
if (s.daemon_init)
@@ -691,29 +745,12 @@ void daemon_start(daemon_state s)
}
if (_shutdown_requested)
INFO(&s, "%s shutdown requested", s.name);
INFO(&s, "%s shutdown requested by signal %d.", s.name, (int)_shutdown_requested);
_shutdown_sockets(&s);
INFO(&s, "%s waiting for client threads to finish", s.name);
_reap(s, 1);
out:
/* If activated by systemd, do not unlink the socket - systemd takes care of that! */
if (!_systemd_activation && s.socket_fd >= 0)
if (s.socket_path && unlink(s.socket_path))
perror("unlink error");
if (s.socket_fd >= 0)
if (close(s.socket_fd))
perror("socket close");
if (s.daemon_fini)
if (!s.daemon_fini(&s))
failed = 1;
INFO(&s, "%s shutting down", s.name);
closelog(); /* FIXME */
if (s.pidfile)
_remove_lockfile(s.pidfile);
if (failed)
exit(1);
_daemon_cleanup(s, failed);
}

View File

@@ -15,6 +15,7 @@
*/
#include "libdm/misc/dm-logging.h"
#include "libdaemon/server/daemon-stray.h" /* daemon_close_stray_fds() from libdaemon */
#include "util.h"
#ifdef __linux__
@@ -439,7 +440,7 @@ static int _filemap_monitor_reopen_fd(struct filemap_monitor *fm)
*
* FIXME: stat file and skip if inode is unchanged.
*/
if (fm->fd > 0)
if (fm->fd >= 0)
log_error("Filemap file descriptor already open.");
while ((fm->fd < 0) && --tries)
@@ -533,7 +534,7 @@ out:
static void _filemap_monitor_destroy(struct filemap_monitor *fm)
{
if (fm->fd > 0) {
if (fm->fd >= 0) {
_filemap_monitor_end_notify(fm);
_filemap_monitor_close_fd(fm);
}
@@ -629,7 +630,9 @@ check_unlinked:
static int _daemonize(struct filemap_monitor *fm)
{
pid_t pid = 0;
int fd, ffd;
int fd;
/* Close stray file descriptors, preserving fm->fd */
struct custom_fds custom_fds = { .out = fm->fd };
if (!setsid()) {
_early_log("setsid failed.");
@@ -658,24 +661,22 @@ static int _daemonize(struct filemap_monitor *fm)
return 0;
}
if ((dup2(fd, STDIN_FILENO) == -1) ||
(dup2(fd, STDOUT_FILENO) == -1) ||
(dup2(fd, STDERR_FILENO) == -1)) {
if (((fd != STDIN_FILENO) && (dup2(fd, STDIN_FILENO) == -1)) ||
((fd != STDOUT_FILENO) && (dup2(fd, STDOUT_FILENO) == -1)) ||
((fd != STDERR_FILENO) && (dup2(fd, STDERR_FILENO) == -1))) {
if (fd > STDERR_FILENO)
(void) close(fd);
_early_log("Error redirecting stdin/out/err to null.");
/* coverity[leaked_handle] no leak */
/* coverity[leaked_handle] fd is stdin/stdout/stderr */
return 0;
}
if (fd > STDERR_FILENO)
(void) close(fd);
}
/* TODO: Use libdaemon/server/daemon-server.c _daemonize() */
for (ffd = (int) sysconf(_SC_OPEN_MAX) - 1; ffd > STDERR_FILENO; --ffd)
if (ffd != fm->fd)
(void) close(ffd);
/* coverity[leaked_handle] no leak */
daemon_close_stray_fds("dmfilemapd", 1, STDERR_FILENO, &custom_fds);
/* coverity[leaked_handle] fd is stdin/stdout/stderr */
return 1;
}
@@ -814,7 +815,7 @@ static const char _mode_names[][8] = {
*/
int main(int argc, char **argv)
{
struct filemap_monitor fm = { .fd = 0 };
struct filemap_monitor fm = { .fd = -1 };
if (!_parse_args(argc, argv, &fm)) {
free(fm.path);

View File

@@ -1069,6 +1069,9 @@ static const char *_find_config_str(const void *start, node_lookup_fn find_fn,
log_warn("WARNING: Ignoring unsupported value for %s.", path);
}
if (fail)
log_very_verbose("%s not found in config: defaulting to %s",
path, fail);
return fail;
}
@@ -1094,6 +1097,8 @@ static int64_t _find_config_int64(const void *start, node_lookup_fn find,
return n->v->v.i;
}
log_very_verbose("%s not found in config: defaulting to %" PRId64,
path, fail);
return fail;
}
@@ -1107,6 +1112,9 @@ static float _find_config_float(const void *start, node_lookup_fn find,
return n->v->v.f;
}
log_very_verbose("%s not found in config: defaulting to %f",
path, fail);
return fail;
}
@@ -1161,6 +1169,9 @@ static int _find_config_bool(const void *start, node_lookup_fn find,
}
}
log_very_verbose("%s not found in config: defaulting to %d",
path, fail);
return fail;
}

View File

@@ -456,8 +456,8 @@ debug: record full command debugging.
.
.TP
.O_list
List config settings with summarizing comment. This is the same as using
options --typeconfig list --withsummary.
Print a list of config settings instead of structured config settings tree.
If used without other options, this is the same as --typeconfig list --withsummary.
.
.TP
.O_lockopt

View File

@@ -183,11 +183,11 @@ the device IDs. LVM commands automatically update this information if it
changes. This includes the last known device name, and the PV UUID (PVID)
from the LVM disk header.
.P
To check if devices file content needs to be updated, run:
Check if the devices file content needs to be updated:
.br
.B lvmdevices --check
.P
To update devices file fields that may be outdated, run:
Update devices file fields that are outdated:
.br
.B lvmdevices --update
.P
@@ -219,26 +219,60 @@ PART: the partition number if a PV exists on a partition.
.P
.SS device ID refresh
.
When LVM writes system.devices, it includes an ID of the machine running
the command (see PRODUCT_UUID or HOSTNAME above.) When LVM reads
system.devices, it compares the saved value to the current machine's value
to detect if system.devices has been copied from another machine. When the
saved and current values differ, it indicates that PVs may have been copied or
restored onto new devices on a new machine. When this happens, lvm will
search for new devices that hold the PVIDs listed in system.devices. If a
PVID is found on a new device, lvm updates the device ID in system.devices
to match the new location for the PV. The command lvmdevices --check
--refresh can also be used to do this manually.
When lvm writes system.devices, it includes a local machine ID in the
system.devices file (as PRODUCT_UUID or HOSTNAME.) When lvm reads
system.devices, it compares this saved machine ID to the current machine,
which allows lvm to detect when system.devices has been copied or restored
onto a different machine. When a machine change is detected, lvm enables
a "device ID refresh" mode (configured by lvm.conf device_ids_refresh and
device_ids_refresh_checks.)
.P
The machine identifier used in system.devices will be either the DMI
product_uuid from
In refresh mode, a device in system.devices that is not found by its device ID
will be located using its PVID. LVM will scan all devices on the system to
search for the missing PVIDs in system.devices. If a PVID is found on a
new device, the system.devices entry is updated with a new device ID matching
the new device on which the PVID was found. The refresh mode can be configured
to run once, when the machine change is first detected, or can be enabled
for period of time following the first refresh, or can be disabled
entirely.
.P
.B device_ids_refresh = 0
.br
Disables refresh mode.
.P
.B device_ids_refresh = 1
.br
Enables one attempt to refresh device IDs when a machine
change is first detected.
.P
.B device_ids_refresh =
.I seconds
.br
The refresh mode is enabled for this number of seconds
following the initial refresh attempt, or until all PVs
in system.devices are found. During this period, a
REFRESH_UNTIL line appears in system.devices. Accepted
values are 10-600 seconds.
.P
In addition to the automated device ID refresh mode, refresh
can be performed manually:
.P
Check if system.devices would be updated with new device IDs:
.br
.B lvmdevices --check --refresh
.P
Update system.devices with new device IDs if PVs are found on new devices:
.br
.B lvmdevices --update --refresh
.P
The machine ID used in system.devices will be either the DMI product_uuid from
.IR /sys/devices/virtual/dmi/id/product_uuid ,
or the hostname from
.BR uname (2).
See
.BR lvm.conf (5)
.B device_ids_refresh_checks to
configure this.
.B device_ids_refresh_checks
to configure this.
.P
.SS custom devices files
.

View File

@@ -31,6 +31,10 @@
.OPA adddev
\fIPV\fP
..
.de O_addid
.OPA addid
\fIString\fP
..
.de O_addpvid
.OPA addpvid
\fIString\fP
@@ -54,6 +58,10 @@
.OPA deldev
\fIString\fP
..
.de O_delid
.OPA delid
\fIString\fP
..
.de O_delnotfound
.OPS delnotfound
..
@@ -77,6 +85,10 @@
.OPA driverloaded
\fBy\fP|\fBn\fP
..
.de O_force
.OPA f force
\&\.\|.\|.\&
..
.de O_help
.OPS h help
..
@@ -84,6 +96,10 @@
.OPA journal
\fIString\fP
..
.de O_listids
.OPA listids
\fIPV\fP
..
.de O_lockopt
.OPA lockopt
\fIString\fP
@@ -142,6 +158,8 @@ lvmdevices \(em Manage the devices file
.PD 0
.O_adddev
.br
.O_addid
.br
.O_addpvid
.br
.O_check
@@ -154,6 +172,8 @@ lvmdevices \(em Manage the devices file
.br
.O_deldev
.br
.O_delid
.br
.O_delnotfound
.br
.O_delpvid
@@ -166,10 +186,14 @@ lvmdevices \(em Manage the devices file
.br
.O_driverloaded
.br
.O_force
.br
.O_help
.br
.O_journal
.br
.O_listids
.br
.O_lockopt
.br
.O_longhelp
@@ -205,75 +229,126 @@ lvmdevices \(em Manage the devices file
.
.SH DESCRIPTION
.
The LVM devices file lists devices that lvm can use. The default file is
\fI#DEFAULT_SYS_DIR#/devices/system.devices\fP, and the \fBlvmdevices\fP(8) command is used to
add or remove device entries. If the file does not exist, or if lvm.conf
includes use_devicesfile=0, then lvm will not use a devices file.
The LVM devices file is the list of devices that lvm commands will use.
It is located at \fI#DEFAULT_SYS_DIR#/devices/system.devices\fP.
The \fBlvmdevices\fP(8) command manages the file, and is used to
add, remove and list devices.
.P
To use a device with lvm, add it to the devices file with the command
lvmdevices --adddev, and to prevent lvm from seeing or using a device,
remove it from the devices file with lvmdevices --deldev. The
vgimportdevices(8) command adds all PVs from a VG to the devices file,
and updates the VG metadata to include device IDs of the PVs.
.SS Listing devices
.
Run the lvmdevices command with no options or arguments to display the
entries in system.devices:
.br
.B lvmdevices
.P
Commands that add new devices to the devices file necessarily look outside
the existing devices file to find the devices being added. pvcreate,
vgcreate, and vgextend also look outside the devices file to create new
PVs and add those PVs to the devices file.
Each line begins with a current device name from the system, followed by
its device ID from the devices file, followed by other device details used by lvm.
A line begins with "Device none" if no device on the system matches the device ID.
(Viewing the system.devices file directly does not indicate if a device is present
on the system.)
.P
LVM records devices in the devices file using hardware-specific IDs, such
as the WWID, and attempts to use subsystem-specific IDs for virtual device
types (which also aim to be as unique and stable as possible.) These
device IDs are also written in the VG metadata. When no hardware or
virtual ID is available, lvm falls back using the unstable device name as
the device ID. When devnames are used as IDs, lvm performs extra scanning
to find devices if their devname changes, e.g. after reboot.
.SS Adding devices
.
To use a device with lvm, add it to the devices file with one of the
following commands.
.P
When proper device IDs are used, an lvm command will not look at devices
outside the devices file, but when devnames are used as a fallback, lvm
will scan devices outside the devices file to locate PVs on renamed
devices. A config setting search_for_devnames can be used to control the
scanning for renamed devname entries.
Add a device by referencing its device path:
.br
.B lvmdevices --adddev
.I device
.P
Related to the devices file, the command option --devices <devnames>
allows a list of devices to be specified for the command to use,
overriding the devices file. The listed devices act as a sort of devices
file in terms of limiting which devices lvm will see and use. Devices
that are not listed will appear to be missing to the lvm command.
Add a device by referencing its PVID:
.br
.B lvmdevices --addpvid
.I PVID
.P
Multiple devices files can be kept in \fI#DEFAULT_SYS_DIR#/devices\fP, which
allows lvm to be used with different sets of devices. For example, system
devices do not need to be exposed to a specific application, and the
application can use lvm on its own devices that are not exposed to the
system. The option --devicesfile <filename> is used to select the devices
file to use with the command. Without the option set, the default system
devices file is used.
Add a device by referencing its device ID:
.br
.B lvmdevices --addid
.I IDNAME
.B --deviceidtype
.I IDTYPE
.P
Setting --devicesfile "" causes lvm to not use a devices file.
Add all of the PVs in a VG:
.br
.B vgimportdevices
.I VG
.P
With no devices file, lvm will use any device on the system, and applies
the filter to limit the full set of system devices. With a devices file,
the regex filter is not used, and the filter settings in lvm.conf or the
command line are ignored. The vgimportdevices command is one exception
which does apply the regex filter when looking for a VG to import.
Add all of the PVs in all visible VGs:
.br
.B vgimportdevices -a
.P
If a devices file exists, lvm will use it, even if it's empty. An empty
devices file means lvm will see no devices.
.B pvcreate,
.B vgcreate,
and
.B vgextend
also look outside of the existing devices file to find the target device,
and automatically add it to the devices file.
.P
If the system devices file does not yet exist, the pvcreate or vgcreate
commands will create it if they see no existing VGs on the system.
lvmdevices --addev and vgimportdevices will always create a new devices file
if it does not yet exist.
.SS Removing devices
.
Removing a device from the devices file will prevent lvm from
seeing or using that device. Remove a device with one of the
following commands.
.P
It is recommended to use lvm commands to make changes to the devices file to
ensure proper updates.
Remove a device by referencing its device path:
.br
.B lvmdevices --deldev
.I device
.P
The device ID and device ID type are included in the VG metadata and can
be reported with pvs -o deviceid,deviceidtype. (Note that the lvmdevices
command does not update VG metadata, but subsequent lvm commands modifying
the metadata will include the device ID.)
Remove a device by referencing its PVID:
.br
.B lvmdevices --delpvid
.I PVID
.P
Possible device ID types are:
Remove a device by referencing its device ID:
.br
.B lvmdevices --delid
.I IDNAME
.B --deviceidtype
.I IDTYPE
.P
.SS device IDs
.
LVM identifies devices in the devices file using hardware-specific IDs,
such as the WWID or serial number. Subsystem-specific IDs are used for
virtual device types, which also aim to be unique and stable.
When no hardware or subsystem ID is available, lvm falls back using the
device name as the device ID. Using device names as IDs is not optimal
because they are not stable, and will often change after reboot. When
device names are used as IDs, lvm must perform extra device scanning
to locate devices if the device name changes.
.P
When stable device IDs are used, lvm will not access devices outside of
those listed in the devices file. When device names are used as IDs, lvm
will scan devices outside the devices file to locate PVs on devices that
changed names. The config setting search_for_devnames can be used to
control lvm's behavior in locating renamed devname entries.
.P
A device ID has two parts: an IDTYPE and an IDNAME.
.P
The IDTYPE specifies the origin of the ID, and the IDNAME is the
actual identifier. There is a predefined set of IDTYPEs listed
in the next section. A devices file entry must have one of these
ID types. When adding a device to the devices file, lvm automatically
chooses the best IDTYPE, which can be overridden with the --deviceidtype
option (this is not generally recommended.)
.P
To display all of the possible device IDs for a device, or the value
of one specific type, use the commands:
.P
.br
.B lvmdevices --listids
.I device
.br
.B lvmdevices --listids
.I device
.B --deviceidtype
.I IDTYPE
.P
.SS device ID types
.
The available device ID types are:
.br
.IP \[bu] 2
.B sys_wwid
@@ -309,38 +384,205 @@ is used for loop devices, the backing file name reported by sysfs.
.IP \[bu]
.B devname
the device name is used if no other type applies.
.IP \[bu]
.B nvme_uuid, nvme_nguid, nvme_eui64
are not generally used, but may appear for nvme devices that report
invalid wwid values.
.P
The default choice for device ID type can be overridden using lvmdevices
--addev --deviceidtype <type>. If the specified type is available for the
device it will be used, otherwise the device will be added using the type
that would otherwise be chosen.
.SS sysfs files
Most of the device ID types read the device ID value from sysfs.
Those sysfs values can also be read directly from the following paths:
.P
LVM commands run by dmeventd will use the devices file
\fI#DEFAULT_SYS_DIR#/devices/dmeventd.devices\fP if it exists,
otherwise system.devices is used. VGs that require the dmeventd
service should be included in system.devices, even if they are
included in dmeventd.devices.
.nf
/sys/dev/block/\fImajor\fP:\fIminor\fP/device/wwid
/sys/dev/block/\fImajor\fP:\fIminor\fP/device/serial
/sys/dev/block/\fImajor\fP:\fIminor\fP/wwid
/sys/dev/block/\fImajor\fP:\fIminor\fP/device/vpd_pg83 (binary)
/sys/dev/block/\fImajor\fP:\fIminor\fP/device/vpd_pg80 (binary)
/sys/dev/block/\fImajor\fP:\fIminor\fP/dm/uuid (lvm reads via ioctl)
/sys/dev/block/\fImajor\fP:\fIminor\fP/md/uuid
/sys/dev/block/\fImajor\fP:\fIminor\fP/loop/backing_file
.fi
.P
(Some sysfs values are modified before being used as the device ID,
e.g. spaces omitted or replaced with underscores.)
.P
.SS devices file contents
.
.SS Device ID refresh
.
A machine identifier is saved in the devices file, and is used to detect
when the devices file has been created by a different machine. If the
devices file was created by a different machine, it indicates that PVs may
have been copied or restored onto new devices on a new machine. In this
case, lvm will search for the PVs listed in system.devices on new devices.
If found, the device IDs will be updated in system.devices for the
existing PVIDs (assuming the original device IDs are also no longer
found.)
LVM writes some additional information to the devices file in addition to
the device IDs. LVM commands automatically update this information if it
changes. This includes the last known device name, and the PV UUID (PVID)
from the LVM disk header.
.P
The machine identifier used in system.devices will be either the DMI
product_uuid from
Check if the devices file content needs to be updated:
.br
.B lvmdevices --check
.P
Update devices file fields that are outdated:
.br
.B lvmdevices --update
.P
The devices file is meant to be edited by lvm commands, not by the user.
The devices file contains a HASH value which lvm uses to detect if the
file has been modified since lvm last wrote it.
When lvm updates the devices file, the previous version is moved to
/etc/lvm/devices/backup/.
.P
The following fields can be found in the devices file:
.br
VERSION: incremented for each file update.
.br
PRODUCT_UUID: a unique machine ID used to detect if the system.devices
file has been moved to a new machine, and may require updating.
When not available, HOSTNAME is used.
.P
Device entry fields:
.br
IDTYPE: indicates the source of the device ID value in IDNAME.
.br
IDNAME: the unique device ID value.
.br
DEVNAME: the most recent device name associated with the device ID.
.br
PVID: the LVM PV UUID from the LVM disk header.
.br
PART: the partition number if a PV exists on a partition.
.P
.SS device ID refresh
.
When lvm writes system.devices, it includes a local machine ID in the
system.devices file (as PRODUCT_UUID or HOSTNAME.) When lvm reads
system.devices, it compares this saved machine ID to the current machine,
which allows lvm to detect when system.devices has been copied or restored
onto a different machine. When a machine change is detected, lvm enables
a "device ID refresh" mode (configured by lvm.conf device_ids_refresh and
device_ids_refresh_checks.)
.P
In refresh mode, a device in system.devices that is not found by its device ID
will be located using its PVID. LVM will scan all devices on the system to
search for the missing PVIDs in system.devices. If a PVID is found on a
new device, the system.devices entry is updated with a new device ID matching
the new device on which the PVID was found. The refresh mode can be configured
to run once, when the machine change is first detected, or can be enabled
for period of time following the first refresh, or can be disabled
entirely.
.P
.B device_ids_refresh = 0
.br
Disables refresh mode.
.P
.B device_ids_refresh = 1
.br
Enables one attempt to refresh device IDs when a machine
change is first detected.
.P
.B device_ids_refresh =
.I seconds
.br
The refresh mode is enabled for this number of seconds
following the initial refresh attempt, or until all PVs
in system.devices are found. During this period, a
REFRESH_UNTIL line appears in system.devices. Accepted
values are 10-600 seconds.
.P
In addition to the automated device ID refresh mode, refresh
can be performed manually:
.P
Check if system.devices would be updated with new device IDs:
.br
.B lvmdevices --check --refresh
.P
Update system.devices with new device IDs if PVs are found on new devices:
.br
.B lvmdevices --update --refresh
.P
The machine ID used in system.devices will be either the DMI product_uuid from
.IR /sys/devices/virtual/dmi/id/product_uuid ,
or the hostname from
.BR uname (2).
See
.BR lvm.conf (5)
.B device_ids_refresh_checks to
configure this.
.B device_ids_refresh_checks
to configure this.
.P
.SS custom devices files
.
Multiple devices files can be kept in #DEFAULT_SYS_DIR#/devices, which
allows lvm to be used with different sets of devices. For example, a
given application may not need to access the system's devices, and the
system may not need to access the application's devices. In this case,
system.devices could list only the system's devices and
<application>.devices file could list only the application's devices. The
option --devicesfile <filename> is used to select the devices file to use
with the command. Without the option set, the default system.devices file
is used.
.P
If the special devices file \fI#DEFAULT_SYS_DIR#/devices/dmeventd.devices\fP
exists, then dmeventd uses dmeventd.devices instead of system.devices.
Using dmeventd.devices is necessary if VGs from separate devices files
require the services of dmeventd. In this case, dmeventd.devices should
list devices from all of the VGs that require dmeventd.
.P
.SS disabling and overriding
.
There are multiple ways that the devices file feature can be disabled
or overridden:
.P
.IP \[bu] 2
no system.devices
.br
If the system.devices file does not exist, then the devices file feature
is disabled.
.IP \[bu] 2
.B use_devicesfile=0
.br
If lvm.conf use_devicesfile is set to 0, then the devices file feature
is disabled, even if the system.devices file exists.
.br
.IP \[bu] 2
.B --devicesfile\ ""
.br
If an empty devices file name is specified on the command line, then
that command will not use a devices file.
.br
.IP \[bu] 2
.B --devices
.I device
.br
If specific devices are named on the command line with --devices,
then the command will not use a devices file, and will only access
the named devices.
.IP \[bu] 2
.B pvs -A
.br
If given the -A or --allpvs option, the \fBpvs\fP(8) command will
not use a devices file.
.P
When the devices file is disabled, lvm commands revert to using the
lvm.conf filter.
When the devices file is used, lvm commands ignore the lvm.conf
filter setting, except for vgimportdevices which does apply the
regex filter to the set of devices on the system when looking for
VGs to import to the devices file.
.P
.SS VG metadata
.
LVM commands that write VG metadata will include the device ID of each
PV in the VG metadata. The device ID can be displayed with the options:
.P
.B pvs -o deviceidtype,deviceid
.P
(Note that the lvmdevices command does not update VG metadata, but
subsequent lvm commands modifying the metadata will include the device
ID.)
.P
.SS creating the devices file
.P
If the system.devices file does not yet exist, the pvcreate or vgcreate
commands will create it only if they see no existing VGs on the system.
lvmdevices --adddev and vgimportdevices will always create a new devices file
if it does not yet exist.
.P
.
.SH USAGE
.
@@ -379,6 +621,10 @@ Update the devices file to fix incorrect values.
.O_update
.RS
[
.O_force
]
.br
[
.O_delnotfound
]
.br
@@ -448,6 +694,48 @@ Remove the devices file entry for the given PVID.
.RS
[ COMMON_OPTIONS ]
.RE
.
.P
\(em
.P
.
Find the device with the given device_id and add it to the devices file.
.P
.B lvmdevices
.O_addid
.O_deviceidtype
.RS
[ COMMON_OPTIONS ]
.RE
.
.P
\(em
.P
.
Remove the devices file entry with the given device_id.
.P
.B lvmdevices
.O_delid
.O_deviceidtype
.RS
[ COMMON_OPTIONS ]
.RE
.
.P
\(em
.P
.
Print device_id types and values available for the device.
.P
.B lvmdevices
.O_listids
.RS
[
.O_deviceidtype
]
.br
[ COMMON_OPTIONS ]
.RE
.P
\(em
.P
@@ -535,6 +823,10 @@ Common options for lvm:
Add a device to the devices file.
.
.TP
.O_addid
Find the device with the given device_id and add it to the devices file.
.
.TP
.O_addpvid
Find a device with the PVID and add the device to the devices file.
.
@@ -567,6 +859,10 @@ When used alone, --deldev specifies a device name.
When used with --deviceidtype, --deldev specifies a device id.
.
.TP
.O_delid
Remove the device with the specified device ID from the devices file.
.
.TP
.O_delnotfound
Remove devices file entries with no matching device.
.
@@ -601,6 +897,11 @@ If set to no, the command will not attempt to use device-mapper.
For testing and debugging.
.
.TP
.O_force
Override various checks, confirmations and protections.
Use with extreme caution.
.
.TP
.O_help
Display help text.
.
@@ -614,6 +915,10 @@ output: record the default command output.
debug: record full command debugging.
.
.TP
.O_listids
Print a list of device IDs available for the device.
.
.TP
.O_lockopt
Used to pass options for special cases to lvmlockd.
See \fBlvmlockd\fP(8) for more information.

View File

@@ -35,6 +35,19 @@ Note that this new process cannot support the original LVM1
type of on-disk metadata. Metadata can be converted using
\fBvgconvert\fP(8).
.P
By default, pvmove will mirror an entire LV segment at once. If the process
is interrupted (e.g. by a system crash or power failure) before the segment
is fully mirrored, the entire segment must be mirrored again when pvmove is
restarted. For very large segments, this can result in significant rework.
The \fBallocation/pvmove_max_segment_size_mb\fP setting in \fBlvm.conf\fP(5)
can be used to limit the maximum size of data mirrored in a single operation.
When set to a non-zero value, pvmove will split large segments into smaller
chunks of the specified size (in MiB), mirror each chunk, and update metadata
between chunks. This ensures that at most one chunk needs to be re-mirrored
after an interruption. For example, setting this to 10240 will limit each
mirroring operation to 10 GiB. The default value of 0 means no limit - entire
segments are mirrored at once.
.P
If the \fB--atomic\fP option is used, a slightly different approach is
used for the move. Again, a temporary 'pvmove' LV is created to store the
details of all the data movements required. This temporary LV contains

View File

@@ -25,8 +25,10 @@ expect_failure() {
check_daemon_in_builddir() {
# skip if we don't have our own daemon...
[[ -z "${installed_testsuite+varset}" ]] && \
(which "$1" 2>/dev/null | grep "$abs_builddir" >/dev/null ) || skip "$1 is not in executed path."
if [[ -z "${installed_testsuite+varset}" ]]; then
(which "$1" 2>/dev/null | grep -q "$abs_builddir") || \
skip "$1 is not in executed path."
fi
rm -f debug.log strace.log
}
@@ -145,7 +147,7 @@ prepare_lvmlockd() {
elif [[ "${LVM_TEST_LVMLOCKD_TEST_DLM:-0}" != 0 ]]; then
# make check_lvmlockd_test
echo "Starting lvmlockd --test (dlm)."
lvmlockd --test -g dlm
lvmlockd --test -D -g dlm &
elif [[ "${LVM_TEST_LVMLOCKD_TEST_SANLOCK:-0}" != 0 ]]; then
# FIXME: add option for this combination of --test and sanlock
@@ -169,41 +171,8 @@ prepare_lvmlockd() {
fi
}
prepare_clvmd() {
[[ "${LVM_TEST_LOCKING:-0}" -ne 3 ]] && return # not needed
if pgrep clvmd ; then
skip "Cannot use fake cluster locking with real clvmd ($(pgrep clvmd)) running."
fi
check_daemon_in_builddir clvmd
[[ -e "$DM_DEV_DIR/control" ]] || dmsetup table >/dev/null # create control node
# skip if singlenode is not compiled in
(clvmd --help 2>&1 | grep "Available cluster managers" | grep "singlenode" >/dev/null) || \
skip "Compiled clvmd does not support singlenode for testing."
# lvmconf "activation/monitoring = 1"
local run_valgrind=""
[[ "${LVM_VALGRIND_CLVMD:-0}" -eq 0 ]] || run_valgrind="run_valgrind"
rm -f "$CLVMD_PIDFILE"
echo "<======== Starting CLVMD ========>"
echo -n "## preparing clvmd..."
# lvs is executed from clvmd - use our version
LVM_LOG_FILE_EPOCH=CLVMD LVM_LOG_FILE_MAX_LINES=1000000 $run_valgrind clvmd -Isinglenode -d 1 -f &
echo $! > LOCAL_CLVMD
for i in {200..0} ; do
[[ "$i" -eq 0 ]] && die "Startup of clvmd is too slow."
[[ -e "$CLVMD_PIDFILE" && -e "${CLVMD_PIDFILE%/*}/lvm/clvmd.sock" ]] && break
echo -n .
sleep .1
done
echo ok
}
prepare_dmeventd() {
[[ -n "$RUNNING_DMEVENTD" ]] && skip "Cannot test dmeventd with real dmeventd ($RUNNING_DMEVENTD) running."
[[ -n "${RUNNING_DMEVENTD-}" ]] && skip "Cannot test dmeventd with real dmeventd ($RUNNING_DMEVENTD) running."
check_daemon_in_builddir dmeventd
lvmconf "activation/monitoring = 1"
@@ -247,23 +216,45 @@ prepare_lvmpolld() {
lvmpolld_talk() {
local use=nc
local socket="$TESTDIR/lvmpolld.socket"
local cmd
local result
local rc
# Determine which tool to use
if type -p socat >& /dev/null; then
use=socat
elif echo | not nc -U "$TESTDIR/lvmpolld.socket" ; then
echo "WARNING: Neither socat nor nc -U seems to be available." 1>&2
cmd=(socat "unix-connect:$socket" -)
elif type -p nc >& /dev/null; then
cmd=(nc -U "$socket")
else
echo "WARNING: Neither socat nor nc seems to be available." 1>&2
echo "## failed to contact lvmpolld."
return 1
fi
if [[ "$use" = nc ]]; then
nc -U "$TESTDIR/lvmpolld.socket"
else
socat "unix-connect:$TESTDIR/lvmpolld.socket" -
fi | tee -a lvmpolld-talk.txt
# Try to connect with unified error handling
if ! result=$("${cmd[@]}" 2>&1); then
rc=$?
# Check what kind of failure
if [[ ! -S "$socket" ]]; then
echo "WARNING: lvmpolld socket does not exist at $socket" 1>&2
echo "## lvmpolld may have shut down or not started properly." 1>&2
elif [[ "$result" == *"No such file"* ]]; then
echo "WARNING: lvmpolld socket disappeared during connection attempt" 1>&2
echo "## lvmpolld shut down while trying to connect." 1>&2
else
echo "WARNING: Failed to connect to lvmpolld (rc=$rc): $result" 1>&2
fi
echo "## failed to contact lvmpolld."
return 1
fi
echo "$result" | tee -a lvmpolld-talk.txt
}
lvmpolld_dump() {
(echo 'request="dump"'; echo '##') | lvmpolld_talk "$@"
(echo 'request="dump"'; echo '##') | lvmpolld_talk
}
prepare_lvmdbusd() {
@@ -426,7 +417,7 @@ teardown_devs_prefixed() {
for dm in $(dm_info name,open --separator ';' --nameprefixes --unquoted --sort open,"$sortby" -S "name=~$prefix || uuid=~$prefix" --mangle none || true) ; do
[[ "$dm" != "No devices found" ]] || break 2
eval "$dm"
eval "$dm" 2>/dev/null
local force="-f"
if [[ "$i" = 0 ]]; then
if [[ "$once" = 1 ]]; then
@@ -477,7 +468,7 @@ teardown_devs() {
fi
# NOTE: SCSI_DEBUG_DEV test must come before the LOOP test because
# prepare_scsi_debug_dev() also sets LOOP to short-circuit prepare_loop()
# aux prepare_scsi_debug_dev() also sets LOOP to short-circuit aux prepare_loop()
if [[ -f SCSI_DEBUG_DEV ]]; then
udev_wait
if [[ "${LVM_TEST_PARALLEL:-0}" -ne 1 ]]; then
@@ -510,21 +501,27 @@ teardown_devs() {
}
kill_sleep_kill_() {
local pid=()
local pidfile=$1
local slow=$2
local pid
local sleep_time="0.05"
if [[ -s "$pidfile" ]]; then
pid=( $(< "$pidfile") )
rm -f "$pidfile"
[[ "$pidfile" = "LOCAL_LVMDBUSD" ]] && killall -9 lvmdbusd || true
kill -TERM "${pid[@]}" 2>/dev/null || return 0
for i in {0..10} ; do
ps "${pid[@]}" >/dev/null || return 0
if [[ "$slow" -eq 0 ]]; then sleep .2 ; else sleep 1 ; fi
kill -KILL "${pid[@]}" 2>/dev/null || true
done
fi
[[ ! -s "$pidfile" ]] && return 0
# Normal: 40 * 0.05 = 2 seconds, Valgrind 40 x 0.2s = 8 seconds
[[ "$2" -eq 0 ]] || sleep_time="0.2"
pid=( $(< "$pidfile") ) || true
rm -f "$pidfile" || true
[[ "$pidfile" = "LOCAL_LVMDBUSD" ]] && killall -9 lvmdbusd || true
kill -TERM "${pid[@]}" 2>/dev/null || return 0
# Give process time to shut down gracefully
for i in {0..40} ; do
ps "${pid[@]}" >/dev/null || return 0
sleep "$sleep_time"
done
# After timeout, use SIGKILL as last resort
kill -KILL "${pid[@]}" 2>/dev/null || true
}
print_procs_by_tag_() {
@@ -547,18 +544,19 @@ kill_tagged_processes() {
kill -TERM "$pid" 2>/dev/null || true
fi
pids+=( "$pid" )
done < <(print_procs_by_tag_ "$@")
done < <(print_procs_by_tag_ "${@-}")
[[ ${#pids[@]} -eq 0 ]] && return
# wait if process exited and eventually -KILL
wait=0
local wait_count=0
for pid in "${pids[@]}" ; do
while ps "$pid" > /dev/null && "$wait" -le 10; do
wait_count=0
while ps "$pid" > /dev/null && [[ "$wait_count" -le 10 ]]; do
sleep .2
wait=$(( wait + 1 ))
wait_count=$(( wait_count + 1 ))
done
[[ "$wait" -le 10 ]] || kill -KILL "$pid" 2>/dev/null || true
[[ "$wait_count" -le 10 ]] || kill -KILL "$pid" 2>/dev/null || true
done
}
@@ -605,10 +603,6 @@ teardown() {
echo -n .
kill_sleep_kill_ LOCAL_CLVMD "${LVM_VALGRIND_CLVMD:-0}"
echo -n .
kill_sleep_kill_ LOCAL_DMEVENTD "${LVM_VALGRIND_DMEVENTD:-0}"
echo -n .
@@ -644,7 +638,7 @@ teardown() {
# Check if this test is leaking some 'symlinks' with our name (udev)
LEAKED_LINKS=( $(find /dev -path "/dev/mapper/${PREFIX}*" -type l -exec test ! -e {} \; -print -o \
-path "/dev/${PREFIX}*/" -type l -exec test ! -e {} \; -print 2>/dev/null || true) )
-path "/dev/${PREFIX}*/" -type l -exec test ! -e {} \; -print 2>/dev/null) ) || true
[[ "${#LEAKED_LINKS[@]}" -eq 0 ]] || echo "## removing stray symlinks the names beginning with ${PREFIX}"
@@ -662,7 +656,7 @@ teardown() {
find /dev -type d -name "${LEAKED_PREFIX}*" -empty -delete 2>/dev/null || true
# Fail test with leaked links as most likely somewhere is missing synchronization...
[[ "${#LEAKED_LINKS[@]}" -eq 0 ]] || die "Test leaked these symlinks ${LEAKED_LINKS[@]}"
[[ "${#LEAKED_LINKS[@]}" -eq 0 ]] || die "Test leaked these symlinks ${LEAKED_LINKS[*]}"
}
prepare_loop() {
@@ -741,7 +735,7 @@ prepare_real_devs() {
if [[ -n "${LVM_TEST_DEVICE_LIST-}" ]]; then
local count=0
while read path; do
while read -r path; do
REAL_DEVICES[count]=$path
count=$(( count + 1 ))
extend_filter "a|$path|"
@@ -860,7 +854,7 @@ mdadm_create() {
}
mdadm_assemble() {
STRACE=
local STRACE=
mdadm -V 2>&1 | grep " v3.2" && {
# use this 'trick' to slow down mdadm which otherwise
# is racing with udev rule since mdadm internally
@@ -991,7 +985,7 @@ clear_devs() {
touch NO_BLKDISCARD_Z
fi
dd if=/dev/zero of="$1" bs=512K oflag=direct $seek $count || true
dd if=/dev/zero of="$1" bs=512K oflag=direct $seek $count 2>/dev/null || true
;;
esac
shift
@@ -1004,17 +998,15 @@ clear_devs() {
# $2 string/pattern search for corruption
# $3 string/pattern replacing/corrupting
corrupt_dev() {
local a
local position
# search for string on a file
# Note: returned string may possibly start with other ASCII chars
# a[0] is position in file, a[1] is the actual string
a=( $(strings -t d -n 64 "$1" | grep -m 1 "$2") ) || true
# Find byte offset of the pattern in file
position=$(grep -oba -m 1 -F "$2" "$1" | head -n 1 | cut -d: -f1) || true
[[ -n "${a[0]-}" ]] || return 0
[[ -n "$position" ]] || return 0
# Seek for the sequence and replace it with corruption pattern
echo -n "${a[1]/$2/$3}" | LANG=C dd of="$1" bs=1 seek="${a[0]}" conv=fdatasync
# Seek to the position and replace with corruption pattern
echo -n "$3" | LANG=C dd of="$1" bs=1 seek="$position" conv=notrunc,fdatasync 2>/dev/null
}
prepare_backing_dev() {
@@ -1642,11 +1634,14 @@ generate_config() {
declare -A CONF 2>/dev/null || {
# Associative arrays is not available
local s
for s in $(cut -f1 -d/ "$config_values" | sort | uniq); do
for s in $(cut -f1 -d/ "$config_values" | sort -u); do
echo "$s {"
local k
for k in $(grep ^"$s"/ "$config_values" | cut -f1 -d= | sed -e 's, *$,,' | sort | uniq); do
grep "^${k}[ \t=]" "$config_values" | tail -n 1 | sed -e "s,^$s/, ," || true
# $(grep ^"$s"/ "$config_values" | cut -f1 -d= | sed -e 's, *$,,' | sort | uniq)
for k in $(awk -F= -v s="$s" '$0 ~ "^" s "/" {sub(/ *$/, "", $1); print $1}' "$config_values" | sort -u); do
# grep "^${k}[ \t=]" "$config_values" | tail -n 1 | sed -e "s,^$s/, ," || true
# single command with '|' as delimiter
sed -n "\|^${k}[ \t=]|h;\${g;s|^$s/| |p}" "$config_values" || true
done
echo "}"
echo
@@ -1798,7 +1793,7 @@ thin_restore_needs_more_volumes() {
udev_wait() {
local arg="--timeout=15"
[[ -n "${1-}" ]] && arg="--exit-if-exists=$1"
[[ -n "${1-}" ]] && arg="--exit-if-exists=${1-}"
if [[ ! -f UDEV_PID ]]; then
pgrep udev >UDEV_PID 2>/dev/null || return 0

View File

@@ -201,7 +201,7 @@ in_sync() {
local ignore_a=${3:-0}
local dm_name="$1-$2"
a=( $(dmsetup status "$dm_name") ) || \
a=( $(dmsetup status "$dm_name") ) || \
die "Unable to get sync status of $1"
if [[ "${a[2]}" = "snapshot-origin" ]]; then
@@ -443,7 +443,8 @@ raid_leg_status() {
# Ignore inconsistent raid status 0/xxxxx idle
for i in {100..0} ; do
st=( $(dmsetup status --noflush "$1-$2") ) || die "Unable to get status of $vg/$lv1"
st=( $(dmsetup status --noflush "$1-$2") ) || \
die "Unable to get status of $vg/$lv1"
case "${st[7]}" in
"resync"|"recover") [ "${st[5]}" = "$3" ] && return 0 ;;
esac

View File

@@ -91,18 +91,12 @@ LVM_TEST_LOCK_TYPE_DLM=${LVM_TEST_LOCK_TYPE_DLM:-0}
LVM_TEST_LOCK_TYPE_SANLOCK=${LVM_TEST_LOCK_TYPE_SANLOCK:-0}
LVM_TEST_LOCK_TYPE_IDM=${LVM_TEST_LOCK_TYPE_IDM:-0}
SKIP_WITHOUT_CLVMD=${SKIP_WITHOUT_CLVMD:-0}
SKIP_WITH_CLVMD=${SKIP_WITH_CLVMD:-0}
SKIP_WITH_LOW_SPACE=${SKIP_WITH_LOW_SPACE-50}
[[ -n "$LVM_TEST_FLAVOUR" ]] || { echo "NOTE: Empty flavour">&2; initskip; }
[[ -f "lib/flavour-$LVM_TEST_FLAVOUR" ]] || { echo "NOTE: Flavour '$LVM_TEST_FLAVOUR' does not exist">&2; initskip; }
. "lib/flavour-$LVM_TEST_FLAVOUR"
[[ "$SKIP_WITHOUT_CLVMD" != 0 && "$LVM_TEST_LOCKING" -ne 3 ]] && initskip
[[ "$SKIP_WITH_CLVMD" != 0 && "$LVM_TEST_LOCKING" = 3 ]] && initskip
# When requested testing LVMLOCKD & LVMPOLLD - ignore skipping of marked test for lvmpolld
[[ "$LVM_TEST_LVMLOCKD" != 0 && "$LVM_TEST_LVMPOLLD" != 0 ]] && SKIP_WITH_LVMPOLLD=0
@@ -142,7 +136,7 @@ if [[ "$SKIP_ROOT_DM_CHECK" -eq 0 ]]; then
case "$d" in
"No devices found") ;;
"") ;;
*) die "DM table already has either suspended or $PREFIX prefixed devices: $d" ;;
*) skip "DM table already has either suspended or $PREFIX prefixed devices: $d" ;;
esac
fi

View File

@@ -141,7 +141,7 @@ STACKTRACE() {
local cores=()
local IFS=$IFS_NL
cores=( $(find . "$(dirname "$(sysctl -n kernel.core_pattern)")" \
"/var/lib/systemd/coredump/" -name 'core*' -newer TESTNAME 2>/dev/null || true ) )
"/var/lib/systemd/coredump/" -name 'core*' -newer TESTNAME 2>/dev/null) ) || true
for i in "${cores[@]-}"; do
bin=$(gdb -batch -c "$i" 2>&1 | grep "generated by" | \
@@ -263,13 +263,14 @@ skip() {
}
get_real_devs() {
REAL_DEVICES=( $(<REAL_DEVICES) )
local IFS=$IFS_NL
REAL_DEVICES=( $(< REAL_DEVICES) ) || true
export REAL_DEVICES
}
get_devs() {
local IFS=$IFS_NL
DEVICES=( $(<DEVICES) )
DEVICES=( $(< DEVICES) ) || true
export DEVICES
# local DEVS=( $(<DEVICES) )
# eval "$1"'=("${DEVS[@]}")'

View File

@@ -11,7 +11,6 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
SKIP_WITH_CLVMD=1
. lib/inittest --skip-with-lvmpolld

View File

@@ -0,0 +1,501 @@
#!/usr/bin/env bash
# Copyright (C) 2020-23 Red Hat, Inc. All rights reserved.
#
# 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 General Public License v.2.
#
# You should have received a copy of the GNU 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
test_description='refresh device ids if system changes'
. lib/inittest --skip-with-lvmpolld
aux lvmconf 'devices/scan = "/dev"'
aux prepare_devs 1
# The tests run with system dir of "/etc" but lvm when running
# normally has cmd->system_dir set to "/etc/lvm".
DFDIR="$LVM_SYSTEM_DIR/devices"
mkdir -p "$DFDIR" || true
DF="$DFDIR/system.devices"
# requires trailing / to match dm
SYS_DIR="$PWD/test/sys"
aux lvmconf "devices/use_devicesfile = 1" \
"devices/device_id_sysfs_dir = \"$SYS_DIR/\"" \
"devices/device_ids_refresh = 10"
losetup -h | grep sector-size || skip
which fallocate || skip
FILE1="lvmloopfile1"
FILE2="lvmloopfile2"
FILE3="lvmloopfile3"
FILE4="lvmloopfile4"
create_loops() {
fallocate -l 2M "$FILE1"
fallocate -l 2M "$FILE2"
fallocate -l 2M "$FILE3"
fallocate -l 2M "$FILE4"
for i in {1..5} ; do
LOOP1=$(losetup -f "$FILE1" --show || true)
test -n "$LOOP1" && break
done
for i in {1..5} ; do
LOOP2=$(losetup -f "$FILE2" --show || true)
test -n "$LOOP2" && break
done
for i in {1..5} ; do
LOOP3=$(losetup -f "$FILE3" --show || true)
test -n "$LOOP3" && break
done
for i in {1..5} ; do
LOOP4=$(losetup -f "$FILE4" --show || true)
test -n "$LOOP4" && break
done
}
remove_loops() {
losetup -D
rm "$FILE1"
rm "$FILE2"
rm "$FILE3"
rm "$FILE4"
}
create_pvs() {
# First two loop devs are original PVs.
pvcreate --devices "$LOOP1" "$LOOP1"
pvcreate --devices "$LOOP2" "$LOOP2"
eval "$(pvs --noheading --nameprefixes -o major,minor,uuid --devices "$LOOP1" "$LOOP1")"
MAJOR1=$LVM2_PV_MAJOR
MINOR1=$LVM2_PV_MINOR
OPVID1=$LVM2_PV_UUID
PVID1=${OPVID1//-/}
eval "$(pvs --noheading --nameprefixes -o major,minor,uuid --devices "$LOOP2" "$LOOP2")"
MAJOR2=$LVM2_PV_MAJOR
MINOR2=$LVM2_PV_MINOR
OPVID2=$LVM2_PV_UUID
PVID2=${OPVID2//-/}
# Second two loop devs are not originally PVs.
# Used to move original PVs to new devices.
# (pvcreate is temporarily used so pvs can report MAJOR/MINOR)
pvcreate --devices "$LOOP3" "$LOOP3"
pvcreate --devices "$LOOP4" "$LOOP4"
eval "$(pvs --noheading --nameprefixes -o major,minor,uuid --devices "$LOOP3" "$LOOP3")"
MAJOR3=$LVM2_PV_MAJOR
MINOR3=$LVM2_PV_MINOR
eval "$(pvs --noheading --nameprefixes -o major,minor,uuid --devices "$LOOP4" "$LOOP4")"
MAJOR4=$LVM2_PV_MAJOR
MINOR4=$LVM2_PV_MINOR
pvremove --devices "$LOOP3" "$LOOP3"
pvremove --devices "$LOOP4" "$LOOP4"
dd if="$LOOP1" of=pvheader1 bs=1M count=1
dd if="$LOOP2" of=pvheader2 bs=1M count=1
}
remove_pvs() {
rm pvheader1
rm pvheader2
}
PRODUCT_UUID1="11111111-2222-3333-4444-555555555555"
PRODUCT_UUID2="11111111-2222-3333-4444-666666666666"
create_sysfs() {
mkdir -p "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/loop"
mkdir -p "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/loop"
mkdir -p "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/loop"
mkdir -p "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/loop"
mkdir -p "$SYS_DIR/devices/virtual/dmi/id/"
}
remove_sysfs() {
rm -rf "$SYS_DIR"
}
cleanup_and_teardown()
{
remove_sysfs
remove_loops
remove_pvs
aux teardown
}
use_12() {
losetup -D
losetup "$LOOP1" "$FILE1"
losetup "$LOOP2" "$FILE2"
losetup "$LOOP3" "$FILE3"
losetup "$LOOP4" "$FILE4"
dd if=pvheader1 of="$LOOP1" bs=1M count=1
dd if=pvheader2 of="$LOOP2" bs=1M count=1
aux wipefs_a "$LOOP3"
aux wipefs_a "$LOOP4"
losetup -d "$LOOP3"
losetup -d "$LOOP4"
rm "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/loop/backing_file"
rm "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/loop/backing_file"
echo "$FILE1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/loop/backing_file"
echo "$FILE2" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/loop/backing_file"
}
use_34() {
losetup -D
losetup "$LOOP1" "$FILE1"
losetup "$LOOP2" "$FILE2"
losetup "$LOOP3" "$FILE3"
losetup "$LOOP4" "$FILE4"
dd if=pvheader1 of="$LOOP3" bs=1M count=1
dd if=pvheader2 of="$LOOP4" bs=1M count=1
aux wipefs_a "$LOOP1"
aux wipefs_a "$LOOP2"
losetup -d "$LOOP1"
losetup -d "$LOOP2"
rm "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/loop/backing_file"
rm "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/loop/backing_file"
echo "$FILE3" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/loop/backing_file"
echo "$FILE4" > "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/loop/backing_file"
}
detach_1() {
losetup -d "$LOOP1"
rm "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/loop/backing_file"
}
attach_1() {
losetup "$LOOP1" "$FILE1"
echo "$FILE1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/loop/backing_file"
}
detach_2() {
losetup -d "$LOOP2"
rm "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/loop/backing_file"
}
attach_2() {
losetup "$LOOP2" "$FILE2"
echo "$FILE2" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/loop/backing_file"
}
detach_3() {
losetup -d "$LOOP3"
rm "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/loop/backing_file"
}
attach_3() {
losetup "$LOOP3" "$FILE3"
echo "$FILE3" > "$SYS_DIR/dev/block/$MAJOR3:$MINOR3/loop/backing_file"
}
detach_4() {
losetup -d "$LOOP4"
rm "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/loop/backing_file"
}
attach_4() {
losetup "$LOOP4" "$FILE4"
echo "$FILE4" > "$SYS_DIR/dev/block/$MAJOR4:$MINOR4/loop/backing_file"
}
DFDIR="$LVM_SYSTEM_DIR/devices"
mkdir -p "$DFDIR" || true
DF="$DFDIR/system.devices"
ORIG="$DFDIR/orig.devices"
trap 'cleanup_and_teardown' EXIT
remove_sysfs
create_loops
create_pvs
create_sysfs
losetup -D
########################################################################
# initial state:
# system is UUID1
# PV1 on LOOP1
# PV2 on LOOP2
# no LOOP3 or LOOP4 exist
echo "$PRODUCT_UUID1" > "$SYS_DIR/devices/virtual/dmi/id/product_uuid"
echo "$FILE1" > "$SYS_DIR/dev/block/$MAJOR1:$MINOR1/loop/backing_file"
echo "$FILE2" > "$SYS_DIR/dev/block/$MAJOR2:$MINOR2/loop/backing_file"
losetup "$LOOP1" "$FILE1"
losetup "$LOOP2" "$FILE2"
touch "$DF"
lvmdevices --adddev "$LOOP1"
lvmdevices --adddev "$LOOP2"
cat "$DF"
grep "$LOOP1" "$DF"
grep "$LOOP2" "$DF"
not grep "$LOOP3" "$DF"
not grep "$LOOP4" "$DF"
grep "$FILE1" "$DF"
grep "$FILE2" "$DF"
not grep "$FILE3" "$DF"
not grep "$FILE4" "$DF"
########################################################################
# system changes from UUID1 to UUID2
# on new system:
# PV1 is on LOOP3
# PV2 is on LOOP4
# no LOOP1 or LOOP2 exist
echo "$PRODUCT_UUID2" > "$SYS_DIR/devices/virtual/dmi/id/product_uuid"
use_34
# initial refresh trigger finds both, no REFRESH_UNTIL needed
pvs -o+uuid | tee out
cat "$DF"
grep "$OPVID1" out
grep "$OPVID2" out
grep "$LOOP3" out
grep "$LOOP4" out
grep "$PVID1" "$DF"
grep "$PVID2" "$DF"
grep "$LOOP3" "$DF"
grep "$LOOP4" "$DF"
grep "$FILE3" "$DF"
grep "$FILE4" "$DF"
grep "$PRODUCT_UUID2" "$DF"
not grep REFRESH_UNTIL "$DF"
########################################################################
# system changes from UUID2 to UUID1
# on new system:
# PV1 is on LOOP1
# PV2 is on LOOP2
# no LOOP3 or LOOP4 exist
# PV2 appears after delay
echo "$PRODUCT_UUID1" > "$SYS_DIR/devices/virtual/dmi/id/product_uuid"
use_12
# will be attached after a delay
detach_2
# initial refresh trigger finds only PV1
pvs -o+uuid | tee out
cat "$DF"
grep "$OPVID1" out
grep "$LOOP1" out
not grep "$OPVID2" out
not grep "$LOOP2" out
# new device ID is shown for PV1
grep "$PVID1" "$DF" | tee line1
grep "$LOOP1" line1
grep "$FILE1" line1
# old device ID still shown for PV2
grep "$PVID2" "$DF" | tee line2
grep "$LOOP4" line2
grep "$FILE4" line2
grep "$PRODUCT_UUID1" "$DF"
grep REFRESH_UNTIL "$DF"
# attach after a delay less than refresh period
sleep 1
attach_2
# second refresh finds both
pvs -o+uuid | tee out
cat "$DF"
grep "$OPVID1" out
grep "$LOOP1" out
grep "$OPVID2" out
grep "$LOOP2" out
# unchanged device ID for PV1
grep "$PVID1" "$DF" | tee line1
grep "$LOOP1" line1
grep "$FILE1" line1
# new devie ID now shown for PV2
grep "$PVID2" "$DF" | tee line2
grep "$LOOP2" line2
grep "$FILE2" line2
grep "$PRODUCT_UUID1" "$DF"
not grep REFRESH_UNTIL "$DF"
########################################################################
# system changes from UUID1 to UUID2
# on new system:
# PV1 is on LOOP3
# PV2 is on LOOP4
# no LOOP1 or LOOP2 exist
# PV1 and PV2 appear after delay
echo "$PRODUCT_UUID2" > "$SYS_DIR/devices/virtual/dmi/id/product_uuid"
use_34
# will be attached after a delay
detach_3
detach_4
# initial refresh trigger finds none
pvs -o+uuid | tee out
cat "$DF"
not grep "$OPVID1" out
not grep "$LOOP3" out
not grep "$OPVID2" out
not grep "$LOOP4" out
# old device ID still shown for PV1
grep "$PVID1" "$DF" | tee line1
grep "$LOOP1" line1
grep "$FILE1" line1
# old device ID still shown for PV2
grep "$PVID2" "$DF" | tee line2
grep "$LOOP2" line2
grep "$FILE2" line2
grep "$PRODUCT_UUID2" "$DF"
grep REFRESH_UNTIL "$DF"
# attach after a delay less than refresh period
sleep 1
attach_3
attach_4
# second refresh finds both
pvs -o+uuid | tee out
cat "$DF"
grep "$OPVID1" out
grep "$LOOP3" out
grep "$OPVID2" out
grep "$LOOP4" out
# new devie ID now shown for PV1
grep "$PVID1" "$DF" | tee line1
grep "$LOOP3" line1
grep "$FILE3" line1
# new devie ID now shown for PV2
grep "$PVID2" "$DF" | tee line2
grep "$LOOP4" line2
grep "$FILE4" line2
not grep REFRESH_UNTIL "$DF"
########################################################################
# system changes from UUID2 to UUID1
# on new system:
# PV1 is on LOOP1
# PV2 is on LOOP2
# no LOOP3 or LOOP4 exist
# PV1 appears after delay < 10s
# PV2 appears after delay > 10s, not seen by 'pvs' until forced refresh
echo "$PRODUCT_UUID1" > "$SYS_DIR/devices/virtual/dmi/id/product_uuid"
use_12
# will be attached after a delay
detach_1
detach_2
# initial refresh trigger finds none
pvs -o+uuid | tee out
cat "$DF"
not grep "$OPVID1" out
not grep "$LOOP3" out
not grep "$OPVID2" out
not grep "$LOOP4" out
# old device ID still shown for PV1
grep "$PVID1" "$DF" | tee line1
grep "$LOOP3" line1
grep "$FILE3" line1
# old device ID still shown for PV2
grep "$PVID2" "$DF" | tee line2
grep "$LOOP4" line2
grep "$FILE4" line2
grep "$PRODUCT_UUID1" "$DF"
grep REFRESH_UNTIL "$DF"
# attach 1 after a delay less than refresh period
sleep 1
attach_1
# second refresh finds PV1
pvs -o+uuid | tee out
cat "$DF"
grep "$OPVID1" out
grep "$LOOP1" out
not grep "$OPVID2" out
not grep "$LOOP2" out
# new devie ID now shown for PV1
grep "$PVID1" "$DF" | tee line1
grep "$LOOP1" line1
grep "$FILE1" line1
# old devie ID still shown for PV2
grep "$PVID2" "$DF" | tee line2
grep "$LOOP4" line2
grep "$FILE4" line2
grep REFRESH_UNTIL "$DF"
# attach PV2 after a delay larger than refresh period
sleep 10
attach_2
# refresh period expired, so pvs will not refresh and still
# doesn't see 2
pvs -o+uuid | tee out
cat "$DF"
grep "$OPVID1" out
grep "$LOOP1" out
not grep "$OPVID2" out
not grep "$LOOP2" out
# old devie ID still shown for PV2
grep "$PVID2" "$DF" | tee line2
grep "$LOOP4" line2
grep "$FILE4" line2
# refresh expired, so removed from DF
not grep REFRESH_UNTIL "$DF"
# forced refresh now finds 2
lvmdevices --update --refresh
pvs -o+uuid | tee out
cat "$DF"
grep "$OPVID1" out
grep "$LOOP1" out
grep "$OPVID2" out
grep "$LOOP2" out
# new devie ID now shown for PV2
grep "$PVID2" "$DF" | tee line2
grep "$LOOP2" line2
grep "$FILE2" line2

View File

@@ -23,6 +23,7 @@ test "$DM_DEV_DIR" = "/dev" || skip "Only works with /dev access -> make check L
SYS_DIR="$PWD/test/sys"
aux lvmconf "devices/use_devicesfile = 1" \
"devices/device_id_sysfs_dir = \"$SYS_DIR/\"" \
"devices/device_ids_refresh = 1" \
'devices/global_filter = [ "a|.*|" ]' \
"global/event_activation = 1"

View File

@@ -64,9 +64,9 @@ check lv_field $vg/3way seg_monitor "monitored"
check lv_field $vg/4way seg_monitor "monitored"
lvchange --monitor y --verbose $vg/3way 2>&1 | tee lvchange.out
# only non-cluster tests can check command result
test -e LOCAL_CLVMD || grep 'already monitored' lvchange.out
grep 'already monitored' lvchange.out
lvchange --monitor y --verbose $vg/4way 2>&1 | tee lvchange.out
test -e LOCAL_CLVMD || grep 'already monitored' lvchange.out
grep 'already monitored' lvchange.out
# now try what happens if no dmeventd is running
pid=$(< LOCAL_DMEVENTD)
@@ -105,10 +105,10 @@ pgrep -o dmeventd >LOCAL_DMEVENTD
check lv_field $vg/4way seg_monitor "not monitored"
lvchange --monitor y --verbose $vg/3way 2>&1 | tee lvchange.out
test -e LOCAL_CLVMD || not grep 'already monitored' lvchange.out
not grep 'already monitored' lvchange.out
lvchange --monitor y --verbose $vg/$lv2 2>&1 | tee lvchange.out
test -e LOCAL_CLVMD || not grep 'already monitored' lvchange.out
not grep 'already monitored' lvchange.out
_restart_dmeventd

View File

@@ -42,6 +42,7 @@ for j in empty existing ; do
rm -f cmdout
"$i" "$dev1" "$DMTEST" "TEST-${PREFIX}-secure" >cmdout 2>&1 &
PID=$!
SECURE_TEST_PID=$PID
for k in $(seq 1 20); do
sleep .1
lines=$(wc -l < cmdout 2>/dev/null || true)
@@ -60,7 +61,7 @@ gcore "$PID" | tee out || skip
# check we capture core while dmsecuretest was already sleeping
grep -e "nanosleep\|kernel_vsyscall\|internal_syscall_cancel" out
kill "$PID" || true
wait
wait "$SECURE_TEST_PID" || true
cat cmdout

View File

@@ -21,8 +21,6 @@ flatten() {
done
}
# clvmd might not be started fast enough and
# lvm still activates locking for all commands.
# FIXME: Either make longer start delay,
# or even better do not initialize
# locking for commands like 'dumpconfig'

View File

@@ -366,7 +366,7 @@ vgs -o+uuid |tee out
grep $vg1 out
grep $UUID1 out
grep $UUID2 out
not group $UUID3 out
not grep $UUID3 out
vgs --foreign -o+uuid |tee out
grep $vg1 out
grep $UUID1 out
@@ -443,8 +443,8 @@ vgs -o+uuid |tee out
grep $vg1 out
grep $UUID1 out
grep $UUID2 out
not group $UUID3 out
not group $UUID4 out
not grep $UUID3 out
not grep $UUID4 out
vgs --foreign -o+uuid |tee out
grep $vg1 out
grep $UUID1 out
@@ -527,9 +527,9 @@ grep $vg1 out
grep $UUID1 out
grep $UUID2 out
grep $UUID3 out
not group $UUID4 out
not group $UUID5 out
not group $UUID6 out
not grep $UUID4 out
not grep $UUID5 out
not grep $UUID6 out
vgs --foreign -o+uuid |tee out
grep $vg1 out
grep $UUID1 out

View File

@@ -37,7 +37,7 @@ _prepare_vg() {
}
_test1() {
mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1"
mkfs.ext4 -b 4096 "$DM_DEV_DIR/$vg/$lv1"
mount "$DM_DEV_DIR/$vg/$lv1" "$mnt"
@@ -82,7 +82,7 @@ _test1() {
}
_test2() {
mkfs.ext4 "$DM_DEV_DIR/$vg/$lv1"
mkfs.ext4 -b 4096 "$DM_DEV_DIR/$vg/$lv1"
mount "$DM_DEV_DIR/$vg/$lv1" "$mnt"

View File

@@ -12,7 +12,6 @@
test_description='test some blocking / non-blocking multi-vg operations'
SKIP_WITH_CLVMD=1
. lib/inittest --skip-with-lvmpolld

View File

@@ -32,6 +32,7 @@ aux delay_dev "$dev1" 50 50 "$(get first_extent_sector "$dev1"):"
test -f HAVE_DM_DELAY || skip "delay_dev is missing"
lvresize -L-5 -r $vg/$lv1 &
LVRESIZE_PID=$!
# Let's wait till resize starts
for i in $(seq 1 300); do
@@ -41,7 +42,7 @@ done
lvremove -f $vg/$lv2
wait
wait "$LVRESIZE_PID" || true
aux enable_dev "$dev1"

View File

@@ -18,7 +18,6 @@
# Current support for syncaction in cluster is broken
# might get fixed one day though
# meanwhile skipped
SKIP_WITH_CLVMD=1
. lib/inittest --skip-with-lvmpolld

View File

@@ -13,7 +13,6 @@
# FIXME RESYNC doesn't work in cluster with exclusive activation
# seriously broken!
SKIP_WITH_CLVMD=1
. lib/inittest --skip-with-lvmpolld

View File

@@ -339,7 +339,7 @@ TEST_TYPES="- snapshot"
# thinpool works EX in cluster
# but they don't work together in a cluster yet
# (nor does thinpool+mirror work in a cluster yet)
test ! -e LOCAL_CLVMD && aux have_thin 1 8 0 && TEST_TYPE="$TEST_TYPES thinpool_data thinpool_meta"
aux have_thin 1 8 0 && TEST_TYPE="$TEST_TYPES thinpool_data thinpool_meta"
# Implicit test for 'raid1' only
if test "${TEST_RAID:-raid1}" = raid1 ; then

View File

@@ -18,7 +18,6 @@
# Current support for syncaction in cluster is broken
# might get fixed one day though
# meanwhile skipped
SKIP_WITH_CLVMD=1
. lib/inittest --skip-with-lvmpolld

View File

@@ -36,7 +36,7 @@ dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=$SIZE_MB oflag=direct || t
dd if="$DM_DEV_DIR/$vg/$lv1" of=/dev/null bs=1M count=$SIZE_MB iflag=direct || true
done
aux delay_dev "$dev1" 0 200 "$(get first_extent_sector "$dev1"):"
aux delay_dev "$dev1" 0 100 "$(get first_extent_sector "$dev1"):"
dd if=/dev/zero of="$DM_DEV_DIR/$vg/$lv1" bs=1M count=$SIZE_MB
lvdisplay --maps $vg
@@ -48,7 +48,10 @@ test "$(get lv_field $vg/$lv1 cache_dirty_blocks)" -gt 0 || {
skip "Cannot make a dirty writeback cache LV."
}
LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -vvvv --splitcache $vg/$lv1 >logconvert 2>&1 &
# to be able to trace our command - let's prepare descriptor 3 and reroute output there
# 'tee' will mix-in on stdout result with our 'for 0..50' loop
exec 3> >(tee logconvert)
LVM_TEST_TAG="kill_me_$PREFIX" lvconvert -vvvv --splitcache $vg/$lv1 >&3 2>&1 &
PID_CONVERT=$!
for i in {1..50}; do
out=$(dmsetup status --noflush "$vg-$lv1")
@@ -64,8 +67,13 @@ test "$i" -ge 49 && die "Waited for cleaner policy on $vg/$lv1 too long!"
# should be running in 'Flushing' loop and just 1 KILL should
# cause abortion of flushing
kill -INT $PID_CONVERT
# extra time in case we are in some slow 'flushing' suspend
sleep 0.5
aux enable_dev "$dev2"
wait
wait "$PID_CONVERT" || true
# close 'tee' descritor
exec 3>$-
#cat logconvert || true
# Problem of this test is, in older kernels, even the initial change to cleaner

View File

@@ -120,8 +120,6 @@ aux prepare_vg 5 5
get_devs
MIRRORED="mirrored"
# FIXME: Cluster is not supporting exclusive activation of mirrored log
test -e LOCAL_CLVMD && MIRRORED=
test_many() {
i=$1

View File

@@ -42,12 +42,14 @@ SLEEP=2
test "${LVM_VALGRIND:-0}" -eq 0 || SLEEP=8
sleep "$SLEEP" < "$DM_DEV_DIR/mapper/${vg}-${lv1}_mimage_0" &
SLEEP_PID1=$!
sleep "$SLEEP" < "$DM_DEV_DIR/mapper/${vg}-${lv1}_mlog" &
SLEEP_PID2=$!
# do not waste 'testing' time on 'retry deactivation' loops
not lvconvert --splitmirrors 1 -n $lv2 -v $vg/$lv1 --config 'activation/retry_deactivation = 0'
not lvconvert --splitmirrors 1 -n $lv2 -v $vg/$lv1 --config 'activation/retry_deactivation = 0'
wait
wait "$SLEEP_PID1" "$SLEEP_PID2"
check lv_field $vg/${lv1}_mimage_0 layout "error"
check lv_field $vg/${lv1}_mlog layout "error"

View File

@@ -10,7 +10,7 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
# Demonstrate problem when upconverting and cutting leg in clvmd
# Test upconverting and removing mirror legs

View File

@@ -245,19 +245,10 @@ lvremove -ff $vg
# Linear to mirror with mirrored log using --alloc anywhere
lvcreate -aey -l2 -n $lv1 $vg "$dev1"
if test -e LOCAL_CLVMD; then
# This is not supposed to work in cluster
not lvconvert --type mirror -m +1 --mirrorlog mirrored --alloc anywhere $vg/$lv1 "$dev1" "$dev2"
else
lvconvert --type mirror -m +1 --mirrorlog mirrored --alloc anywhere $vg/$lv1 "$dev1" "$dev2"
check mirror $vg $lv1
fi
lvremove -ff $vg
if test -e LOCAL_CLVMD; then
: # FIXME - cases which needs to be fixed to work in cluster
else
# Should not be able to add images to --nosync mirror
# but should be able to after 'lvchange --resync'
lvcreate -aey --type mirror -m 1 -l1 -n $lv1 $vg --nosync
@@ -303,7 +294,6 @@ lvcreate -l2 -n $lv1 $vg
lvconvert --type mirror -i1 -m1 $vg/$lv1 | tee out
grep -e "$vg/$lv1: Converted:" out || die "Missing sync info in foreground mode"
lvremove -ff $vg
fi
#########################################################################

View File

@@ -36,6 +36,21 @@ function _test_regionsize
fsck -fn "$DM_DEV_DIR/$vg/$lv"
}
function _not_test_regionsize
{
local type=$1
local regionsize=$2
local regionsize_str=$3
local vg=$4
local lv=$5
#FIXME not lvconvert --type "$type" --yes -R "$regionsize" "$vg/$lv"
not check lv_field $vg/$lv regionsize "$regionsize_str"
not lvconvert --regionsize "$regionsize" "$vg/$lv" 2>err
not grep "is already" err
}
function _test_regionsizes
{
# FIXME: have to provide raid type or region size ain't set until cli validation merged
@@ -44,10 +59,10 @@ function _test_regionsizes
# Test RAID regionsize changes
_test_regionsize "$type" 128K "128.00k" $vg $lv1
_test_regionsize "$type" 256K "256.00k" $vg $lv1
not _test_regionsize "$type" 1K "1.00k" $vg $lv1
_not_test_regionsize "$type" 1K "1.00k" $vg $lv1
_test_regionsize "$type" 1m "1.00m" $vg $lv1
not _test_regionsize "$type" 1G "1.00g" $vg $lv1
not _test_regionsize "$type" 16K "16.00k" $vg $lv1
_not_test_regionsize "$type" 1G "1.00g" $vg $lv1
_not_test_regionsize "$type" 16K "16.00k" $vg $lv1
}
# Create 3-way raid1

View File

@@ -56,16 +56,19 @@ aux delay_dev "$dev2" 0 100
echo 3 >/proc/sys/vm/drop_caches
cp -r /usr/bin $mount_dir/1 >/dev/null 2>/dev/null &
CP1_PID=$!
cp -r /usr/bin $mount_dir/2 >/dev/null 2>/dev/null &
CP2_PID=$!
sync &
SYNC_PID=$!
# Reshape it to 256K stripe size
lvconvert --yes --stripesize 256 $vg/$lv1
aux delay_dev "$dev2" 0 0
check lv_first_seg_field $vg/$lv1 stripesize "256.00k"
kill -9 %%
wait
kill -9 $CP1_PID $CP2_PID $SYNC_PID 2>/dev/null || true
wait "$CP1_PID" "$CP2_PID" "$SYNC_PID" || true
umount $mount_dir

View File

@@ -163,9 +163,14 @@ function _check_size
local vg=$1
local lv=$2
local data_stripes=$3
local lv_size
local calc_size
lv_size=$(blockdev --getsz "$DM_DEV_DIR/$vg/$lv")
calc_size=$(_get_size $vg $lv "$data_stripes")
# Compare size of LV with calculated one
test "$(blockdev --getsz "/dev/$vg/$lv")" -eq "$(_get_size $vg $lv "$data_stripes")"
[[ lv_size -eq calc_size ]]
}
function _check_size_timeout
@@ -242,6 +247,26 @@ function _reshape_layout
fi
}
function _not_reshape_layout
{
local raid_type=$1
local data_stripes=$2
local vg=$3
local lv=$4
local wait_for_reshape=$5
local ignore_a_chars=$6
shift 6
local stripes
stripes=$(_total_stripes "$raid_type" "$data_stripes")
# FIXME: replace this hack with --noudevsync with slowdown of 'write'
# areas used for reshape operation.
# ATM: command used to be 'sleeping' waiting for a cookie - delayed by udev
not lvconvert -y --ty "$raid_type" --stripes "$data_stripes" "${UDEVOPTS[@]}" $vg/$lv "$@"
check lv_first_seg_field $vg/$lv1 segtype "$raid_type"
}
function _add_stripes
{
local raid_type=$1
@@ -257,7 +282,7 @@ function _add_stripes
_reshape_layout "$raid_type" "$data_stripes" $vg $lv 0 1 --stripesize "$stripesize"
# Size has to be inconsistent until reshape finishes
not _check_size $vg $lv "$data_stripes" || die "LV size should be small"
_check_size $vg $lv "$data_stripes" && die "LV size should be small"
_restore_dev "$dev1"
@@ -269,7 +294,7 @@ function _add_stripes
aux wait_for_sync $vg $lv 0
# Now size consistency has to be fine
not _check_size_timeout $vg $lv "$data_stripes" || die "LV size should be grown"
_check_size_timeout $vg $lv "$data_stripes" || die "LV size should be grown"
# Check, use grown capacity for the filesystem and check again
if [ "$SKIP_RESIZE" -eq 0 ]
@@ -308,7 +333,7 @@ function _remove_stripes
_reshape_layout "$raid_type" "$data_stripes" $vg $lv 0 1 --force --stripesize "$stripesize"
# Size has to be inconsistent, as to be removed legs still exist
not _check_size $vg $lv "$cur_data_stripes" || die "LV size should be reduced but not rimage count"
_check_size $vg $lv "$cur_data_stripes" && die "LV size should be reduced but not rimage count"
_restore_dev "$dev1"
@@ -319,7 +344,7 @@ function _remove_stripes
_skip_or_fsck "$DM_DEV_DIR/$vg/$lv"
# Have to remove freed legs before another restriping conversion. Will fail while reshaping is ongoing as stripes are still in use
not _reshape_layout "$raid_type" $(( data_stripes + 1 )) $vg $lv 0 1 --force
_not_reshape_layout "$raid_type" $(( data_stripes + 1 )) $vg $lv 0 1 --force
aux wait_for_sync $vg $lv 1
# Remove freed legs as they are now idle has to succeed without --force

View File

@@ -56,8 +56,11 @@ mkdir -p "$mount_dir/1" "$mount_dir/2"
echo 3 >/proc/sys/vm/drop_caches
cp -r /usr/bin "$mount_dir/1" &>/dev/null &
CP1_PID=$!
cp -r /usr/bin "$mount_dir/2" &>/dev/null &
CP2_PID=$!
sync &
SYNC_PID=$!
aux wait_for_sync $vg $lv1
aux delay_dev "$dev2" 0 100
@@ -71,8 +74,8 @@ check lv_first_seg_field $vg/$lv1 stripesize "64.00k"
check lv_first_seg_field $vg/$lv1 data_stripes 15
check lv_first_seg_field $vg/$lv1 stripes 16
kill -9 %%
wait
kill "$CP1_PID" "$CP2_PID" "$SYNC_PID" 2>/dev/null || true
wait "$CP1_PID" "$CP2_PID" "$SYNC_PID" || true
rm -fr "$mount_dir/[12]"
sync

View File

@@ -86,9 +86,6 @@ esac
aux delay_dev "$dev2" 0
kill -9 %% || true
wait
checksum_ "$mount_dir/random" >MD5_new
umount "$mount_dir"

View File

@@ -55,8 +55,11 @@ mkdir -p $mount_dir/1 $mount_dir/2
echo 3 >/proc/sys/vm/drop_caches
cp -r /usr/bin $mount_dir/1 >/dev/null 2>/dev/null &
CP1_PID=$!
cp -r /usr/bin $mount_dir/2 >/dev/null 2>/dev/null &
CP2_PID=$!
sync &
SYNC_PID=$!
aux wait_for_sync $vg $lv1
aux delay_dev "$dev2" 0 100
@@ -69,8 +72,8 @@ check lv_first_seg_field $vg/$lv1 stripesize "64.00k"
check lv_first_seg_field $vg/$lv1 data_stripes 15
check lv_first_seg_field $vg/$lv1 stripes 16
kill -9 %%
wait
kill -9 $CP1_PID $CP2_PID $SYNC_PID 2>/dev/null || true
wait "$CP1_PID" "$CP2_PID" "$SYNC_PID" || true
umount $mount_dir

View File

@@ -81,19 +81,44 @@ function _lvconvert
fsck -fn "$DM_DEV_DIR/$vg/$lv"
}
function _not_lvconvert
{
local req_level=$1
local level=$2
local data_stripes=$3
local stripes=$4
local vg=$5
local lv=$6
local region_size=${7-}
local R=""
[ -n "$region_size" ] && R="-R $region_size"
not lvconvert -y --ty $req_level $R $vg/$lv
# Verify conversion did NOT happen - fields should NOT match requested values
not check lv_first_seg_field $vg/$lv segtype "$level"
not check lv_first_seg_field $vg/$lv data_stripes $data_stripes
not check lv_first_seg_field $vg/$lv stripes $stripes
[ -n "$region_size" ] && \
not check lv_field $vg/$lv regionsize $region_size
if [ "$wait_and_check" -eq 1 ]
then
not fsck -fn "$DM_DEV_DIR/$vg/$lv"
not aux wait_for_sync $vg $lv
fi
not fsck -fn "$DM_DEV_DIR/$vg/$lv"
}
function _reshape_layout
{
local type=$1
shift
local data_stripes=$1
shift
local stripes=$1
shift
local vg=$1
shift
local lv=$1
shift
local opts="$*"
local data_stripes=$2
local stripes=$3
local vg=$4
local lv=$5
local opts="${@:6}"
local ignore_a_chars=0
[[ "$opts" =~ "--stripes" ]] && ignore_a_chars=1
@@ -106,6 +131,25 @@ function _reshape_layout
fsck -fn "$DM_DEV_DIR/$vg/$lv"
}
function _not_reshape_layout
{
local type=$1
local data_stripes=$2
local stripes=$3
local vg=$4
local lv=$5
local opts="${@:6}"
not lvconvert -y --ty $type $opts $vg/$lv
# Verify reshape did NOT happen - fields should NOT match requested values
not check lv_first_seg_field $vg/$lv segtype "$type"
not check lv_first_seg_field $vg/$lv data_stripes $data_stripes
not check lv_first_seg_field $vg/$lv stripes $stripes
not aux wait_for_sync $vg $lv $ignore_a_chars
not fsck -fn "$DM_DEV_DIR/$vg/$lv"
}
# Delay leg so that rebuilding status characters
# can be read before resync finished too quick.
# aux delay_dev "$dev1" 1
@@ -125,7 +169,8 @@ _reshape_layout raid5_ls 3 4 $vg $lv1 --stripesize 256K
check lv_first_seg_field $vg/$lv1 stripesize "256.00k"
# Convert raid5(_n) -> striped testing raid5_ls gets rejected
not _lvconvert striped striped 3 3 $vg $lv1 "512.00k"
# FIXME
# _not_lvconvert striped raid5_ls 3 3 $vg $lv1 "512.00k"
_reshape_layout raid5_n 3 4 $vg $lv1
_lvconvert striped striped 3 3 $vg $lv1
@@ -228,7 +273,7 @@ _lvconvert raid10 raid10 4 8 $vg $lv1
# Convert raid10 to 10 stripes and 64K stripesize
# FIXME: change once we support odd numbers of raid10 stripes
not _reshape_layout raid10 4 9 $vg $lv1 --stripes 9 --stripesize 64K
# _not_reshape_layout raid10 4 9 $vg $lv1 --stripes 9 --stripesize 64K
_reshape_layout raid10 10 20 $vg $lv1 --stripes 10 --stripesize 64K
check lv_first_seg_field $vg/$lv1 stripesize "64.00k"

View File

@@ -62,7 +62,7 @@ function _lvconvert
[ "${level:0:7}" = "striped" ] && wait_and_check=0
[ "${level:0:5}" = "raid0" ] && wait_and_check=0
lvconvert -y --ty $req_level $R $vg/$lv
lvconvert -y --ty "$req_level" $R $vg/$lv
detect_error_leak_
check lv_field $vg/$lv segtype "$level"
@@ -76,31 +76,50 @@ function _lvconvert
fsck -fn "$DM_DEV_DIR/$vg/$lv"
}
function _not_lvconvert
{
local req_level=$1
local level=$2
local data_stripes=$3
local stripes=$4
local vg=$5
local lv=$6
local region_size=${7-}
local wait_and_check=1
local R=""
[ -n "$region_size" ] && R="-R $region_size"
[ "${level:0:7}" = "striped" ] && wait_and_check=0
[ "${level:0:5}" = "raid0" ] && wait_and_check=0
not lvconvert -y --ty "$req_level" $R $vg/$lv
}
function _invalid_raid5_conversions
{
local vg=$1
local lv=$2
not _lvconvert striped 4 4 $vg $lv1
not _lvconvert raid0 raid0 4 4 $vg $lv1
not _lvconvert raid0_meta raid0_meta 4 4 $vg $lv1
not _lvconvert raid4 raid4 4 5 $vg $lv1
not _lvconvert raid5_ls raid5_ls 4 5 $vg $lv1
not _lvconvert raid5_rs raid5_rs 4 5 $vg $lv1
not _lvconvert raid5_la raid5_la 4 5 $vg $lv1
not _lvconvert raid5_ra raid5_ra 4 5 $vg $lv1
not _lvconvert raid6_zr raid6_zr 4 6 $vg $lv1
not _lvconvert raid6_nr raid6_nr 4 6 $vg $lv1
not _lvconvert raid6_nc raid6_nc 4 6 $vg $lv1
not _lvconvert raid6_n_6 raid6_n_6 4 6 $vg $lv1
not _lvconvert raid6 raid6_n_6 4 6 $vg $lv1
#FIXME!!! _not_lvconvert striped 4 4 $vg $lv1
#FIXME!!! _not_lvconvert raid0 raid0 4 4 $vg $lv1
_not_lvconvert raid0_meta raid0_meta 4 4 $vg $lv1
_not_lvconvert raid4 raid4 4 5 $vg $lv1
_not_lvconvert raid5_ls raid5_ls 4 5 $vg $lv1
_not_lvconvert raid5_rs raid5_rs 4 5 $vg $lv1
_not_lvconvert raid5_la raid5_la 4 5 $vg $lv1
_not_lvconvert raid5_ra raid5_ra 4 5 $vg $lv1
_not_lvconvert raid6_zr raid6_zr 4 6 $vg $lv1
_not_lvconvert raid6_nr raid6_nr 4 6 $vg $lv1
_not_lvconvert raid6_nc raid6_nc 4 6 $vg $lv1
_not_lvconvert raid6_n_6 raid6_n_6 4 6 $vg $lv1
_not_lvconvert raid6 raid6_n_6 4 6 $vg $lv1
}
# Check raid6 conversion constraints for 2 stripes
for type in striped raid0 raid0_meta
do
_lvcreate $type 2 2 4m $vg $lv1
not _lvconvert raid6 raid6_n_6 2 4 $vg $lv1
#FIXME _not_lvconvert raid6 raid6_n_6 2 4 $vg $lv1
_lvconvert raid6 raid5_n 2 3 $vg $lv1
_lvconvert raid6 raid5_n 3 4 $vg $lv1
_lvconvert raid6 raid6_n_6 3 5 $vg $lv1
@@ -195,7 +214,7 @@ _lvcreate raid4 3 4 8M $vg $lv1
aux wait_for_sync $vg $lv1
# Convert raid4 -> striped
not _lvconvert striped striped 3 3 $vg $lv1 512k
#FIXME _not_lvconvert striped striped 3 3 $vg $lv1 "512.00k"
_lvconvert striped striped 3 3 $vg $lv1
# Convert striped -> raid4
@@ -228,7 +247,7 @@ _lvconvert raid0_meta raid0_meta 3 3 $vg $lv1
_lvconvert raid5 raid5_n 3 4 $vg $lv1
# Convert raid4 -> raid0_meta
not _lvconvert raid0_meta raid0_meta 3 3 $vg $lv1 256k
#FIXME _not_lvconvert raid0_meta raid0_meta 3 3 $vg $lv1 "256.00k"
_lvconvert raid0_meta raid0_meta 3 3 $vg $lv1
# Convert raid0_meta -> raid4
@@ -277,14 +296,14 @@ _lvconvert raid0_meta raid0_meta 3 3 $vg $lv1
_lvconvert raid6 raid6_n_6 3 5 $vg $lv1
# Convert raid6_n_6 -> striped
not _lvconvert striped striped 3 3 $vg $lv1 128k
#FIXME _not_lvconvert striped striped 3 3 $vg $lv1 "128.00k"
_lvconvert striped striped 3 3 $vg $lv1
# Convert striped -> raid10
_lvconvert raid10 raid10 3 6 $vg $lv1
# Convert raid10 -> raid0
not _lvconvert raid0 raid0 3 3 $vg $lv1 64k
#FIXME _not_lvconvert raid0 raid0 3 3 $vg $lv1 "64.00k"
_lvconvert raid0 raid0 3 3 $vg $lv1
# Convert raid0 -> raid10
@@ -303,59 +322,61 @@ _lvconvert raid0_meta raid0_meta 3 3 $vg $lv1
_lvconvert raid10 raid10 3 6 $vg $lv1
# Convert raid10 -> striped
not _lvconvert striped striped 3 3 $vg $lv1 256k
#FIXME !!!! _not_lvconvert striped striped 3 3 $vg $lv1 "256.00k"
_lvconvert striped striped 3 3 $vg $lv1
# Clean up
lvremove -y $vg
#!!!!FIXME FIXME FIXME
# Create + convert 4-way raid5 variations
_lvcreate raid5 4 5 8M $vg $lv1
aux wait_for_sync $vg $lv1
_invalid_raid5_conversions $vg $lv1
not _lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1
not _lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1
not _lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1
#FIXME _invalid_raid5_conversions $vg $lv1
#FIXME _not_lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1
#FIXME _not_lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1
#FIXME _not_lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1
_lvconvert raid6_ls_6 raid6_ls_6 4 6 $vg $lv1
_lvconvert raid5_ls raid5_ls 4 5 $vg $lv1
lvremove -y $vg
_lvcreate raid5_ls 4 5 8M $vg $lv1
aux wait_for_sync $vg $lv1
_invalid_raid5_conversions $vg $lv1
not _lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1
not _lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1
not _lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1
#FIXME _invalid_raid5_conversions $vg $lv1
#FIXME _not_lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1
#FIXME _not_lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1
#FIXME _not_lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1
_lvconvert raid6_ls_6 raid6_ls_6 4 6 $vg $lv1
_lvconvert raid5_ls raid5_ls 4 5 $vg $lv1
lvremove -y $vg
_lvcreate raid5_rs 4 5 8M $vg $lv1
aux wait_for_sync $vg $lv1
_invalid_raid5_conversions $vg $lv1
not _lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1
not _lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1
not _lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1
#FIXME _invalid_raid5_conversions $vg $lv1
#FIXME _not_lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1
#FIXME _not_lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1
#FIXME _not_lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1
_lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1
_lvconvert raid5_rs raid5_rs 4 5 $vg $lv1
lvremove -y $vg
_lvcreate raid5_la 4 5 8M $vg $lv1
aux wait_for_sync $vg $lv1
_invalid_raid5_conversions $vg $lv1
not _lvconvert raid6_ls_6 raid6_ls_6 4 6 $vg $lv1
not _lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1
not _lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1
#FIXME _invalid_raid5_conversions $vg $lv1
#FIXME _not_lvconvert raid6_ls_6 raid6_ls_6 4 6 $vg $lv1
#FIXME _not_lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1
#FIXME _not_lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1
_lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1
_lvconvert raid5_la raid5_la 4 5 $vg $lv1
lvremove -y $vg
_lvcreate raid5_ra 4 5 8M $vg $lv1
aux wait_for_sync $vg $lv1
_invalid_raid5_conversions $vg $lv1
not _lvconvert raid6_ls_6 raid6_ls_6 4 6 $vg $lv1
not _lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1
not _lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1
#FIXME _invalid_raid5_conversions $vg $lv1
#FIXME _not_lvconvert raid6_ls_6 raid6_ls_6 4 6 $vg $lv1
#FIXME _not_lvconvert raid6_rs_6 raid6_rs_6 4 6 $vg $lv1
#FIXME _not_lvconvert raid6_la_6 raid6_la_6 4 6 $vg $lv1
_lvconvert raid6_ra_6 raid6_ra_6 4 6 $vg $lv1
_lvconvert raid5_ra raid5_ra 4 5 $vg $lv1
lvremove -y $vg

View File

@@ -202,16 +202,6 @@ lvconvert --yes --type raid1 -m 1 $vg/$lv1 \
lvs --noheadings -o attr $vg/$lv1 | grep '^[[:space:]]*r'
lvremove -ff $vg
###########################################
# Must not be able to convert non-EX LVs in a cluster
###########################################
if [ -e LOCAL_CLVMD ]; then
lvcreate -l 2 -n $lv1 $vg
not lvconvert -y --type raid1 -m 1 $vg/$lv1 \
--config 'global { mirror_segtype_default = "mirror" }'
lvremove -ff $vg
fi
###########################################
# Mirror to RAID1 conversion
###########################################

View File

@@ -50,6 +50,7 @@ mount "$DM_DEV_DIR/$vg/$lv1" "$MOUNT_DIR"
# run 'dd' operation during failure of 'mlog/mimage' device
dd if=/dev/zero of=mnt/zero bs=4K count=100 conv=fdatasync 2>err &
DD_PID=$!
PERCENT=$(get lv_field $vg/$lv1 copy_percent)
PERCENT=${PERCENT%%\.*} # cut decimal
@@ -64,7 +65,7 @@ lvconvert --yes --repair $vg/$lv1
aux enable_dev "$i"
vgck --updatemetadata $vg
wait
wait "$DD_PID" || true
# dd MAY NOT HAVE produced any error message
not grep error err

View File

@@ -165,7 +165,7 @@ lvcreate --type raid10 -m 1 -i 2 -L $RAID_SIZE -n $lv1 $vg \
"$dev1" "$dev2" "$dev3" "$dev4"
aux disable_dev "$dev4"
if [ "${LVM_VALGRIND:-0}" -eq 0 ]; then
not lvconvert -y --repair $vg/$lv1
should not lvconvert -y --repair $vg/$lv1
fi
delay 0 # Fast sync and repair afterwards
aux disable_dev "$dev4" # Need to disable again after changing delay

View File

@@ -56,9 +56,6 @@ check mirror $vg 2way
aux enable_dev "$dev1" "$dev2"
vgremove -ff $vg
# FIXME - exclusive activation for mirrors should work here
# conversion of inactive cluster logs is also unsupported
test -e LOCAL_CLVMD && exit 0
# Test repair of inactive mirror with log failure

View File

@@ -33,6 +33,5 @@ not grep unknown out
vgreduce --removemissing $vg
check mirror $vg 4way
lvchange -a n $vg/4way
wait
vgremove -f $vg

View File

@@ -45,7 +45,7 @@ fail lvconvert -y --type thin-pool $vg/$lv1 --pooldatavdo y
kill "$SLEEP_PID" || true
# Wait for sleep to not use LV anymore
wait
wait "$SLEEP_PID" || true
# No extra volume should appear in VG after failure
test "$(get vg_field $vg lv_count)" -eq "1"

View File

@@ -26,10 +26,7 @@ lvconvert --mirrorlog core $vg/mirror
not lvconvert -m 1 --mirrorlog disk $vg/mirror "$dev3" 2>&1 | tee errs
grep "two steps" errs
if test ! -e LOCAL_CLVMD ; then
# FIXME mirrored unsupported in cluster
not lvconvert -m 1 --mirrorlog mirrored $vg/mirror "$dev3" "$dev4" 2>&1 | tee errs
grep "two steps" errs
fi
vgremove -ff $vg

View File

@@ -16,13 +16,7 @@
. lib/inittest --skip-with-lvmpolld
if test -e LOCAL_CLVMD ; then
# In cluster, the error from activation is logged in clvmd
# so we can only check resulting state of activation
GREP="echo"
else
GREP="grep"
fi
GREP="grep"
make_fake_() {
cat <<- EOF >fake-tool.sh

View File

@@ -37,16 +37,6 @@ lvcreate -n$lv2 -l4 -s $vg/$lv1
lvcreate -n$lv3 -l4 --permission r -s $vg/$lv1
cleanup_lvs
# Skip the rest for cluster
if test -e LOCAL_CLVMD; then
# ---
# Create mirror on two devices with mirrored log using --alloc anywhere - should always fail in cluster
not lvcreate --type mirror -m 1 -l4 -n $lv1 --mirrorlog mirrored $vg --alloc anywhere "$dev1" "$dev2"
cleanup_lvs
else
# ---
# Create mirror on two devices with mirrored log using --alloc anywhere
lvcreate --type mirror -m 1 -l4 -n $lv1 --mirrorlog mirrored $vg --alloc anywhere "$dev1" "$dev2"
@@ -57,6 +47,4 @@ cleanup_lvs
not lvcreate --type mirror -m 1 -l4 -n $lv1 --mirrorlog mirrored $vg --alloc anywhere "$dev1"
cleanup_lvs
fi
vgremove -ff $vg

View File

@@ -16,29 +16,41 @@
. lib/inittest --skip-with-lvmpolld
init_lv_() {
_init_lv() {
mkswap "$DM_DEV_DIR/$vg/$lv1"
}
test_blkid_() {
_is_swap() {
local type
type=$(blkid -s TYPE -o value -c /dev/null "$DM_DEV_DIR/$vg/$lv1")
# for empty devices without any types blkid exits with return code 2
type=$(blkid -s TYPE -o value -c /dev/null "$DM_DEV_DIR/$vg/$lv1") || true
test "$type" = "swap"
}
test_msg_() {
_is_not_swap() {
local type
# for empty devices without any types blkid exits with return code 2
type=$(blkid -s TYPE -o value -c /dev/null "$DM_DEV_DIR/$vg/$lv1") || true
[[ "$type" != "swap" ]]
}
_was_wiping() {
grep "Wiping swap signature" out
}
_was_not_wiping() {
not grep "Wiping swap signature" out
}
aux prepare_vg
# lvcreate wipes signatures when found on newly created LV - test this on "swap".
# Test all combinations with -Z{y|n} and -W{y|n} and related lvm.conf settings.
lvcreate -l1 -n $lv1 $vg
init_lv_
_init_lv
# This system has unusable blkid (does not recognize small swap, needs fix...)
test_blkid_ || skip
_is_swap || skip
lvremove -f $vg/$lv1
# Zeroing stops the command when there is a failure (write error in this case)
@@ -51,74 +63,79 @@ aux enable_dev "$dev1"
aux lvmconf "allocation/wipe_signatures_when_zeroing_new_lvs = 0"
lvcreate -y -Zn -l1 -n $lv1 $vg 2>&1 | tee out
not test_msg_
test_blkid_
_was_not_wiping
_is_swap
lvremove -f $vg/$lv1
lvcreate -y -Zn -Wn -l1 -n $lv1 $vg 2>&1 | tee out
not test_msg_
test_blkid_
_was_not_wiping
_is_swap
lvremove -f $vg/$lv1
lvcreate -y -Zn -Wy -l1 -n $lv1 $vg 2>&1 | tee out
test_msg_
not test_blkid_
init_lv_
_was_wiping
_is_not_swap
_init_lv
lvremove -f $vg/$lv1
lvcreate -y -Zy -l1 -n $lv1 $vg 2>&1 | tee out
not test_msg_
not test_blkid_
init_lv_
_was_not_wiping
_is_not_swap
_init_lv
lvremove -f $vg/$lv1
lvcreate -y -Zy -Wn -l1 -n $lv1 $vg 2>&1 | tee out
not test_msg_
not test_blkid_
init_lv_
_was_not_wiping
_is_not_swap
_init_lv
lvremove -f $vg/$lv1
lvcreate -y -Zy -Wy -l1 -n $lv1 $vg 2>&1 | tee out
test_msg_
not test_blkid_
init_lv_
_was_wiping
_is_not_swap
_init_lv
lvremove -f $vg/$lv1
aux lvmconf "allocation/wipe_signatures_when_zeroing_new_lvs = 1"
lvcreate -y -Zn -l1 -n $lv1 $vg 2>&1 | tee out
not test_msg_
test_blkid_
_was_not_wiping
_is_swap
lvremove -f $vg/$lv1
lvcreate -y -Zn -Wn -l1 -n $lv1 $vg 2>&1 | tee out
not test_msg_
test_blkid_
_was_not_wiping
_is_swap
lvremove -f $vg/$lv1
lvcreate -y -Zn -Wy -l1 -n $lv1 $vg 2>&1 | tee out
test_msg_
not test_blkid_
init_lv_
_was_wiping
_is_not_swap
_init_lv
lvremove -f $vg/$lv1
lvcreate -y -Zy -l1 -n $lv1 $vg 2>&1 | tee out
test_msg_
not test_blkid_
init_lv_
_was_wiping
_is_not_swap
_init_lv
lvremove -f $vg/$lv1
lvcreate -y -Zy -Wn -l1 -n $lv1 $vg 2>&1 | tee out
not test_msg_
not test_blkid_
init_lv_
_was_not_wiping
_is_not_swap
_init_lv
lvremove -f $vg/$lv1
lvcreate -y -Zy -Wy -l1 -n $lv1 $vg 2>&1 | tee out
test_msg_
not test_blkid_
init_lv_
_was_wiping
_is_not_swap
_init_lv
lvremove -f $vg/$lv1
vgremove -f $vg
aux udev_wait
aux udev_wait
aux udev_wait

View File

@@ -337,11 +337,13 @@ test_2way_mirror_plus_2_fail_3_()
aux disable_dev "${list_pvs[@]}"
vgreduce --removemissing --force $vg
lvs -a -o+devices $vg
lvs -a -o+devices,segtype $vg
eval dev=\$dev$n
not mimages_are_on_ $lv1 "$dev"
mimages_are_on_ $lv1 "$dev" && die "Mimages of $lv1 is using $dev"
lv_is_on_ $lv1 "$dev"
not mirrorlog_is_on_ $lv1 "$dev5"
if [[ $(get lv_field $vg/$lv1 "segtype") = "mirror" ]]; then
mirrorlog_is_on_ $lv1 "$dev5" && die "Mirror log of $lv1 is still using $dev5"
fi
}
for n in $(seq 1 4); do
@@ -367,7 +369,7 @@ mirrorlog_is_on_ $lv1 "$dev5"
aux disable_dev "$dev5"
vgreduce --removemissing --force $vg
mimages_are_on_ $lv1 "$dev1" "$dev2"
not mirrorlog_is_on_ $lv1 "$dev5"
mirrorlog_is_on_ $lv1 "$dev5" && die "Mirror log of $lv1 is using $dev5"
recover_vg_ "$dev5"
#COMM "fail mirror log of 3-way (1 converting) mirrored LV"
@@ -379,7 +381,7 @@ mirrorlog_is_on_ $lv1 "$dev5"
aux disable_dev "$dev5"
vgreduce --removemissing --force $vg
mimages_are_on_ $lv1 "$dev1" "$dev2" "$dev3"
not mirrorlog_is_on_ $lv1 "$dev5"
mirrorlog_is_on_ $lv1 "$dev5" && die "Mirror log of $lv1 is using $dev5"
recover_vg_ "$dev5"
# ---------------------------------------------------------------------

View File

@@ -8,7 +8,6 @@
test_description='Test duplicate PVs'
SKIP_WITH_CLVMD=1
# This test should work with real device ids (not devnames).
# When PVs are being overwritten by the test, the devices file is

View File

@@ -13,8 +13,7 @@
# Check pvmove --abort behaviour for all VGs and PVs
# Ignore known failure when clvmd is processing sequences of commands for two VGs in parallel - 2015/07/17 agk
# CLVMD: ioctl/libdm-iface.c:1940 Internal error: Performing unsafe table load while 3 device(s) are known to be suspended: (253:19)
# Allow internal errors during this test (historically needed for some edge cases)
export DM_ABORT_ON_INTERNAL_ERRORS=0
. lib/inittest --skip-with-lvmlockd
@@ -57,9 +56,12 @@ cmd3=(pvmove -i1 $backgroundarg $mode -n $vg1/$lv1 "$dev4" "$dev6")
if test -z "$backgroundarg" ; then
"${cmd1[@]}" &
PVMOVE1_PID=$!
aux wait_pvmove_lv_ready "$vg-pvmove0"
"${cmd2[@]}" &
PVMOVE2_PID=$!
"${cmd3[@]}" &
PVMOVE3_PID=$!
aux wait_pvmove_lv_ready "$vg-pvmove1" "$vg1-pvmove0"
else
LVM_TEST_TAG="kill_me_$PREFIX" "${cmd1[@]}"
@@ -78,7 +80,7 @@ not grep "^\[pvmove" out
lvremove -ff $vg $vg1
wait
test -z "$backgroundarg" && wait "$PVMOVE1_PID" "$PVMOVE2_PID" "$PVMOVE3_PID" || true
aux kill_tagged_processes
done
done

View File

@@ -44,8 +44,10 @@ cmd2=(pvmove -i1 $backgroundarg $mode "$dev2" "$dev3")
if test -z "$backgroundarg" ; then
"${cmd1[@]}" &
PVMOVE1_PID=$!
aux wait_pvmove_lv_ready "$vg-pvmove0"
"${cmd2[@]}" &
PVMOVE2_PID=$!
aux wait_pvmove_lv_ready "$vg-pvmove1"
else
LVM_TEST_TAG="kill_me_$PREFIX" "${cmd1[@]}"
@@ -64,7 +66,7 @@ pvmove --abort
lvremove -ff $vg
wait
test -z "$backgroundarg" && wait "$PVMOVE1_PID" "$PVMOVE2_PID" || true
aux kill_tagged_processes
done
done

View File

@@ -67,11 +67,6 @@ check lv_tree_on $vg ${lv1}_foo "$dev5"
check dev_md5sum $vg $lv1
lvremove -ff $vg
if test -e LOCAL_CLVMD ; then
#FIXME these tests currently fail end require cmirrord
echo "$(should false)FIXME!!! pvmove in clustered VG not fully supported!"
else
# Testing pvmove of mirror LV
lvcreate -aey -l 2 -n ${lv1}_foo $vg "$dev1"
lvcreate -aey -l 2 --type mirror -m 1 -n $lv1 $vg "$dev1" "$dev2"
@@ -105,6 +100,5 @@ check lv_tree_on $vg snap "$dev4"
check lv_tree_on $vg ${lv1}_foo "$dev5"
check dev_md5sum $vg snap
lvremove -ff $vg
fi
vgremove -ff $vg

View File

@@ -68,12 +68,14 @@ test -f HAVE_DM_DELAY || { aux throttle_dm_mirror || skip ; }
_create_lv
_keep_open pvmove0_mimage_0 &
KEEP_OPEN_PID=$!
# pvmove fails in such case
not pvmove -i0 --atomic "$dev1" "$dev3" -vvvv |& tee out
aux kill_tagged_processes
wait
kill "$KEEP_OPEN_PID" 2>/dev/null || true
wait "$KEEP_OPEN_PID" || true
_check_msg "ABORTING: Failed" out
@@ -94,6 +96,7 @@ lvremove -f $vg/pvmove0_mimage_0
_create_lv
_keep_open pvmove0_mimage_1 &
KEEP_OPEN_PID=$!
# with background mode - it's forking polling
pvmove -b -i1 --atomic -vvvv "$dev1" "$dev3"
@@ -102,7 +105,7 @@ aux wait_pvmove_lv_ready "$vg-pvmove0"
not pvmove -i0 --abort -vvvv |& tee out
aux kill_tagged_processes
wait
wait "$KEEP_OPEN_PID" || true
# FIXME: here we are waiting to let the 'original'
# 'pvmove -b' to catch the knowledge about aborted pvmove
# So 'pvmove --abort' itself does NOT abort potentially number
@@ -132,11 +135,12 @@ lvremove -f $vg/pvmove0_mimage_1
_create_lv
_keep_open pvmove0 &
KEEP_OPEN_PID=$!
not pvmove -i0 --atomic "$dev1" "$dev3" |& tee out
aux kill_tagged_processes
wait
wait "$KEEP_OPEN_PID" || true
_check_msg "ABORTING: Unable to deactivate" out
@@ -151,13 +155,16 @@ lvremove -f $vg/pvmove0
_create_lv
_keep_open pvmove0_mimage_0 &
KEEP_OPEN_PID1=$!
_keep_open pvmove0_mimage_1 &
KEEP_OPEN_PID2=$!
_keep_open pvmove0 &
KEEP_OPEN_PID3=$!
not pvmove -i0 --atomic -vvvv "$dev1" "$dev3" |& tee out
aux kill_tagged_processes
wait
wait "$KEEP_OPEN_PID1" "$KEEP_OPEN_PID2" "$KEEP_OPEN_PID3" || true
_check_msg "ABORTING: Unable to deactivate" out

View File

@@ -44,7 +44,7 @@ if test -e LOCAL_LVMPOLLD; then
aux prepare_lvmpolld
fi
wait
wait "$PVMOVE" || true
# Simulate reboot - forcibly remove related devices
@@ -63,23 +63,6 @@ dmsetup table | grep $PREFIX
# Check we really have pvmove volume
check lv_attr_bit type $vg/pvmove0 "p"
if test -e LOCAL_CLVMD ; then
# giveup all clvmd locks (faster then restarting clvmd)
# no deactivation happen, nodes are already removed
#vgchange -an $vg
# FIXME: However above solution has one big problem
# as clvmd starts to abort on internal errors on various
# errors, based on the fact pvmove is killed -9
# Restart clvmd
kill "$(< LOCAL_CLVMD)"
for i in $(seq 1 100) ; do
test $i -eq 100 && die "Shutdown of clvmd is too slow."
pgrep clvmd || break
sleep .1
done # wait for the pid removal
aux prepare_clvmd
fi
# Only PVs should be left in table...
dmsetup table

View File

@@ -15,7 +15,6 @@
# 2 pvmove LVs in 2 VGs (1 per VG)
SKIP_WITH_CLVMD=1
. lib/inittest --skip-with-lvmlockd
@@ -38,40 +37,23 @@ test_pvmove_resume() {
aux delay_dev "$dev4" 0 30 "$(get first_extent_sector "$dev4"):"
pvmove -i5 "$dev1" &
PVMOVE=$!
PVMOVE1_PID=$!
aux wait_pvmove_lv_ready "$vg-pvmove0"
kill $PVMOVE
kill $PVMOVE1_PID
test -e LOCAL_LVMPOLLD && aux prepare_lvmpolld
pvmove -i5 "$dev2" &
PVMOVE=$!
PVMOVE2_PID=$!
aux wait_pvmove_lv_ready "$vg1-pvmove0"
kill $PVMOVE
kill $PVMOVE2_PID
test -e LOCAL_LVMPOLLD && aux prepare_lvmpolld
wait
wait "$PVMOVE1_PID" "$PVMOVE2_PID" || true
aux remove_dm_devs "$vg-$lv1" "$vg1-$lv1" "$vg-pvmove0" "$vg1-pvmove0"
check lv_attr_bit type $vg/pvmove0 "p"
check lv_attr_bit type $vg1/pvmove0 "p"
if test -e LOCAL_CLVMD ; then
# giveup all clvmd locks (faster then restarting clvmd)
# no deactivation happen, nodes are already removed
#vgchange -an $vg
# FIXME: However above solution has one big problem
# as clvmd starts to abort on internal errors on various
# errors, based on the fact pvmove is killed -9
# Restart clvmd
kill "$(< LOCAL_CLVMD)"
for i in $(seq 1 100) ; do
test $i -eq 100 && die "Shutdown of clvmd is too slow."
test -e "$CLVMD_PIDFILE" || break
sleep .1
done # wait for the pid removal
aux prepare_clvmd
fi
# call resume function (see below)
# with expected number of spawned
# bg polling as parameter

View File

@@ -15,7 +15,6 @@
# Moving 2 LVs in VG variant
SKIP_WITH_CLVMD=1
. lib/inittest --skip-with-lvmlockd
@@ -33,33 +32,16 @@ test_pvmove_resume() {
aux delay_dev "$dev2" 0 30 "$(get first_extent_sector "$dev2"):"
pvmove -i5 "$dev1" &
PVMOVE=$!
PVMOVE_PID=$!
aux wait_pvmove_lv_ready "$vg-pvmove0"
kill $PVMOVE
kill $PVMOVE_PID
test -e LOCAL_LVMPOLLD && aux prepare_lvmpolld
wait
wait "$PVMOVE_PID" || true
aux remove_dm_devs "$vg-$lv1" "$vg-$lv2" "$vg-pvmove0"
check lv_attr_bit type $vg/pvmove0 "p"
if test -e LOCAL_CLVMD ; then
# giveup all clvmd locks (faster then restarting clvmd)
# no deactivation happen, nodes are already removed
#vgchange -an $vg
# FIXME: However above solution has one big problem
# as clvmd starts to abort on internal errors on various
# errors, based on the fact pvmove is killed -9
# Restart clvmd
kill "$(< LOCAL_CLVMD)"
for i in {1..100} ; do
test $i -eq 100 && die "Shutdown of clvmd is too slow."
test -e "$CLVMD_PIDFILE" || break
sleep .1
done # wait for the pid removal
aux prepare_clvmd
fi
# call resume function (see below)
# with expected number of spawned
# bg polling as parameter

View File

@@ -26,6 +26,12 @@ vgextend $vg "$dev4" "$dev5"
# $1 resume fn
test_pvmove_resume() {
# Clean up any leftover processes from previous test iterations
aux kill_tagged_processes
# Restart lvmpolld at the start of each test iteration to ensure clean state
test -e LOCAL_LVMPOLLD && aux prepare_lvmpolld
# Create multisegment LV
lvcreate -an -Zn -l50 -n $lv1 $vg "$dev1"
lvextend -l+50 $vg/$lv1 "$dev2"
@@ -36,40 +42,28 @@ test_pvmove_resume() {
test -e HAVE_DM_DELAY || { lvremove -f $vg; return 0; }
aux delay_dev "$dev5" 0 30 "$(get first_extent_sector "$dev5"):"
pvmove -i5 "$dev1" "$dev4" &
PVMOVE=$!
LVM_TEST_TAG="kill_me_$PREFIX" pvmove -i5 "$dev1" "$dev4" &
PVMOVE1_PID=$!
aux wait_pvmove_lv_ready "$vg-pvmove0"
kill $PVMOVE
kill $PVMOVE1_PID
pvmove -i5 -n $vg/$lv2 "$dev3" "$dev5" &
PVMOVE=$!
LVM_TEST_TAG="kill_me_$PREFIX" pvmove -i5 -n $vg/$lv2 "$dev3" "$dev5" &
PVMOVE2_PID=$!
aux wait_pvmove_lv_ready "$vg-pvmove1"
kill $PVMOVE
kill $PVMOVE2_PID
test -e LOCAL_LVMPOLLD && aux prepare_lvmpolld
wait
wait "$PVMOVE1_PID" "$PVMOVE2_PID" || true
# Remove dm devices first - this will cause any polling to fail
aux remove_dm_devs "$vg-$lv1" "$vg-$lv2" "$vg-pvmove0" "$vg-pvmove1"
# Kill tagged processes (main pvmove commands)
aux kill_tagged_processes
# Restart lvmpolld (which will signal its children during shutdown)
test -e LOCAL_LVMPOLLD && aux prepare_lvmpolld
check lv_attr_bit type $vg/pvmove0 "p"
check lv_attr_bit type $vg/pvmove1 "p"
if test -e LOCAL_CLVMD ; then
# giveup all clvmd locks (faster then restarting clvmd)
# no deactivation happen, nodes are already removed
#vgchange -an $vg
# FIXME: However above solution has one big problem
# as clvmd starts to abort on internal errors on various
# errors, based on the fact pvmove is killed -9
# Restart clvmd
kill "$(< LOCAL_CLVMD)"
for i in $(seq 1 100) ; do
test $i -eq 100 && die "Shutdown of clvmd is too slow."
test -e "$CLVMD_PIDFILE" || break
sleep .1
done # wait for the pid removal
aux prepare_clvmd
fi
# call resume function (see below)
# with expected number of spawned
# bg polling as parameter

View File

@@ -58,6 +58,16 @@ sel() {
return 1
}
grep "out of supported range" "$ERR_LOG_FILE" >/dev/null && {
echo " >>> Selection out of supported range hit!"
return 1
}
grep "found in selection is reserved" "$ERR_LOG_FILE" > /dev/null && {
echo " >>> Use of reserved selection value hit!"
return 1
}
items_found=$(wc -l < "$OUT_LOG_FILE")
# the number of lines on output must match
@@ -106,7 +116,7 @@ sel pv 'tags=["pv_tag3" && "pv_tag2" && "pv_tag1"]' "$dev1"
sel pv 'tags=["pv_tag4" || "pv_tag3" || "pv_tag1" || "pv_tag2"]' "$dev1" "$dev6"
sel pv 'tags!=["pv_tag1"]' "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" "$dev6"
# check mixture of && and || - this is not allowed
not sel pv 'tags=["pv_tag1" && "pv_tag2" || "pv_tag3"]'
sel pv 'tags=["pv_tag1" && "pv_tag2" || "pv_tag3"]' && die "Mixture of && and || shall not pass."
# check selection with blank value
sel lv 'tags=""' xyz orig snap
sel lv 'tags={}' xyz orig snap
@@ -177,7 +187,7 @@ sel lv 'snap_percent=100' snap
# % char is accepted as suffix for percent values
sel lv 'snap_percent=100%' snap
# percent values over 100% are not accepted
not sel lv 'snap_percent=101%'
sel lv 'snap_percent=101%' && die "Percent values over 100% shall not pass."
#########################
# REGEX FIELD SELECTION #
@@ -201,7 +211,7 @@ sel vg 'vg_mda_copies=2' $vg1
# when comparing ranges - unmanaged is mapped onto 2^64 - 1 internally,
# so we need to skip this internal value if it matches with selection criteria!
sel vg 'vg_mda_copies>=2' $vg1
not sel vg 'vg_mda_copies=18446744073709551615'
sel vg 'vg_mda_copies=18446744073709551615' && die "vg_mda_copies over 2^64 - 1 shall not pass."
sel lv 'lv_read_ahead=auto' vol1 vol2 orig snap
sel lv 'lv_read_ahead=256k' abc xyz

View File

@@ -34,7 +34,7 @@ PID_SLEEP=$!
lvconvert --config 'activation/retry_deactivation=0' --merge $vg/$lv2
kill $PID_SLEEP
wait
wait "$PID_SLEEP" || true
# Remove everything
lvremove --yes $vg

View File

@@ -25,8 +25,10 @@ fill() {
cleanup_tail()
{
test -z "${SLEEP_PID-}" || kill $SLEEP_PID || true
wait
if test -n "${SLEEP_PID-}"; then
kill $SLEEP_PID || true
wait "$SLEEP_PID" || true
fi
vgremove -ff $vg1 || true
vgremove -ff $vg
aux teardown
@@ -99,36 +101,19 @@ fill 64k $vg1/snap50
lvcreate -s -l 25%ORIGIN -n snap25 $vg1/$lv
fill 32k $vg1/snap25
# Check we do not provide too much extra space
not fill 33k $vg1/snap25
# This feature works properly only with newer targets
if aux target_at_least dm-snapshot 1 10 0 ; then
# Check we do not provide too much extra space
fill 33k $vg1/snap25 && die "Snapshot should not be able to fit 33k!"
fi
lvs -a $vg1
lvremove -f $vg1
# Test virtual snapshot over /dev/zero
lvcreate --type snapshot -V50 -L10 -n $lv1 -s $vg1
CHECK_ACTIVE="active"
test ! -e LOCAL_CLVMD || CHECK_ACTIVE="local exclusive"
check lv_field $vg1/$lv1 lv_active "$CHECK_ACTIVE"
check lv_field $vg1/$lv1 lv_active "active"
lvchange -an $vg1
# On cluster snapshot gets exclusive activation
lvchange -ay $vg1
check lv_field $vg1/$lv1 lv_active "$CHECK_ACTIVE"
# Test removal of opened (but unmounted) snapshot (device busy) for a while
SLEEP_PID=$(aux hold_device_open $vg1 $lv1 60)
# Opened virtual snapshot device is not removable
# it should retry device removal for a few seconds
not lvremove -f $vg1/$lv1
kill $SLEEP_PID
SLEEP_PID=
# Wait for killed task, so there is no device holder
wait
lvremove -f $vg1/$lv1
check lv_not_exists $vg1 $lv1
# Check border size
@@ -180,10 +165,19 @@ lvremove -f $vg1
# This test expects extent size 1K
aux lvmconf "allocation/wipe_signatures_when_zeroing_new_lvs = 1"
lvcreate -aey -L4 -n $lv $vg1
$MKFS "$DM_DEV_DIR/$vg1/$lv"
lvcreate -c 8 -s -L1 -n snap $vg1/$lv
# Populate snapshot
#dd if=/dev/urandom of="$DM_DEV_DIR/$vg1/$lv" bs=4096 count=10
$MKFS "$DM_DEV_DIR/$vg1/$lv"
mkdir mnt
mount "$DM_DEV_DIR/$vg1/snap" mnt
# Opened virtual snapshot device is not removable
# it should retry device removal for a few seconds
not lvremove -f $vg1/snap
umount mnt
lvremove -f $vg1/snap
# Undeleted header would trigger attempt to access

View File

@@ -39,10 +39,7 @@ not lvconvert -m2 $vg/lv
lvconvert --mirrorlog core $vg/lv
# Log conversion (core -> mirrored)
# FIXME on cluster
SHOULD=""
test -e LOCAL_CLVMD && SHOULD=should
$SHOULD lvconvert --mirrorlog mirrored $vg/lv
lvconvert --mirrorlog mirrored $vg/lv
# Log conversion (mirrored -> core)
lvconvert --mirrorlog core $vg/lv

View File

@@ -27,7 +27,6 @@ lvcreate -an -Zn --type mirror -m 1 -l 1 -n mirror $vg
aux disable_dev "$dev1"
# FIXME:
# for the .cache use case we need to run pvscan
# to keep clvmd in sync.
pvscan
vgreduce --removemissing --force $vg
aux enable_dev "$dev1"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Copyright (C) 2012-2016 Red Hat, Inc. All rights reserved.
# Copyright (C) 2012-2025 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
@@ -21,17 +21,18 @@ export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false}
mntdir="${PREFIX}mnt with space"
mntusedir="${PREFIX}mntuse"
cleanup_mounted_and_teardown()
_cleanup_mounted_and_teardown()
{
[[ -z "${PID_SLEEP-}" ]] || { kill "$PID_SLEEP" || true ; }
umount "$mntdir" 2>/dev/null || true
umount "$mntusedir" 2>/dev/null || true
vgremove -ff $vg
aux teardown
}
is_lv_opened_()
_is_lv_opened()
{
test "$(get lv_field "$1" lv_device_open --binary)" = 1
[[ $(get lv_field "$1" lv_device_open --binary) = 1 ]]
}
#
@@ -42,23 +43,31 @@ export MKE2FS_CONFIG="$TESTDIR/lib/mke2fs.conf"
aux have_thin 1 0 0 || skip
# Simple implementation of umount when lvextend fails
#
# Simple implementation that umounts the volume when lvextend fails
# because we use autoextend_percent == 0.
#
# Note: A failing exit status from this script ensures
# the command is called repeatedly, which is needed
# for umount retry in this test.
#
cat <<- EOF >testcmd.sh
#!/bin/sh
echo "Data: \$DMEVENTD_THIN_POOL_DATA"
echo "Metadata: \$DMEVENTD_THIN_POOL_METADATA"
echo "Data: \${DMEVENTD_THIN_POOL_DATA-raised_event}"
echo "Metadata: \${DMEVENTD_THIN_POOL_METADATA-raised_event}"
"$TESTDIR/lib/lvextend" --use-policies \$1 || {
umount "$mntdir" || true
"$LVM_BINARY" lvextend --use-policies "\$1" || {
umount "$mntdir" || true
umount "$mntusedir" || true
return 0
}
test "\$($TESTDIR/lib/lvs -o selected -S "data_percent>95||metadata_percent>95" --noheadings \$1)" -eq 0 || {
umount "$mntdir" || true
umount "$mntusedir" || true
return 0
}
p=\$("$LVM_BINARY" lvs -o selected -S "data_percent>95||metadata_percent>95" --noheadings "\$1")
test "\$p" -eq 0 || exit 1
echo "No volume with percentage above 95%."
exit 0
EOF
chmod +x testcmd.sh
# Show prepared script
@@ -67,7 +76,7 @@ cat testcmd.sh
# Use autoextend percent 0 - so extension fails and triggers umount...
aux lvmconf "activation/thin_pool_autoextend_percent = 0" \
"activation/thin_pool_autoextend_threshold = 70" \
"dmeventd/thin_command = \"/$PWD/testcmd.sh\""
"dmeventd/thin_command = \"$PWD/testcmd.sh\""
aux prepare_dmeventd
@@ -82,13 +91,13 @@ mkfs.ext4 "$DM_DEV_DIR/$vg/$lv2"
lvchange --monitor y $vg/pool
mkdir "$mntdir" "$mntusedir"
trap 'cleanup_mounted_and_teardown' EXIT
trap '_cleanup_mounted_and_teardown' EXIT
mount "$DM_DEV_DIR/$vg/$lv1" "$mntdir"
mount "$DM_DEV_DIR/$vg/$lv2" "$mntusedir"
# Check both LVs are opened (~mounted)
is_lv_opened_ "$vg/$lv1"
is_lv_opened_ "$vg/$lv2"
_is_lv_opened "$vg/$lv1"
_is_lv_opened "$vg/$lv2"
touch "$mntusedir/file$$"
sync
@@ -103,25 +112,36 @@ dd if=/dev/zero of="$mntdir/file$$" bs=256K count=20 conv=fdatasync
lvs -a $vg
# Could loop here for a few secs so dmeventd can do some work
# Loop here for a few secs so dmeventd can do some work
# In the worst case check only happens every 10 seconds :(
# With low water mark it quickly discovers overflow and umounts $vg/$lv1
for i in $(seq 1 12) ; do
is_lv_opened_ "$vg/$lv1" || break
test $i -lt 12 || die "$mntdir should have been unmounted by dmeventd!"
for i in {1..12} ; do
_is_lv_opened "$vg/$lv1" || break
sleep 1
echo "$i"
done
lvs -a $vg
is_lv_opened_ "$vg/$lv2" || \
[[ $i -lt 12 ]] || die "$mntdir should have been unmounted by dmeventd!"
_is_lv_opened "$vg/$lv2" || \
die "$mntusedir is not mounted here (sleep already expired??)"
# Kill device holding process
kill $PID_SLEEP
wait
kill "$PID_SLEEP"
wait "$PID_SLEEP" || true
PID_SLEEP=
not is_lv_opened_ "$vg/$lv2" || {
mount
for i in {1..12} ; do
_is_lv_opened "$vg/$lv2" || break
sleep 1
echo "$i"
done
[[ $i -lt 12 ]] || {
mount | grep "$lv2"
die "$mntusedir should have been unmounted by dmeventd!"
}
exit 0 # -> _cleanup_mounted_and_teardown

View File

@@ -34,6 +34,7 @@ check lv_field $vg/$lv1 size "2.00m"
seq 0 315465 > 2M
md5sum 2M | cut -f 1 -d ' ' | tee MD5
dd if=2M of="$DM_DEV_DIR/mapper/$vg-$lv1" bs=512K conv=fdatasync >log 2>&1 &
DD_PID=$!
#dd if=2M of="$DM_DEV_DIR/mapper/$vg-$lv1" bs=2M oflag=direct &
# give it some time to fill thin-volume
@@ -48,7 +49,7 @@ lvextend -L+512k $vg/pool
lvextend -L+512k $vg/pool
# collect 'dd' result
wait
wait "$DD_PID" || true
cat log
lvs -a $vg

View File

@@ -28,7 +28,6 @@ vgcfgrestore -f bak0 $vg
not lvchange -aey $vg/$lv1 # check that activation is refused
# try once more to catch invalid memory access with valgrind
# when clvmd flushes cmd mem pool
not lvchange -aey $vg/$lv2 # check that activation is refused
not lvchange -aey $vg/$lv3 # check that activation is refused

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Copyright (C) 2019 Red Hat, Inc. All rights reserved.
# Copyright (C) 2019-2025 Red Hat, Inc. All rights reserved.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
@@ -13,23 +13,22 @@
# no automatic extensions, just umount
. lib/inittest --skip-with-lvmpolld
mntdir="${PREFIX}mnt with space"
PERCENT=70
cleanup_mounted_and_teardown()
_cleanup_mounted_and_teardown()
{
test -z "$PID_SLEEP" || { kill "$PID_SLEEP" || true ; }
[[ -z "${PID_SLEEP=}" ]] || { kill "$PID_SLEEP" || true ; }
umount "$mntdir" 2>/dev/null || true
vgremove -ff $vg
aux teardown
}
is_lv_opened_()
_is_lv_opened()
{
test "$(get lv_field "$1" lv_device_open --binary)" = 1
[[ $(get lv_field "$1" lv_device_open --binary) = 1 ]]
}
#
@@ -46,16 +45,19 @@ aux have_vdo 6 2 0 || skip
cat <<- EOF >testcmd.sh
#!/bin/sh
echo "VDO Pool: \$DMEVENTD_VDO_POOL"
echo "VDO Pool: \${DMEVENTD_VDO_POOL-raised_event}"
"$TESTDIR/lib/lvextend" --use-policies \$1 || {
"$LVM_BINARY" lvextend --use-policies "\$1" || {
umount "$mntdir" && exit 0
touch $PWD/TRIED_UMOUNT
touch "$PWD/TRIED_UMOUNT"
}
test "\$($TESTDIR/lib/lvs -o selected -S "data_percent>=$PERCENT" --noheadings \$1)" -eq 0 || {
echo "Percentage still above $PERCENT"
}
exit 1
p=\$("$LVM_BINARY" lvs -o selected -S "data_percent>=$PERCENT" --noheadings "\$1")
test "\$p" -eq 0 || exit 1
echo "No volume with percentage above $PERCENT%."
exit 0
EOF
chmod +x testcmd.sh
# Show prepared script
@@ -78,11 +80,11 @@ mkfs.ext4 -E nodiscard "$DM_DEV_DIR/$vg/$lv1"
lvchange --monitor y $vg/vpool
mkdir "$mntdir"
trap 'cleanup_mounted_and_teardown' EXIT
trap '_cleanup_mounted_and_teardown' EXIT
mount "$DM_DEV_DIR/$vg/$lv1" "$mntdir"
# Check both LV is opened (~mounted)
is_lv_opened_ "$vg/$lv1"
_is_lv_opened "$vg/$lv1"
touch "$mntdir/file$$"
sync
@@ -99,14 +101,15 @@ lvs -a $vg
# Could loop here for a few secs so dmeventd can do some work
# In the worst case check only happens every 10 seconds :(
for i in $(seq 1 12) ; do
is_lv_opened_ "$vg/$lv1" || break
test ! -f "TRIED_UMOUNT" || continue # finish loop quickly
for i in {1..12}; do
_is_lv_opened "$vg/$lv1" || break
test -f "TRIED_UMOUNT" && break # finish loop quickly
sleep 1
echo "$i"
done
rm -f "TRIED_UMOUNT"
test "$i" -eq 12 || die "$mntdir should NOT have been unmounted by dmeventd!"
[[ $i -lt 12 ]] || die "$mntdir should NOT have been unmounted by dmeventd!"
lvs -a $vg
@@ -117,10 +120,13 @@ PID_SLEEP=
# Could loop here for a few secs so dmeventd can do some work
# In the worst case check only happens every 10 seconds :(
for i in $(seq 1 12) ; do
is_lv_opened_ "$vg/$lv1" || break
test "$i" -lt 12 || die "$mntdir should have been unmounted by dmeventd!"
for i in {1..12} ; do
_is_lv_opened "$vg/$lv1" || break
sleep 1
echo "$i"
done
# vgremove is managed through cleanup_mounted_and_teardown()
[[ $i -lt 12 ]] || die "$mntdir should have been unmounted by dmeventd!"
# vgremove is managed through _cleanup_mounted_and_teardown()
exit 0

View File

@@ -10,7 +10,6 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
SKIP_WITH_CLVMD=1
. lib/inittest --skip-with-lvmpolld

View File

@@ -86,7 +86,6 @@ check vg_field $vg vg_extent_size 4.00m
check vg_field $vg max_lv 0
check vg_field $vg max_pv 0
ATTRS="wz--n--"
test -e LOCAL_CLVMD && ATTRS="wz--nc-"
if [[ "${LVM_TEST_LVMLOCKD:-0}" != 0 ]]; then
ATTRS="wz--ns-"
fi

View File

@@ -11,7 +11,6 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
SKIP_WITH_CLVMD=1
. lib/inittest --skip-with-lvmpolld

View File

@@ -120,9 +120,6 @@ COMM "vgsplit correctly splits mirror (log+leg on same dev) into $i VG ($j args)
lvremove -f $vg2/$lv1
vgremove -f $vg1 $vg2
# Can't use mirrored log without cmirrord
# TODO: Should work for inactive device, needs some fixes....
if test ! -e LOCAL_CLVMD ; then
COMM "vgsplit correctly splits mirror LV with mirrored log into $i VG ($j args)"
create_vg_ $vg1 "$dev1" "$dev2" "$dev3" "$dev4"
test $i = existing && create_vg_ $vg2 "$dev5"
@@ -170,7 +167,6 @@ COMM "vgsplit correctly splits mirror LV with mirrored log on same devs into $i
fi
lvremove -f $vg2/$lv1
vgremove -f $vg1 $vg2
fi
COMM "vgsplit correctly splits origin and snapshot LV into $i VG ($j args)"
create_vg_ $vg1 "$dev1" "$dev2"

View File

@@ -146,18 +146,6 @@ vgchange -an $vg1
not vgsplit $vg1 $vg2 "$dev3" 2>err;
vgremove -f $vg2 $vg1
# Restart clvm because using the same
# devs as lvm1 and then lvm2 causes problems.
if test -e LOCAL_CLVMD ; then
kill "$(< LOCAL_CLVMD)"
for i in $(seq 1 100) ; do
test $i -eq 100 && die "Shutdown of clvmd is too slow."
pgrep clvmd || break
sleep .1
done # wait for the pid removal
aux prepare_clvmd
fi
done
if [[ "${LVM_TEST_LVM1:-0}" = 0 ]] ; then

View File

@@ -1520,8 +1520,8 @@ arg(list_ARG, 'l', "list", 0, 0, 0,
"#lvmconfig\n"
"#dumpconfig\n"
"#config\n"
"List config settings with summarizing comment. This is the same as using\n"
"options --typeconfig list --withsummary.\n"
"Print a list of config settings instead of structured config settings tree.\n"
"If used without other options, this is the same as --typeconfig list --withsummary.\n"
"#vgcfgrestore\n"
"List metadata backup and archive files pertaining to the VG.\n"
"May be used with --file. Does not restore the VG.\n"

View File

@@ -109,11 +109,6 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
if (arg_is_set(cmd, configtype_ARG) && arg_is_set(cmd, list_ARG)) {
log_error("Only one of --type and --list permitted.");
return EINVALID_CMD_LINE;
}
if (arg_is_set(cmd, atversion_ARG)) {
if (arg_is_set(cmd, sinceversion_ARG)) {
log_error("Only one of --atversion and --sinceversion permitted.");
@@ -228,24 +223,9 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
}
}
if (!strcmp(type, "list") || arg_is_set(cmd, list_ARG)) {
if (!strcmp(type, "list")) {
tree_spec.listmode = 1;
tree_spec.type = CFG_DEF_TREE_LIST;
if (arg_is_set(cmd, withcomments_ARG)) {
log_error("--withcomments has no effect with --type list");
return EINVALID_CMD_LINE;
}
if (arg_is_set(cmd, withlocalpreamble_ARG)) {
log_error("--withlocalpreamble has no effect with --type list");
return EINVALID_CMD_LINE;
}
if (arg_is_set(cmd, withgeneralpreamble_ARG)) {
log_error("--withgeneralpreamble has no effect with --type list");
return EINVALID_CMD_LINE;
}
if (arg_is_set(cmd, valuesonly_ARG)) {
log_err("--valuesonly has no effect with --type list");
return EINVALID_CMD_LINE;
}
/* list type does not require status check */
} else if (!strcmp(type, "full")) {
tree_spec.type = CFG_DEF_TREE_FULL;
@@ -303,7 +283,14 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
goto out;
}
if (arg_is_set(cmd, withsummary_ARG) || arg_is_set(cmd, list_ARG))
if (arg_is_set(cmd, withsummary_ARG))
tree_spec.withsummary = 1;
/*
* This is for backwards compatibility with the original prehistoric
* 'dumpcofig --list' when the --typeconfig was not supported yet.
*/
if (arg_is_set(cmd, list_ARG) && !arg_is_set(cmd, configtype_ARG))
tree_spec.withsummary = 1;
if (arg_is_set(cmd, withcomments_ARG))
@@ -327,6 +314,28 @@ int dumpconfig(struct cmd_context *cmd, int argc, char **argv)
if (arg_is_set(cmd, valuesonly_ARG))
tree_spec.valuesonly = 1;
if (arg_is_set(cmd, list_ARG))
tree_spec.listmode = 1;
if (tree_spec.listmode) {
if (arg_is_set(cmd, withcomments_ARG)) {
log_error("--withcomments has no effect with --type list or --list");
return EINVALID_CMD_LINE;
}
if (arg_is_set(cmd, withlocalpreamble_ARG)) {
log_error("--withlocalpreamble has no effect with --type list or --list");
return EINVALID_CMD_LINE;
}
if (arg_is_set(cmd, withgeneralpreamble_ARG)) {
log_error("--withgeneralpreamble has no effect with --type list or --list");
return EINVALID_CMD_LINE;
}
if (arg_is_set(cmd, valuesonly_ARG)) {
log_err("--valuesonly has no effect with --type list or --list");
return EINVALID_CMD_LINE;
}
}
if (cft_check_handle)
tree_spec.check_status = cft_check_handle->status;

View File

@@ -3165,8 +3165,6 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
log_debug("Version: %s", LVM_VERSION);
log_debug("Parsing: %s", cmd->cmd_line);
log_debug_config(cmd);
if (!(cmd->command = _find_command(cmd, cmd->name, &argc, argv)))
return EINVALID_CMD_LINE;

View File

@@ -733,7 +733,7 @@ static int _vgchange_lock_stop(struct cmd_context *cmd, struct volume_group *vg)
return_0;
/* stop is the only --persist value that's accepted */
if (arg_is_set(cmd, persist_ARG) && !persist_stop(cmd, vg))
if (arg_is_set(cmd, persist_ARG) && (vg->pr & VG_PR_REQUIRE) && !persist_stop(cmd, vg))
log_warn("WARNING: PR stop failed, see lvmpersist stop.");
return 1;