mirror of
git://sourceware.org/git/lvm2.git
synced 2025-11-20 20:24:02 +03:00
Compare commits
57 Commits
dev-dct-lo
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec19a5905c | ||
|
|
12ce9ac97c | ||
|
|
6b04f24f41 | ||
|
|
9c3f376000 | ||
|
|
e0a8648828 | ||
|
|
d9da68b9b2 | ||
|
|
921d1fa339 | ||
|
|
13e56a6b6c | ||
|
|
0a896f1ca1 | ||
|
|
2d1b88a7c2 | ||
|
|
4be1c8b0e3 | ||
|
|
44c0eb935b | ||
|
|
60aae15eb3 | ||
|
|
aef860fa69 | ||
|
|
933d8944aa | ||
|
|
b2bc16591a | ||
|
|
e8109843e0 | ||
|
|
dceab4902a | ||
|
|
f200096eb3 | ||
|
|
154a42bdae | ||
|
|
c7a45237aa | ||
|
|
2c5f135482 | ||
|
|
dd03db75ac | ||
|
|
c8960be7d3 | ||
|
|
2660e92c06 | ||
|
|
492a5a070f | ||
|
|
a3cd838e5c | ||
|
|
332fa080de | ||
|
|
a3072d7241 | ||
|
|
81892cb4ef | ||
|
|
bbc14aafa8 | ||
|
|
52cc897902 | ||
|
|
b2ed0609bc | ||
|
|
018c4c1ace | ||
|
|
648b86a09f | ||
|
|
49e3a16003 | ||
|
|
ffab693183 | ||
|
|
3edc6eeb4e | ||
|
|
704e8f482a | ||
|
|
0ebea8ec6a | ||
|
|
7ff5ff5c85 | ||
|
|
5dbb1854c3 | ||
|
|
9dc6d0c948 | ||
|
|
c2b85e2f29 | ||
|
|
e2cf605037 | ||
|
|
2cb0f6598b | ||
|
|
4b9cd637d6 | ||
|
|
3fe8dd6254 | ||
|
|
9cccfe9c69 | ||
|
|
4190e73c1b | ||
|
|
8744c086ee | ||
|
|
44db4ebbbd | ||
|
|
3d011ab3df | ||
|
|
0f3cbac7ec | ||
|
|
0d25d18504 | ||
|
|
f3424d7edf | ||
|
|
704ed0cdcd |
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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) */
|
||||
};
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -348,4 +348,6 @@
|
||||
|
||||
#define DEFAULT_DEVICESFILE_BACKUP_LIMIT 50
|
||||
|
||||
#define DEFAULT_DEVICE_IDS_REFRESH 10
|
||||
|
||||
#endif /* _LVM_DEFAULTS_H */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
167
test/lib/aux.sh
167
test/lib/aux.sh
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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[@]}")'
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
SKIP_WITH_CLVMD=1
|
||||
|
||||
. lib/inittest --skip-with-lvmpolld
|
||||
|
||||
|
||||
501
test/shell/devicesfile-refresh-extended.sh
Normal file
501
test/shell/devicesfile-refresh-extended.sh
Normal 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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
test_description='test some blocking / non-blocking multi-vg operations'
|
||||
|
||||
SKIP_WITH_CLVMD=1
|
||||
|
||||
. lib/inittest --skip-with-lvmpolld
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
#########################################################################
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -86,9 +86,6 @@ esac
|
||||
|
||||
aux delay_dev "$dev2" 0
|
||||
|
||||
kill -9 %% || true
|
||||
wait
|
||||
|
||||
checksum_ "$mount_dir/random" >MD5_new
|
||||
|
||||
umount "$mount_dir"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
###########################################
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -33,6 +33,5 @@ not grep unknown out
|
||||
vgreduce --removemissing $vg
|
||||
check mirror $vg 4way
|
||||
lvchange -a n $vg/4way
|
||||
wait
|
||||
|
||||
vgremove -f $vg
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
SKIP_WITH_CLVMD=1
|
||||
|
||||
. lib/inittest --skip-with-lvmpolld
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user