1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-10-07 15:33:21 +03:00

Compare commits

..

26 Commits

Author SHA1 Message Date
David Teigland
9c8ef7823a lvmlockd: use persistent reservations for recovery with sanlock
The process of using persistent reservations for recovery:

host A owns a lock
host A fails
host B requests the lock
host B request fails because A owns the lock
host A enters the FAIL state in sanlock
host B retries the lock, and sees owner A is failed
host B runs lvmpersist to remove the PR key of host A
host B tells sanlock that host A is dead
host B retries the lock, which is now granted by sanlock

The new option: --setlockargs persist,notimeout
adds "persist" and "notimeout" components to the
lock_args string in the VG metadata, viewable with
vgs -o+lockargs.  The option is available in vgcreate
or vgchange.

. "persist" tells lvmlockd to remove the PR key of
  a failed host, by running lvmpersist, and set the
  sanlock host state to "dead".

. "notimeout" tells lvmlockd to configure sanlock
  leases to not time out.  sanlock does not use the
  watchdog to protect leases that do not time out.

With this combination, PR removal replaces the watchdog
for fencing hosts with expired leases that are blocking
other hosts.

The lock_args version component is "2.0.0" when
these new settings are used, otherwise remains
"1.0.0".  Previous lvm versions will not start a
VG with lockargs version 2.

Requires sanlock version 4.2.0 or later.
2025-10-03 09:57:10 -05:00
David Teigland
f15d948720 man lvmlockd: updates
Major rewrite of the beginning description/setup/introduction.
2025-09-23 11:19:13 -05:00
Zdenek Kabelac
d73b1ecf4b make: generate 2025-09-20 14:37:58 +02:00
Zdenek Kabelac
6016b2a7e4 commands: enusure stable sorting result
When options do have same name, use it's enum
as secondary key.
2025-09-20 14:36:28 +02:00
Zdenek Kabelac
9d9bb26fd5 commands: preserve any_ro_count
Previous patch unintentionally mixed these options
together while sorting.
2025-09-20 14:36:28 +02:00
David Teigland
5036e067e1 lvmpersist: fix hex digit key check
was incorrectly checking for a-z rather than a-f.
2025-09-19 14:21:11 -05:00
David Teigland
14cd96573f lvmpersist: run sg_turs to clear unit attention errors
Sometimes sg_persist/mpathpersist commands will fail if the
device returns a Unit Attention, e.g. if the host's last
registration was cleared.  Run sg_turs on each scsi/mpath
device at the start of each command to clear any UA errors.
This is simpler than adding code to retry commands throughout
the script if they happen to hit a UA error.
2025-09-19 12:43:37 -05:00
Zdenek Kabelac
622d222b1f make: generate 2025-09-19 14:49:41 +02:00
Zdenek Kabelac
095fb7eff8 test: update lisf of unusable kernels for raid resize 2025-09-19 14:48:46 +02:00
Zdenek Kabelac
5a367077d5 dmeventd: use define for mirror sync layer
Use existing define, just in case someone would have ever changed it.
2025-09-19 14:46:52 +02:00
Zdenek Kabelac
04cb7f742a command: add validation and sorting for args.h
Add comprehensive validation to ensure args.h option definitions follow
the established sorting rules:
1. Options without short options - sorted alphabetically
2. Alias options (without descriptions) - sorted alphabetically
3. Options with short options - sorted by uppercase symbol with
   lowercase variants first, then by long option name

Changes include:
- Enhanced validation logic in _find_lvm_command_enum() to check args.h
  ordering during MAN_PAGE_GENERATOR builds
- Improved error messages showing which entries violate sorting rules
- Added _sort_opt_args() function to sort optional/required option args
  for consistent man page and help generation output
- Fixed validation flag handling to properly report multiple errors

This ensures the args.h reorganization from the previous commit is
maintained and prevents future ordering regressions that could affect
code maintainability and generated documentation consistency.
2025-09-19 14:46:28 +02:00
Zdenek Kabelac
a8f1e2a83d args: sort by rules
tools: reorganize args.h argument definitions by sorting rules

Reorganize argument definitions in args.h to follow consistent sorting:
1. Options without short options - sorted alphabetically
2. Alias options (unadvertised, no description)
3. Options with short options - sorted by uppercase symbol
   with lowercase variants first, then by long option name

This improves code organization and maintainability by establishing
a clear, documented ordering for LVM command line argument definitions.

No functional changes - only reordering of existing argument definitions.

Also note there should never be a command using 2 options with the same
short option symbol
2025-09-19 14:46:28 +02:00
David Teigland
687b1a780f persist: support --setpersist in vgcreate
Previously, setpersist was only supported in vgchange
on an existing VG.  The PR is acquired exclusively before
the devices are modified, and in the case of a shared
VG the PR is subsequently changed to a shared mode.
2025-09-17 15:46:54 -05:00
David Teigland
57bf48c058 persist: use vgid in the key file name
adding a new helper function to create key file path.

Including vgid protects against cases of reading a
stale key file that was left over from a previous VG
with the same name.
2025-09-17 12:28:30 -05:00
David Teigland
ab1405034d persist: vgremove should check for other keys
vgremove should check for keys registered by other hosts
before removing the VG to avoid leaving dangling PR keys
on devices.  This involves refactoring the related commit
ca6fe99162 "lvmpersist: fix vgremove when another key is registered"
that separated persist_stop into before and after parts.
2025-09-17 11:38:08 -05:00
Peter Rajnoha
1f18ee1388 scripts: lvresize-fs-helper.sh: logmsg and not fail if unable to get XFS mount options for remount 2025-09-17 14:36:48 +02:00
Peter Rajnoha
f5852f2c9e WHATS_NEW: update 2025-09-17 12:16:26 +02:00
Peter Rajnoha
b6df5bf9d6 tests: lvresize-xfs: test quota mount options are preserved 2025-09-17 11:57:12 +02:00
Peter Rajnoha
55fda3afa5 scripts: lvresize-fs-helper.sh: detect and use proper quota mount options for XFS
When an XFS file system was previously mounted with quota mount options
(combination of -o uquota,gquota,pgquota) and then we are mounting the
file system as part of the lvresize/lvextend operation (through the fs
resize helper script), we need to preserve the quota mount options.

Otherwise, the XFS would need to recheck quotas - in that case the kernel
log contains:

  XFS (<device>): Quotacheck needed: Please wait.

This may take a long time, depending on the file system size.

Related issue: https://github.com/lvmteam/lvm2/issues/182
2025-09-17 11:57:02 +02:00
Arnout Engelen
6013977043 man: simplify vmautoactivation(7)
Previously this was hard-coded to: "Autoactivation commands use a number
of temp files in /run/lvm (with the expectation that /run is cleared
between boots.)"

Since c1bfc8737f it was made more generic,
but on some systems this logic leads to "Autoactivation commands use a
number of temp files in /run/lvm (with the expectation that /var/run
is cleared between boots)." which I'd say adds more confusion than it
solves.
2025-09-16 15:31:26 +00:00
David Teigland
b4a49811cd persist: fix start/stop with vgchange ay/an
vgchange -ay --persist start
	wasn't working, and should exclude shared VGs.
vgchange -an --persist stop
	code was missing for this case.
2025-09-12 15:20:42 -05:00
Zdenek Kabelac
09ceb425b7 make: generate 2025-09-12 14:23:35 +02:00
Zdenek Kabelac
fb708004fe man: print better arg for persist
As man pages now tend to print options as man macro reference,
we may still need some local 'specialization'.

ATM --persist option is known expection where command may accept only
certain argument to be recognized/allowed - so generic String printed
in Italic can be replaced with just specific argument printed in Bold.

TODO: recognize only cases where the 'generic' String is NOT used and
for rest of them use the common O_persist macro reference.
2025-09-12 14:23:14 +02:00
Zdenek Kabelac
b9e6337f04 codespell: typos 2025-09-11 16:18:19 +02:00
Marian Csontos
edd8b52967 doc: Few fixes and additions in pages
(cherry picked from commit 4561756bda8a0b5417c7cf5df269bb37af6eaec5)
2025-09-11 16:12:39 +02:00
David Teigland
58c534ba57 lvmpersist: fix remove exit code if an invalid local key is specified
Exit with an error if the wrong local key is specified.
2025-09-10 15:56:45 -05:00
54 changed files with 1888 additions and 1411 deletions

View File

@@ -1,5 +1,6 @@
Version 2.03.36 -
==================
Detect and use existing XFS quota mount options for lvresize --fs resize.
Version 2.03.35 - 09th September 2025
=====================================

View File

@@ -39,7 +39,7 @@ local {
# system_id = ""
# Configuration option local/pr_key.
# The local persistent reservation key in hexidecimal.
# The local persistent reservation key in hexadecimal.
# The value must be unique among all hosts using the same VG.
# The max length is 16 hex characters (8 bytes), plus an optional
# 0x prefix. If pr_key is not set, host_id will be used to create a key.

View File

@@ -934,9 +934,12 @@ AC_MSG_RESULT([$BUILD_LOCKDSANLOCK])
dnl -- Look for sanlock libraries
AS_IF([test "$BUILD_LOCKDSANLOCK" = "yes"], [
LOCKDSANLOCK_SUPPORT=410
# FIXME: forcing sanlock 4.2.0 for testing, default should be 370
# LOCKDSANLOCK_SUPPORT=370
PKG_CHECK_EXISTS(libsanlock_client >= 4.0.0, [LOCKDSANLOCK_SUPPORT=400])
PKG_CHECK_EXISTS(libsanlock_client >= 4.1.0, [LOCKDSANLOCK_SUPPORT=410])
PKG_CHECK_EXISTS(libsanlock_client >= 4.2.0, [LOCKDSANLOCK_SUPPORT=420])
LOCKDSANLOCK_SUPPORT=420
PKG_CHECK_MODULES(LIBSANLOCKCLIENT, libsanlock_client >= 3.7.0, [BUILD_LVMLOCKD="yes"])
AC_DEFINE_UNQUOTED([LOCKDSANLOCK_SUPPORT], [$LOCKDSANLOCK_SUPPORT], [Define version of sanlock.])
])

View File

@@ -15,6 +15,7 @@
#include "lib/misc/lib.h"
#include "dmeventd_lvm.h"
#include "daemons/dmeventd/libdevmapper-event.h"
#include "lib/metadata/metadata-exported.h" /* MIRROR_SYNC_LAYER */
#include "tools/lvm2cmd.h"
#include <pthread.h>
@@ -143,7 +144,7 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
}
/* strip off the mirror component designations */
if ((layer = strstr(lv, "_mimagetmp")) ||
if ((layer = strstr(lv, MIRROR_SYNC_LAYER)) ||
(layer = strstr(lv, "_mlog")))
*layer = '\0';

View File

@@ -182,10 +182,10 @@ static int listen_fd;
static int restart_pi;
static int restart_fds[2];
static int helper_send_fd; /* main loop sends requests to helper */
static int helper_recv_fd; /* main loop receives results from helper */
static int helper_pid;
static int helper_pi;
static int helper_send_fd = -1; /* main loop sends requests to helper */
static int helper_recv_fd = -1; /* main loop receives results from helper */
static int helper_pid = -1;
static int helper_pi = -1;
static uint32_t helper_msg_id = 1;
/*
@@ -516,7 +516,7 @@ int lockd_lockargs_get_user_flags(const char *str, uint32_t *flags)
int i;
if (!str)
return 0;
return -1;
dm_strncpy(buf, str, sizeof(buf));
@@ -533,11 +533,11 @@ int lockd_lockargs_get_user_flags(const char *str, uint32_t *flags)
*flags |= LOCKARGS_NOTIMEOUT;
else {
log_error("Unknown lockargs option value: %s", argv[i]);
return 0;
return -1;
}
}
log_debug("lockd_lockargs_get_user_flags %s = 0x%x", str, *flags);
return 1;
return 0;
}
struct lockspace *alloc_lockspace(void)
@@ -2893,6 +2893,8 @@ static void *lockspace_thread_main(void *arg_in)
log_debug("S %s ls actions entry: %s", ls->name, op_str(act->op));
act->ls_generation = ls->generation;
if (act->op == LD_OP_KILL_VG && act->rt == LD_RT_VG) {
/* Continue processing until DROP_VG arrives. */
log_debug("S %s kill_vg", ls->name);
@@ -3013,11 +3015,6 @@ static void *lockspace_thread_main(void *arg_in)
/* return success, allow the change */
/* list_del act and add_client_result done after rem_lockspace */
/*
list_del(&act->list);
act->result = 0;
add_client_result(act);
*/
/* the lockspace needs to be stopped for setlockargs_final */
ls->thread_work = 0;
@@ -3475,6 +3472,7 @@ static int add_lockspace_thread(const char *ls_name,
if (lockd_lockargs_get_meta_flags(vg_args, &ls->lock_args_flags) < 0) {
log_error("add_lockspace_thread %s lock_args invalid %s", ls->name, vg_args);
free(ls);
return -EARGS;
}
ls->no_timeout = (ls->lock_args_flags & LOCKARGS_NOTIMEOUT) ? 1 : 0;
@@ -4265,9 +4263,14 @@ static void work_fence(struct action *act, int *retry)
if (!found_done && !found_busy) {
rv = send_helper_request(act, ls_name, new_msg_id);
if (rv < 0) {
/* TODO: change act to FENCE_RESULT with error and move it to ls->actions */
/* change act to FENCE_RESULT error and move it to ls->actions */
log_error("work_fence %s failed to send helper request %u", vg_name, new_msg_id);
free_action(act);
pthread_mutex_lock(&ls->mutex);
list_del(&act->list);
act->op = LD_OP_FENCE_RESULT;
act->result = -ENOTCONN;
list_add_tail(&act->list, &ls->actions);
pthread_mutex_unlock(&ls->mutex);
}
}
pthread_mutex_unlock(&lockspaces_mutex);
@@ -4834,6 +4837,7 @@ static int client_send_result(struct client *cl, struct action *act)
"op_result = " FMTd64, (int64_t) act->result,
"lm_result = " FMTd64, (int64_t) act->lm_rv,
"result_flags = %s", result_flags[0] ? result_flags : "none",
"ls_generation = " FMTd64, (int64_t) act->ls_generation,
NULL);
}
@@ -5373,6 +5377,7 @@ static int print_lockspace(struct lockspace *ls, const char *prefix, int pos, in
"vg_args=%s "
"lm_type=%s "
"host_id=%u "
"generation=%llu "
"create_fail=%d "
"create_done=%d "
"thread_work=%d "
@@ -5389,6 +5394,7 @@ static int print_lockspace(struct lockspace *ls, const char *prefix, int pos, in
ls->vg_args,
lm_str(ls->lm_type),
ls->host_id,
(unsigned long long)ls->generation,
ls->create_fail ? 1 : 0,
ls->create_done ? 1 : 0,
ls->thread_work ? 1 : 0,

View File

@@ -184,6 +184,7 @@ struct action {
uint64_t ourkey;
uint64_t remkey;
uint64_t lv_size_bytes;
uint64_t ls_generation;
int8_t op; /* operation type LD_OP_ */
int8_t rt; /* resource type LD_RT_ */
int8_t mode; /* lock mode LD_LK_ */
@@ -749,18 +750,18 @@ static inline int lm_support_sanlock(void)
return 0;
}
void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner)
static inline void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner)
{
}
int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act)
static inline int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act)
{
return 0;
}
int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act)
static inline int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act)
{
return 0;
return -1;
}
#endif /* sanlock support */

View File

@@ -28,6 +28,8 @@
#define SANLK_ADD_NODELAY 0x00000002
/* FIXME: copied from sanlock header until the sanlock update is more widespread */
#define SANLK_GET_HOST_LOCAL 0x00000001
/* FIXME: copied from sanlock header until the sanlock update is more widespread */
#define SANLK_LSF_NO_TIMEOUT 0x00000004
#include <stddef.h>
#include <poll.h>
@@ -432,26 +434,6 @@ static int write_info_file(char *vg_name, uint32_t host_id, uint64_t generation,
return 0;
}
static int update_info_file(char *vg_name, int no_timeout_new)
{
uint32_t host_id;
uint64_t generation;
int sector_size;
int align_size;
int no_timeout;
int rv;
rv = read_info_file(vg_name, &host_id, &generation, &sector_size, &align_size, &no_timeout);
if (rv < 0)
return rv;
rv = write_info_file(vg_name, host_id, generation, sector_size, align_size, no_timeout_new);
if (rv < 0)
return rv;
return 0;
}
static void remove_info_file(struct lockspace *ls)
{
char path[PATH_MAX] = { 0 };
@@ -740,13 +722,20 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
int align_mb = 0;
int i, rv;
if (other_args && !lockd_lockargs_get_user_flags(other_args, &lock_args_flags)) {
if (other_args && (lockd_lockargs_get_user_flags(other_args, &lock_args_flags) < 0)) {
log_error("S %s init_vg_san unknown other args %s", ls_name, other_args);
return -EARGS;
}
no_timeout = (lock_args_flags & LOCKARGS_NOTIMEOUT) ? 1 :0;
persist = (lock_args_flags & LOCKARGS_PERSIST) ? 1 : 0;
#if LOCKDSANLOCK_SUPPORT < 420
if (no_timeout || persist) {
log_error("S %s init_vg_san sanlock 4.2 required for args %s", ls_name, other_args);
return -EARGS;
}
#endif
memset(&ss, 0, sizeof(ss));
memset(&rd, 0, sizeof(rd));
memset(&disk, 0, sizeof(disk));
@@ -2800,6 +2789,24 @@ int lm_is_running_sanlock(void)
return 1;
}
#if LOCKDSANLOCK_SUPPORT >= 420
static void update_info_file(char *vg_name, int no_timeout_new)
{
uint32_t host_id;
uint64_t generation;
int sector_size;
int align_size;
int no_timeout;
int rv;
rv = read_info_file(vg_name, &host_id, &generation, &sector_size, &align_size, &no_timeout);
if (rv < 0)
return;
write_info_file(vg_name, host_id, generation, sector_size, align_size, no_timeout_new);
}
void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner)
{
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
@@ -2812,7 +2819,7 @@ void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner)
host.generation = owner->generation;
rv = sanlock_set_host(&lms->ss, SANLK_SET_HOST_DEAD_EXT, 0, 0, &host);
if (rv < 0)
if (rv)
log_error("S %s set_host_dead_sanlock host_id %u gen %u error %d", ls->name, owner->host_id, owner->generation, rv);
}
@@ -2824,7 +2831,12 @@ int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act)
uint32_t ver_major, ver_minor;
int rv;
if (!lockd_lockargs_get_user_flags(act->other_args, &lock_args_flags)) {
if (!act->other_args[0]) {
log_error("S %s setlockargs_supported empty user lock args", ls->name);
return 0;
}
if (lockd_lockargs_get_user_flags(act->other_args, &lock_args_flags) < 0) {
log_error("S %s setlockargs_supported invalid user lock args %s", ls->name, act->other_args);
return 0;
}
@@ -2843,12 +2855,12 @@ int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act)
ver_major = (daemon_version & 0xFF000000) >> 24;
ver_minor = (daemon_version & 0x00FF0000) >> 16;
/* sanlock 4.1.0 added support for LOCKARGS_NOTIMEOUT or LOCKARGS_PERSIST. */
/* sanlock 4.2.0 added support for LOCKARGS_NOTIMEOUT or LOCKARGS_PERSIST. */
if (ver_major < 4)
return 0;
if ((ver_major == 4) && (ver_minor < 1))
if ((ver_major == 4) && (ver_minor < 2))
return 0;
return 1;
@@ -2869,7 +2881,12 @@ int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act)
int persist;
int rv;
if (!lockd_lockargs_get_user_flags(act->other_args, &lock_args_flags)) {
if (!act->other_args[0]) {
log_error("S %s setlockargs empty user lock args", ls_name);
return 0;
}
if (lockd_lockargs_get_user_flags(act->other_args, &lock_args_flags) < 0) {
log_error("S %s setlockargs invalid user lock args %s", ls_name, act->other_args);
return 0;
}
@@ -2934,3 +2951,19 @@ int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act)
return 0;
}
#else
void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner)
{
}
int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act)
{
return 0;
}
int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act)
{
return -EINVAL;
}
#endif /* LOCKDSANLOCK_SUPPORT >= 420 */

View File

@@ -72,6 +72,7 @@ incorrectly!
Make one by running `pvcreate /dev/sdX`.
See [pvcreate(8)](https://man7.org/linux/man-pages/man8/pvcreate.8.html). This step is optional.
* Volume Group (VG) consisting of one or more PVs is used as a pool from which LVs are allocated.
List VGs using [vgs(8)](https://man7.org/linux/man-pages/man8/vgs.8.html) or
[vgdisplay(8)](https://man7.org/linux/man-pages/man8/vgdisplay.8.html).
@@ -80,27 +81,34 @@ incorrectly!
To use LVM at least one Volume Group must be present on the system.
See [vgcreate(8)](https://man7.org/linux/man-pages/man8/vgcreate.8.html), and
[vgextend(8)](https://man7.org/linux/man-pages/man8/vgextend.8.html).
* Logical Volume (LV) is the block device usually visible to user to be used for file system.
List PVs using [lvs(8)](https://man7.org/linux/man-pages/man8/lvs.8.html) or
List LVs using [lvs(8)](https://man7.org/linux/man-pages/man8/lvs.8.html) or
[lvdisplay(8)](https://man7.org/linux/man-pages/man8/lvdisplay.8.html).
Make one by running `lvcreate [-n LVNAME] -L SIZE VGNAME`, and you are done!
See [vgcreate(8)](https://man7.org/linux/man-pages/man8/vgcreate.8.html).
See [lvcreate(8)](https://man7.org/linux/man-pages/man8/lvcreate.8.html).
To change size of LV it is recommended to use [lvresize(8)](https://man7.org/linux/man-pages/man8/lvresize.8.html) with `--resizefs` option.
To change properties of LV (e.g. to acivate/deactivate a volume, or change it to read only) use [lvchange(8)](https://man7.org/linux/man-pages/man8/lvchange.8.html).
To change the type of LV (e.g. change a linear volume to a RAID) use [lvconvert(8)](https://man7.org/linux/man-pages/man8/lvconvert.8.html).
## Avoiding Problems
Good start is to avoid using `{--force|-f}` and `{--yes|-y}` options which are
Good start is to **avoid using `{--force|-f}` and `{--yes|-y}` options** which are
often seen on internet discussions.
there is a possibility of data loss, LVM tools usually ask, so read the prompts
carefully! Using `--yes` removes these safety.
Also in some cases where it is too dangerous to proceed, e.g. device is used,
LVM refuses to do so, which can be overridden by `--force`.
Second, when resizing and especially when shrinking LVs it is always a good
idea to use `--resizefs` option which ensures the devices are resized in
Second, when **resizing** and especially when shrinking LVs it is always a good
idea to **use `--resizefs` option** which ensures the devices are resized in
correct order.
Third, if you still make a mess, never ever run fsck on damaged LV/FS, this is
Third, if you still make a mess, **never ever run fsck on damaged LV/FS**, this is
usually the final blow to your data. It is always better to ask first!

View File

@@ -2280,7 +2280,7 @@ cfg(local_system_id_CFG, "system_id", local_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_D
"#\n")
cfg(local_pr_key_CFG, "pr_key", local_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, 0, vsn(2, 3, 32), NULL, 0, NULL,
"The local persistent reservation key in hexidecimal.\n"
"The local persistent reservation key in hexadecimal.\n"
"The value must be unique among all hosts using the same VG.\n"
"The max length is 16 hex characters (8 bytes), plus an optional\n"
"0x prefix. If pr_key is not set, host_id will be used to create a key.\n")

View File

@@ -1056,7 +1056,7 @@ static int get_our_key_sanlock_start(struct cmd_context *cmd, struct volume_grou
/*
* Called after sanlock lockstart to check if a registered PR key contains the
* latest generation number (from sanlock) for the host, and if not to update
* the PR key. The sanlock lockstart atually returns the previous generation
* the PR key. The sanlock lockstart actually returns the previous generation
* number that was used for this host_id in the lockspace, and we expect that
* the next generation number just will be +1.
*
@@ -1096,7 +1096,7 @@ int persist_key_update(struct cmd_context *cmd, struct volume_group *vg, uint32_
/*
* When using an explicit pr_key setting, there's
* not sanlock generation number that needs updating.
* no sanlock generation number that needs updating.
*/
if (local_key)
return 1;
@@ -1169,8 +1169,6 @@ int persist_key_update(struct cmd_context *cmd, struct volume_group *vg, uint32_
return 0;
}
/* TODO: send new key to lvmlockd, e.g. call lockd_vg_is_started() and have that include our key */
log_debug("persist_key_update: updated 0x%llx to %s", (unsigned long long)our_key_val, new_key_buf);
return 1;
}
@@ -1572,23 +1570,78 @@ static int _run_stop(struct cmd_context *cmd, struct volume_group *vg, struct dm
}
/*
* Separate persist_stop_prepare() and persist_stop_run() is needed
* for vgremove, where prepare is needed before the normal vgremove,
* and run should happen after the normal vgremove.
* - prepare cannot happen after normal vgremove, because the list
* For vgremove, separate persist_stop into before and after parts:
* - before cannot happen after normal vgremove, because the list
* of PVs is no longer available.
* - run cannot happen before normal vgremove, because removing the
* - after cannot happen before normal vgremove, because removing the
* reservation will prevent writing metadata for normal vgremove if
* another host has a PR key registered (which may not happen in the
* normal usage pattern, but is still possible.)
*/
int persist_stop_prepare(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char **key)
int persist_vgremove_before(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char **key)
{
char *local_key = (char *)find_config_tree_str(cmd, local_pr_key_CFG, NULL);
int local_host_id = find_config_tree_int(cmd, local_host_id_CFG, NULL);
char our_key_buf[PR_KEY_BUF_SIZE] = { 0 };
uint64_t our_key_val = 0;
if (!local_key && !local_host_id)
return 1;
if (!get_our_key(cmd, vg, local_key, local_host_id, our_key_buf, &our_key_val))
return_0;
/*
* When removing a shared VG, verify that other hosts
* have stopped PR to avoid leaving dangling reservations.
*/
if (vg_is_shared(vg)) {
struct pv_list *pvl;
struct device *dev;
int found_key_count;
dm_list_iterate_items(pvl, &vg->pvs) {
if (!(dev = pvl->pv->dev))
continue;
found_key_count = 0;
if (!dev_find_key(cmd, dev, 0, 0, NULL, 0, NULL, 1, &found_key_count, NULL)) {
/* shouldn't happen */
log_error("Failed to get PR keys from %s", dev_name(dev));
return 0;
}
if (found_key_count > 1) {
log_error("Found %d PR keys on %s", found_key_count, dev_name(dev));
log_error("Stop PR for VG %s on other hosts (vgchange --persist stop)", vg->name);
return 0;
}
}
}
if (!pv_list_to_dev_list(cmd->mem, &vg->pvs, devs))
return_0;
if (!(*key = dm_pool_strdup(cmd->mem, our_key_buf)))
return_0;
return 1;
}
void persist_vgremove_after(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char *key)
{
_run_stop(cmd, vg, devs, key, 0);
persist_key_file_remove(cmd, vg);
}
int persist_stop(struct cmd_context *cmd, struct volume_group *vg)
{
DM_LIST_INIT(devs);
char *local_key = (char *)find_config_tree_str(cmd, local_pr_key_CFG, NULL);
int local_host_id = find_config_tree_int(cmd, local_host_id_CFG, NULL);
char our_key_buf[PR_KEY_BUF_SIZE] = { 0 };
uint64_t our_key_val = 0;
uint32_t cur_gen = 0;
if (!local_key && !local_host_id)
@@ -1602,34 +1655,15 @@ int persist_stop_prepare(struct cmd_context *cmd, struct volume_group *vg, struc
if (!get_our_key(cmd, vg, local_key, local_host_id, our_key_buf, &our_key_val))
return_0;
if (!pv_list_to_dev_list(cmd->mem, &vg->pvs, devs))
if (!pv_list_to_dev_list(cmd->mem, &vg->pvs, &devs))
return_0;
if (!(*key = dm_pool_strdup(cmd->mem, our_key_buf)))
if (!_run_stop(cmd, vg, &devs, our_key_buf, 0))
return_0;
return 1;
}
int persist_stop_run(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char *key)
{
if (!_run_stop(cmd, vg, devs, key, 0))
return_0;
return 1;
}
int persist_stop(struct cmd_context *cmd, struct volume_group *vg)
{
DM_LIST_INIT(devs);
char *key = NULL;
if (!persist_stop_prepare(cmd, vg, &devs, &key))
return_0;
if (!persist_stop_run(cmd, vg, &devs, key))
return_0;
return 1;
}
static int _persist_extend_shared(struct cmd_context *cmd, struct volume_group *vg,
uint64_t our_key_val, struct device *check_dev)
{
@@ -1965,7 +1999,8 @@ int persist_vgcreate_begin(struct cmd_context *cmd, char *vg_name, char *local_k
* access PR (typically WE), and starts PR with the normal sh access
* PR (typically WEAR), allowing other hosts to also use the new VG.
*/
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags)
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags,
uint64_t *our_key_ret)
{
DM_LIST_INIT(devs);
struct device_list *devl;
@@ -2032,7 +2067,7 @@ int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, ui
log_debug("stop PR on %d devs with local key %s", pv_count, our_key_buf_stop);
if (!_run_stop(cmd, vg, &devs, our_key_buf_stop, 0))
log_warn("WARNING: failed to stop PR");
log_warn("WARNING: failed to stop PR with key %s", our_key_buf_stop);
log_debug("start PR on %d devs with local key %llx", pv_count, (unsigned long long)our_key_val);
@@ -2073,6 +2108,9 @@ int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, ui
if (!write_key_file(cmd, vg, our_key_val))
stack;
if (our_key_ret)
*our_key_ret = our_key_val;
return 1;
}

View File

@@ -48,8 +48,9 @@ int persist_start(struct cmd_context *cmd, struct volume_group *vg,
char *local_key, int local_host_id, const char *remkey);
int persist_stop(struct cmd_context *cmd, struct volume_group *vg);
int persist_stop_prepare(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char **key);
int persist_stop_run(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char *key);
int persist_vgremove_before(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char **key);
void persist_vgremove_after(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char *key);
int persist_remove(struct cmd_context *cmd, struct volume_group *vg,
char *local_key, int local_host_id, const char *remkey);
@@ -61,7 +62,8 @@ int persist_start_extend(struct cmd_context *cmd, struct volume_group *vg);
int persist_vgcreate_begin(struct cmd_context *cmd, char *vg_name, char *local_key, int local_host_id,
uint32_t set_flags, struct dm_list *devs);
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags);
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags,
uint64_t *our_key_ret);
int persist_upgrade_ex(struct cmd_context *cmd, struct volume_group *vg, uint64_t *our_key_held);
int persist_upgrade_stop(struct cmd_context *cmd, struct volume_group *vg, uint64_t our_key_val);

View File

@@ -149,6 +149,27 @@ int lockd_lockargs_get_user_flags(const char *str, uint32_t *flags)
return 0;
}
}
if (((*flags & LOCKARGS_PERSIST) && (*flags & LOCKARGS_NOPERSIST)) ||
((*flags & LOCKARGS_TIMEOUT) && (*flags & LOCKARGS_NOTIMEOUT))) {
log_error("Invalid setlockargs option combination: %s", str);
return 0;
}
/*
* . nopersist and timeout: default
* . persist and notimeout: permitted with setlockargs
*
* FIXME: when tested, allow
* . nopersist and notimeout: requires manual set host dead
* . persist and timeout: watchdog still resets host when PR is used
*/
if (((*flags & LOCKARGS_PERSIST) && !(*flags & LOCKARGS_NOTIMEOUT)) ||
((*flags & LOCKARGS_NOTIMEOUT) && !(*flags & LOCKARGS_PERSIST))) {
log_error("setlockargs persist and notimeout are currently required together.");
return 0;
}
return 1;
}
@@ -204,7 +225,7 @@ static char *_owner_str(struct owner *owner)
#define NO_LOCKD_RESULT (-1000)
static int _lockd_result(struct cmd_context *cmd, const char *req_name, daemon_reply reply,
int *result, uint32_t *lockd_flags, struct owner *owner)
int *result, uint32_t *lockd_flags, struct owner *owner, uint64_t *our_generation)
{
int reply_result;
const char *str;
@@ -241,6 +262,9 @@ static int _lockd_result(struct cmd_context *cmd, const char *req_name, daemon_r
owner->name = dm_pool_strdup(cmd->mem, str);
}
if (our_generation)
*our_generation = (uint64_t)daemon_reply_int(reply, "our_generation", 0);
log_debug("lockd %s result: %d", req_name, reply_result);
return 1;
}
@@ -455,7 +479,8 @@ static int _lockd_request(struct cmd_context *cmd,
const struct lvmlockd_pvs *lock_pvs,
int *result,
uint32_t *lockd_flags,
struct owner *owner)
struct owner *owner,
uint64_t *our_generation)
{
const char *cmd_name = get_cmd_name();
daemon_reply reply;
@@ -492,7 +517,7 @@ static int _lockd_request(struct cmd_context *cmd,
"lv_lock_args = %s", lv_lock_args ?: "none",
NULL);
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner))
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner, our_generation))
goto fail;
/*
@@ -512,7 +537,7 @@ static int _lockd_request(struct cmd_context *cmd,
"vg_lock_args = %s", vg_lock_args ?: "none",
NULL);
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner))
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner, our_generation))
goto fail;
/*
@@ -530,7 +555,7 @@ static int _lockd_request(struct cmd_context *cmd,
"vg_lock_type = %s", vg_lock_type ?: "none",
NULL);
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner))
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner, our_generation))
goto fail;
log_debug("lockd %s %s result %d %x",
@@ -801,7 +826,7 @@ static int _handle_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg)
"lv_size_bytes = " FMTd64, (int64_t) lv_size_bytes,
NULL);
if (!_lockd_result(cmd, "find_free_lock", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "find_free_lock", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -856,7 +881,7 @@ static int _init_vg(struct cmd_context *cmd, struct volume_group *vg,
"vg_lock_type = %s", lock_type,
NULL);
if (!_lockd_result(cmd, "init_vg", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "init_vg", reply, &result, NULL, NULL, NULL)) {
ret = 0;
result = -ELOCKD;
} else {
@@ -1054,7 +1079,7 @@ static int _init_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg, in
"opts = %s", opts ?: "none",
NULL);
if (!_lockd_result(cmd, "init_vg", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "init_vg", reply, &result, NULL, NULL, NULL)) {
ret = 0;
result = -ELOCKD;
} else {
@@ -1156,7 +1181,7 @@ static int _free_vg(struct cmd_context *cmd, struct volume_group *vg)
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "free_vg", reply, &result, &lockd_flags, NULL)) {
if (!_lockd_result(cmd, "free_vg", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1217,7 +1242,7 @@ int lockd_vg_is_busy(struct cmd_context *cmd, struct volume_group *vg)
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "busy_vg", reply, &result, &lockd_flags, NULL)) {
if (!_lockd_result(cmd, "busy_vg", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 1;
goto out;
}
@@ -1280,7 +1305,7 @@ static int _free_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg)
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "free_vg", reply, &result, &lockd_flags, NULL)) {
if (!_lockd_result(cmd, "free_vg", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1446,7 +1471,7 @@ void lockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg)
case LOCK_TYPE_CLVM:
break;
case LOCK_TYPE_SANLOCK:
persist_key_file_remove(cmd, vg->name);
persist_key_file_remove(cmd, vg);
break;
case LOCK_TYPE_DLM:
_free_vg_dlm(cmd, vg);
@@ -1570,7 +1595,7 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, uint64_t ou
NULL);
}
if (!_lockd_result(cmd, "start_vg", reply, &result, &lockd_flags, NULL)) {
if (!_lockd_result(cmd, "start_vg", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 0;
result = -ELOCKD;
} else {
@@ -1660,7 +1685,7 @@ int lockd_stop_vg(struct cmd_context *cmd, struct volume_group *vg)
"vg_name = %s", vg->name,
NULL);
if (!_lockd_result(cmd, "stop_vg", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "stop_vg", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1706,7 +1731,7 @@ int lockd_start_wait(struct cmd_context *cmd)
"pid = " FMTd64, (int64_t) getpid(),
NULL);
if (!_lockd_result(cmd, "start_wait", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "start_wait", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1825,7 +1850,7 @@ int lockd_global_create(struct cmd_context *cmd, const char *def_mode, const cha
req:
if (!_lockd_request(cmd, "lock_gl",
NULL, vg_lock_type, NULL, NULL, NULL, NULL, mode, NULL,
NULL, &result, &lockd_flags, &owner)) {
NULL, &result, &lockd_flags, &owner, NULL)) {
/* No result from lvmlockd, it is probably not running. */
log_error("Global lock failed: check that lvmlockd is running.");
return 0;
@@ -2089,7 +2114,7 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode)
if (!_lockd_request(cmd, "lock_gl",
NULL, NULL, NULL, NULL, NULL, NULL, mode, opts,
NULL, &result, &lockd_flags, &owner)) {
NULL, &result, &lockd_flags, &owner, NULL)) {
/* No result from lvmlockd, it is probably not running. */
/* We don't care if an unlock fails. */
@@ -2326,6 +2351,7 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode,
uint32_t flags, uint32_t *lockd_state)
{
struct owner owner = { 0 };
uint64_t our_generation = 0;
char opt_buf[64] = {};
const char *mode = NULL;
const char *opts = NULL;
@@ -2440,7 +2466,7 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode,
if (!_lockd_request(cmd, "lock_vg",
vg_name, NULL, NULL, NULL, NULL, NULL, mode, opts,
NULL, &result, &lockd_flags, &owner)) {
NULL, &result, &lockd_flags, &owner, &our_generation)) {
/*
* No result from lvmlockd, it is probably not running.
* Decide if it is ok to continue without a lock in
@@ -2653,7 +2679,7 @@ out:
*/
if ((lockd_flags & LD_RF_DUP_GL_LS) && strcmp(mode, "un"))
log_warn("Duplicate sanlock global lock in VG %s", vg_name);
return ret;
}
@@ -2698,7 +2724,7 @@ int lockd_vg_update(struct volume_group *vg)
"version = " FMTd64, (int64_t) vg->seqno,
NULL);
if (!_lockd_result(vg->cmd, "vg_update", reply, &result, NULL, NULL)) {
if (!_lockd_result(vg->cmd, "vg_update", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -2712,6 +2738,7 @@ int lockd_vg_is_started(struct cmd_context *cmd, struct volume_group *vg, uint32
{
daemon_reply reply;
struct owner owner = { 0 };
uint64_t our_generation = 0;
int result;
int ret = 0;
@@ -2729,7 +2756,7 @@ int lockd_vg_is_started(struct cmd_context *cmd, struct volume_group *vg, uint32
"vg_name = %s", vg->name,
NULL);
if (!_lockd_result(vg->cmd, "vg_status", reply, &result, NULL, &owner)) {
if (!_lockd_result(vg->cmd, "vg_status", reply, &result, NULL, &owner, &our_generation)) {
log_debug("lockd_vg_status %s no result", vg->name);
goto out;
}
@@ -2739,6 +2766,16 @@ int lockd_vg_is_started(struct cmd_context *cmd, struct volume_group *vg, uint32
goto out;
}
/*
* The local host generation number is returned
* in both fields, they should always match.
*/
if (our_generation && owner.generation &&
((uint32_t)our_generation != owner.generation)) {
log_warn("WARNING: lvmlockd local host generation mismatch %llu vs %u",
(unsigned long long)our_generation, owner.generation);
}
log_debug("lockd_vg_status %s host_id %u gen %u",
vg->name, owner.host_id, owner.generation);
@@ -2772,7 +2809,7 @@ static int _query_lv(struct cmd_context *cmd, struct volume_group *vg,
"lv_lock_args = %s", lock_args ?: "none",
NULL);
if (!_lockd_result(cmd, "query_lock_lv", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "query_lock_lv", reply, &result, NULL, NULL, NULL)) {
/* No result from lvmlockd, it is probably not running. */
log_error("Lock query failed for LV %s/%s", vg->name, lv_name);
return 0;
@@ -2845,6 +2882,7 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
const char *opts = NULL;
const char *mode = NULL;
uint32_t lockd_flags;
uint64_t our_generation = 0;
int refreshed = 0;
int result;
struct lvmlockd_pvs lock_pvs;
@@ -2943,7 +2981,7 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
if (!_lockd_request(cmd, "lock_lv",
vg->name, vg->lock_type, vg->lock_args,
lv_name, lv_uuid, lock_args, mode, opts,
&lock_pvs, &result, &lockd_flags, NULL)) {
&lock_pvs, &result, &lockd_flags, NULL, NULL)) {
_lockd_free_pv_list(&lock_pvs);
/* No result from lvmlockd, it is probably not running. */
log_error("Locking failed for LV %s/%s", vg->name, lv_name);
@@ -2954,7 +2992,7 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
if (!_lockd_request(cmd, "lock_lv",
vg->name, vg->lock_type, vg->lock_args,
lv_name, lv_uuid, lock_args, mode, opts,
NULL, &result, &lockd_flags, &owner)) {
NULL, &result, &lockd_flags, &owner, &our_generation)) {
/* No result from lvmlockd, it is probably not running. */
log_error("Locking failed for LV %s/%s", vg->name, lv_name);
return 0;
@@ -3884,7 +3922,7 @@ static int _init_lv_sanlock(struct cmd_context *cmd, struct volume_group *vg,
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "init_lv", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "init_lv", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -3959,7 +3997,7 @@ static int _free_lv(struct cmd_context *cmd, struct volume_group *vg,
"lv_lock_args = %s", lock_args ?: "none",
NULL);
if (!_lockd_result(cmd, "free_lv", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "free_lv", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -4224,7 +4262,7 @@ int lockd_rename_vg_before(struct cmd_context *cmd, struct volume_group *vg)
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "rename_vg_before", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "rename_vg_before", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -4289,7 +4327,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "rename_vg_final", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "rename_vg_final", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -4330,7 +4368,7 @@ const char *lockd_running_lock_type(struct cmd_context *cmd, int *found_multiple
"pid = " FMTd64, (int64_t) getpid(),
NULL);
if (!_lockd_result(cmd, "running_lm", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "running_lm", reply, &result, NULL, NULL, NULL)) {
log_error("Failed to get result from lvmlockd");
goto out;
}
@@ -4451,7 +4489,7 @@ int lockd_lv_refresh(struct cmd_context *cmd, struct lvresize_params *lp)
"path = %s", path,
NULL);
if (!_lockd_result(cmd, "refresh_lv", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "refresh_lv", reply, &result, NULL, NULL, NULL)) {
/* No result from lvmlockd, it is probably not running. */
log_error("LV refresh failed for LV %s", path);
return 0;
@@ -4605,7 +4643,7 @@ int lockd_setlockargs(struct cmd_context *cmd, struct volume_group *vg, const ch
"set_lock_args = %s", set_args,
NULL);
if (!_lockd_result(cmd, "setlockargs_vg_before", reply, &result, &lockd_flags, NULL)) {
if (!_lockd_result(cmd, "setlockargs_vg_before", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 0;
goto out;
}
@@ -4661,7 +4699,7 @@ int lockd_setlockargs(struct cmd_context *cmd, struct volume_group *vg, const ch
"set_lock_args = %s", set_args,
NULL);
if (!_lockd_result(cmd, "setlockargs_vg_final", reply, &result, &lockd_flags, NULL)) {
if (!_lockd_result(cmd, "setlockargs_vg_final", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 0;
goto out;
}

View File

@@ -341,4 +341,3 @@ void split_line(char *buf, int *argc, char **argv, int max_args, char sep)
}
*argc = i;
}

View File

@@ -452,49 +452,49 @@ required, after which the others are optional.
(
.O_contiguous
.in +2n
.O_setactivationskip
.br
.O_persistent
.br
.O_permission
.br
.O_readahead
.br
.O_setactivationskip
.br
.O_zero
.br
.O_persistent
.br
.O_addtag
.br
.O_deltag
.br
.O_alloc
.br
.O_compression
.br
.O_deduplication
.br
.O_detachprofile
.br
.O_metadataprofile
.br
.O_setautoactivation
.br
.O_errorwhenfull
.br
.O_discards
.br
.O_cachemode
.br
.O_cachepolicy
.br
.O_cachesettings
.br
.O_minrecoveryrate
.O_compression
.br
.O_deduplication
.br
.O_deltag
.br
.O_detachprofile
.br
.O_discards
.br
.O_errorwhenfull
.br
.O_integritysettings
.br
.O_maxrecoveryrate
.br
.O_vdosettings
.O_metadataprofile
.br
.O_integritysettings
.O_minrecoveryrate
.br
.O_setautoactivation
.br
.O_vdosettings
.br
.O_writebehind
.br
@@ -508,11 +508,11 @@ required, after which the others are optional.
]
.br
[
.O_poll
.O_monitor
]
.br
[
.O_monitor
.O_poll
]
.br
[ COMMON_OPTIONS ]
@@ -583,11 +583,11 @@ Activate or deactivate an LV.
\fIVG\fP|\fILV\fP|\fITag\fP|\fISelect\fP\ .\|.\|.\&
.RS
[
.O_partial
.O_ignoreactivationskip
]
.br
[
.O_ignoreactivationskip
.O_partial
]
.br
[
@@ -595,7 +595,7 @@ Activate or deactivate an LV.
]
.br
[
.O_poll
.O_ignorelockingfailure
]
.br
[
@@ -603,17 +603,17 @@ Activate or deactivate an LV.
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_sysinit
.O_poll
]
.br
[
.O_readonly
]
.br
[
.O_sysinit
]
.br
[ COMMON_OPTIONS ]
.RE
.
@@ -636,11 +636,11 @@ Reactivate an LV using the latest metadata.
]
.br
[
.O_poll
.O_monitor
]
.br
[
.O_monitor
.O_poll
]
.br
[ COMMON_OPTIONS ]
@@ -683,26 +683,26 @@ Start or stop processing an LV conversion.
Make the minor device number persistent for an LV.
.P
.B lvchange
.O_persistent
.O_minor
.O_persistent
\fILV\fP
.RS
[
.O_major
]
.br
[
.O_activate
]
.br
[
.O_poll
.O_major
]
.br
[
.O_monitor
]
.br
[
.O_poll
]
.br
[ COMMON_OPTIONS ]
.RE
.P

View File

@@ -620,6 +620,10 @@ Convert LV to striped.
\fILV\fP
.RS
[
.O_interval
]
.br
[
.O_stripesize
]
.br
@@ -628,10 +632,6 @@ Convert LV to striped.
]
.br
[
.O_interval
]
.br
[
.O_stripes
]
.br
@@ -651,7 +651,7 @@ Convert LV to type mirror (also see type raid1),
\fILV\fP
.RS
[
.O_mirrors
.O_interval
]
.br
[
@@ -659,21 +659,21 @@ Convert LV to type mirror (also see type raid1),
]
.br
[
.O_mirrors
]
.br
[
.O_regionsize
]
.br
[
.O_interval
.O_mirrorlog
]
.br
[
.O_stripes
]
.br
[
.O_mirrorlog
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIPV\fP\ .\|.\|.\& ]
@@ -691,7 +691,7 @@ Convert LV to raid or change raid layout
\fILV\fP
.RS
[
.O_mirrors
.O_interval
]
.br
[
@@ -699,11 +699,11 @@ Convert LV to raid or change raid layout
]
.br
[
.O_regionsize
.O_mirrors
]
.br
[
.O_interval
.O_regionsize
]
.br
[
@@ -726,11 +726,11 @@ Convert LV to raid1 or mirror, or change number of mirror images.
\fILV\fP
.RS
[
.O_regionsize
.O_interval
]
.br
[
.O_interval
.O_regionsize
]
.br
[
@@ -757,11 +757,11 @@ Convert raid LV to change number of stripe images.
]
.br
[
.O_regionsize
.O_stripesize
]
.br
[
.O_stripesize
.O_regionsize
]
.br
[ COMMON_OPTIONS ]
@@ -861,15 +861,11 @@ raid
Convert LV to a thin LV, using the original LV as an external origin.
.P
.B lvconvert
\fB--type\fP \fBthin\fP
\fB--thinpool\fP \fILV\fP
\fB--type\fP \fBthin\fP
\fILV1\fP
.RS
[
.O_thin
]
.br
[
.O_chunksize
]
.br
@@ -878,6 +874,10 @@ Convert LV to a thin LV, using the original LV as an external origin.
]
.br
[
.O_thin
]
.br
[
.O_wipesignatures
]
.br
@@ -886,6 +886,10 @@ Convert LV to a thin LV, using the original LV as an external origin.
]
.br
[
.O_metadataprofile
]
.br
[
.O_originname
]
.br
@@ -901,10 +905,6 @@ Convert LV to a thin LV, using the original LV as an external origin.
.O_poolmetadataspare
]
.br
[
.O_metadataprofile
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIPV\fP\ .\|.\|.\& ]
@@ -930,10 +930,6 @@ Convert LV to a thin LV, using LV as thin-pool data volume.
\fILV1\fP
.RS
[
.O_thin
]
.br
[
.O_chunksize
]
.br
@@ -942,6 +938,10 @@ Convert LV to a thin LV, using LV as thin-pool data volume.
]
.br
[
.O_thin
]
.br
[
.O_wipesignatures
]
.br
@@ -950,6 +950,10 @@ Convert LV to a thin LV, using LV as thin-pool data volume.
]
.br
[
.O_metadataprofile
]
.br
[
.O_poolmetadata
]
.br
@@ -961,10 +965,6 @@ Convert LV to a thin LV, using LV as thin-pool data volume.
.O_poolmetadataspare
]
.br
[
.O_metadataprofile
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIPV\fP\ .\|.\|.\& ]
@@ -987,23 +987,19 @@ error
Attach a cache pool to an LV, converts the LV to type cache.
.P
.B lvconvert
\fB--type\fP \fBcache\fP
\fB--cachepool\fP \fILV\fP
\fB--type\fP \fBcache\fP
\fILV1\fP
.RS
[
.O_cache
]
.br
[
.O_zero
]
.br
[
.O_chunksize
]
.br
[
.O_cache
]
.br
[
.O_readahead
]
.br
@@ -1012,6 +1008,10 @@ Attach a cache pool to an LV, converts the LV to type cache.
]
.br
[
.O_zero
]
.br
[
.O_cachemetadataformat
]
.br
@@ -1028,6 +1028,10 @@ Attach a cache pool to an LV, converts the LV to type cache.
]
.br
[
.O_metadataprofile
]
.br
[
.O_poolmetadata
]
.br
@@ -1039,10 +1043,6 @@ Attach a cache pool to an LV, converts the LV to type cache.
.O_poolmetadataspare
]
.br
[
.O_metadataprofile
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIPV\fP\ .\|.\|.\& ]
@@ -1068,8 +1068,8 @@ error
Attach a writecache to an LV, converts the LV to type writecache.
.P
.B lvconvert
\fB--type\fP \fBwritecache\fP
.O_cachevol
\fB--type\fP \fBwritecache\fP
\fILV1\fP
.RS
[
@@ -1092,11 +1092,15 @@ thinpool
Attach a cache to an LV, converts the LV to type cache.
.P
.B lvconvert
\fB--type\fP \fBcache\fP
.O_cachevol
\fB--type\fP \fBcache\fP
\fILV1\fP
.RS
[
.O_chunksize
]
.br
[
.O_cache
]
.br
@@ -1105,10 +1109,6 @@ Attach a cache to an LV, converts the LV to type cache.
]
.br
[
.O_chunksize
]
.br
[
.O_cachemetadataformat
]
.br
@@ -1144,16 +1144,16 @@ thinpool
Add a writecache to an LV, using a specified cache device.
.P
.B lvconvert
\fB--type\fP \fBwritecache\fP
.O_cachedevice
\fB--type\fP \fBwritecache\fP
\fILV1\fP
.RS
[
.O_cachesize
.O_cachesettings
]
.br
[
.O_cachesettings
.O_cachesize
]
.br
[ COMMON_OPTIONS ]
@@ -1172,8 +1172,8 @@ thinpool
Add a cache to an LV, using a specified cache device.
.P
.B lvconvert
\fB--type\fP \fBcache\fP
.O_cachedevice
\fB--type\fP \fBcache\fP
\fILV1\fP
.RS
[
@@ -1181,11 +1181,11 @@ Add a cache to an LV, using a specified cache device.
]
.br
[
.O_cachesize
.O_cachesettings
]
.br
[
.O_cachesettings
.O_cachesize
]
.br
[ COMMON_OPTIONS ]
@@ -1208,11 +1208,11 @@ Convert LV to type thin-pool (existing data on LV will be erased).
\fILV1\fP
.RS
[
.O_stripesize
.O_chunksize
]
.br
[
.O_chunksize
.O_stripesize
]
.br
[
@@ -1228,7 +1228,11 @@ Convert LV to type thin-pool (existing data on LV will be erased).
]
.br
[
.O_stripes
.O_compression
]
.br
[
.O_deduplication
]
.br
[
@@ -1240,22 +1244,14 @@ Convert LV to type thin-pool (existing data on LV will be erased).
]
.br
[
.O_metadataprofile
]
.br
[
.O_pooldatavdo
]
.br
[
.O_compression
]
.br
[
.O_deduplication
]
.br
[
.O_vdosettings
]
.br
[
.O_poolmetadata
]
.br
@@ -1268,7 +1264,11 @@ Convert LV to type thin-pool (existing data on LV will be erased).
]
.br
[
.O_metadataprofile
.O_stripes
]
.br
[
.O_vdosettings
]
.br
[ COMMON_OPTIONS ]
@@ -1297,10 +1297,6 @@ Convert LV to type cache-pool (existing data on LV will be erased).
\fILV1\fP
.RS
[
.O_zero
]
.br
[
.O_chunksize
]
.br
@@ -1313,6 +1309,10 @@ Convert LV to type cache-pool (existing data on LV will be erased).
]
.br
[
.O_zero
]
.br
[
.O_cachemetadataformat
]
.br
@@ -1329,6 +1329,10 @@ Convert LV to type cache-pool (existing data on LV will be erased).
]
.br
[
.O_metadataprofile
]
.br
[
.O_poolmetadata
]
.br
@@ -1340,10 +1344,6 @@ Convert LV to type cache-pool (existing data on LV will be erased).
.O_poolmetadataspare
]
.br
[
.O_metadataprofile
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIPV\fP\ .\|.\|.\& ]
@@ -1371,11 +1371,11 @@ Convert LV to type vdopool (existing data on LV will be erased).
]
.br
[
.O_virtualsize
.O_readahead
]
.br
[
.O_readahead
.O_virtualsize
]
.br
[
@@ -1395,11 +1395,11 @@ Convert LV to type vdopool (existing data on LV will be erased).
]
.br
[
.O_vdosettings
.O_metadataprofile
]
.br
[
.O_metadataprofile
.O_vdosettings
]
.br
[ COMMON_OPTIONS ]
@@ -1483,11 +1483,11 @@ origin LV (first arg) to reverse a splitsnapshot command.
\fILV\fP \fILV1\fP
.RS
[
.O_snapshot
.O_chunksize
]
.br
[
.O_chunksize
.O_snapshot
]
.br
[
@@ -1522,11 +1522,11 @@ Repair a cache pool.
]
.br
[
.O_usepolicies
.O_poolmetadataspare
]
.br
[
.O_poolmetadataspare
.O_usepolicies
]
.br
[ COMMON_OPTIONS ]
@@ -1587,7 +1587,7 @@ Add or remove data integrity checksums to raid images.
\fILV1\fP
.RS
[
.O_raidintegritymode
.O_integritysettings
]
.br
[
@@ -1595,7 +1595,7 @@ Add or remove data integrity checksums to raid images.
]
.br
[
.O_integritysettings
.O_raidintegritymode
]
.br
[ COMMON_OPTIONS ]
@@ -2374,8 +2374,8 @@ mirror
Convert LV to a thin LV, using the original LV as an external origin.
.P
.B lvconvert
.O_thin
\fB--thinpool\fP \fILV\fP
.O_thin
\fILV1\fP
.RS
[ \fB--type thin\fP ] (implied)
@@ -2397,6 +2397,10 @@ Convert LV to a thin LV, using the original LV as an external origin.
]
.br
[
.O_metadataprofile
]
.br
[
.O_originname
]
.br
@@ -2412,10 +2416,6 @@ Convert LV to a thin LV, using the original LV as an external origin.
.O_poolmetadataspare
]
.br
[
.O_metadataprofile
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIPV\fP\ .\|.\|.\& ]
@@ -2459,6 +2459,10 @@ Convert LV to a thin LV, using LV as thin-pool data volume.
]
.br
[
.O_metadataprofile
]
.br
[
.O_poolmetadata
]
.br
@@ -2470,10 +2474,6 @@ Convert LV to a thin LV, using LV as thin-pool data volume.
.O_poolmetadataspare
]
.br
[
.O_metadataprofile
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIPV\fP\ .\|.\|.\& ]
@@ -2496,17 +2496,13 @@ error
Attach a cache pool to an LV.
.P
.B lvconvert
.O_cache
\fB--cachepool\fP \fILV\fP
.O_cache
\fILV1\fP
.RS
[ \fB--type cache\fP ] (implied)
.br
[
.O_zero
]
.br
[
.O_chunksize
]
.br
@@ -2519,6 +2515,10 @@ Attach a cache pool to an LV.
]
.br
[
.O_zero
]
.br
[
.O_cachemetadataformat
]
.br
@@ -2535,6 +2535,10 @@ Attach a cache pool to an LV.
]
.br
[
.O_metadataprofile
]
.br
[
.O_poolmetadata
]
.br
@@ -2546,10 +2550,6 @@ Attach a cache pool to an LV.
.O_poolmetadataspare
]
.br
[
.O_metadataprofile
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIPV\fP\ .\|.\|.\& ]
@@ -2574,16 +2574,16 @@ error
Attach a cache to an LV, converts the LV to type cache.
.P
.B lvconvert
.O_cache
.O_cachevol
.O_cache
\fILV1\fP
.RS
[
.O_zero
.O_chunksize
]
.br
[
.O_chunksize
.O_zero
]
.br
[
@@ -2632,11 +2632,11 @@ existing data on LV will be erased).
]
.br
[
.O_virtualsize
.O_readahead
]
.br
[
.O_readahead
.O_virtualsize
]
.br
[
@@ -2656,11 +2656,11 @@ existing data on LV will be erased).
]
.br
[
.O_vdosettings
.O_metadataprofile
]
.br
[
.O_metadataprofile
.O_vdosettings
]
.br
[ COMMON_OPTIONS ]
@@ -2702,8 +2702,8 @@ writecache
Swap metadata LV in a thin pool or cache pool (for repair only).
.P
.B lvconvert
.O_swapmetadata
.O_poolmetadata
.O_swapmetadata
\fILV1\fP
.RS
[

File diff suppressed because it is too large Load Diff

View File

@@ -366,11 +366,11 @@ Display output in columns like lvs.
]
.br
[
.O_select
.O_sort
]
.br
[
.O_sort
.O_select
]
.br
[
@@ -386,11 +386,11 @@ Display output in columns like lvs.
]
.br
[
.O_logonly
.O_headings
]
.br
[
.O_headings
.O_logonly
]
.br
[

View File

@@ -306,10 +306,6 @@ Extend an LV by a specified size.
]
.br
[
.O_resizefs
]
.br
[
.O_stripes
]
.br
@@ -318,7 +314,7 @@ Extend an LV by a specified size.
]
.br
[
.O_poolmetadatasize
.O_resizefs
]
.br
[
@@ -329,6 +325,10 @@ Extend an LV by a specified size.
.O_fsmode
]
.br
[
.O_poolmetadatasize
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIPV\fP\ .\|.\|.\& ]
@@ -344,10 +344,6 @@ Extend an LV by specified PV extents.
\fILV\fP \fIPV\fP\ .\|.\|.\&
.RS
[
.O_resizefs
]
.br
[
.O_stripes
]
.br
@@ -356,6 +352,10 @@ Extend an LV by specified PV extents.
]
.br
[
.O_resizefs
]
.br
[
.O_fs
]
.br

View File

@@ -239,35 +239,11 @@ if information changes between commands.
]
.br
[
.O_select
]
.br
[
.O_sort
]
.br
[
.O_foreign
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_shared
]
.br
[
.O_units
.O_select
]
.br
[
@@ -283,7 +259,7 @@ if information changes between commands.
]
.br
[
.O_logonly
.O_foreign
]
.br
[
@@ -291,6 +267,14 @@ if information changes between commands.
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_logonly
]
.br
[
.O_nameprefixes
]
.br
@@ -303,6 +287,14 @@ if information changes between commands.
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_rows
]
.br
@@ -311,10 +303,18 @@ if information changes between commands.
]
.br
[
.O_shared
]
.br
[
.O_unbuffered
]
.br
[
.O_units
]
.br
[
.O_unquoted
]
.br

View File

@@ -175,9 +175,7 @@ is reserved for udev output.)
.
Autoactivation commands use a number of temp files in
.I #DEFAULT_RUN_DIR#
(with the expectation that
.I #DEFAULT_PID_DIR#
is cleared between boots).
(with the expectation that it is cleared between boots).
.
.TP
.B pvs_online

View File

@@ -214,19 +214,15 @@ line settings from --config.
]
.br
[
.O_typeconfig
]
.br
[
.O_ignoreadvanced
]
.br
[
.O_ignoreunsupported
.O_ignorelocal
]
.br
[
.O_ignorelocal
.O_ignoreunsupported
]
.br
[
@@ -238,10 +234,6 @@ line settings from --config.
]
.br
[
.O_sinceversion
]
.br
[
.O_showdeprecated
]
.br
@@ -250,6 +242,18 @@ line settings from --config.
]
.br
[
.O_sinceversion
]
.br
[
.O_typeconfig
]
.br
[
.O_unconfigured
]
.br
[
.O_validate
]
.br
@@ -258,10 +262,6 @@ line settings from --config.
]
.br
[
.O_withsummary
]
.br
[
.O_withcomments
]
.br
@@ -278,7 +278,7 @@ line settings from --config.
]
.br
[
.O_unconfigured
.O_withsummary
]
.br
[

View File

@@ -20,33 +20,44 @@ lvmlockd \(em LVM locking daemon
.
.SH DESCRIPTION
.
LVM commands use lvmlockd to coordinate access to shared storage.
A shared Volume Group is a VG placed on shared storage devices, e.g. from a
SAN, that can be used by all the hosts that can access the devices. A
shared VG requires the use of lvmlockd, and an external lock manager.
.
.P
When LVM is used on devices shared by multiple hosts, locks will:
Different hosts may activate and use LVs in the same shared VG, and
different hosts can create, extend, or remove LVs in the VG. Locking,
through lvmlockd, ensures this is all done safely and consistently.
LVM commands request locks from lvmlockd, which passes the lock requests
to an external lock manager. Each shared VG has a
.B locktype
attribute, specifying the external lock manager to use for the VG.
.
.P
The lock manager options are:
.B sanlock
which places locks on storage space reserved within the VG, and
.B dlm
which uses a network locking protocol, and has additional clustering
requirements.
.
.P
There are three types of locking performed through lvmlockd:
.PD 0
.IP \[bu] 2
coordinate reading and writing of LVM metadata
per-VG locks protect changes to the VG metadata.
.IP \[bu]
validate caching of LVM metadata
LV locks limit LV activation to one host at a time.
.IP \[bu]
prevent conflicting activation of logical volumes
.PD
.P
lvmlockd uses an external lock manager to perform basic locking.
.P
Lock manager (lock type) options are:
.
.TP 8
.B sanlock
\(en places locks on disk within LVM storage.
.
.TP
.B dlm
\(en uses network communication and a cluster manager.
A Global lock protects unused PVs and the VG namespace.
.PD
.
.SH OPTIONS
.
lvmlockd daemon command line options:
.P
.
.TP
.BR -h | --help
Show this help information.
@@ -108,193 +119,287 @@ Override the default sanlock I/O timeout.
.BR -A | --adopt " " 0 | 1
Enable (1) or disable (0) lock adoption.
.
.SH USAGE
.SH SETUP
.
.SS Initial set up
.
Setting up LVM to use lvmlockd and a shared VG for the first time includes
some one time set up steps:
.
.SS 1. choose a lock manager
.
.TP 8
.B sanlock
Choose sanlock if dlm/corosync are not otherwise required.
sanlock does not depend on any clustering software or configuration.
.
.TP
.B dlm
If dlm (or corosync) are already being used by other cluster
software, then select dlm. dlm uses corosync which requires additional
configuration beyond the scope of this document. See corosync and dlm
documentation for instructions on configuration, set up and usage.
.
.SS 2. configure hosts to use lvmlockd
.
On all hosts running lvmlockd, configure
.BR lvm.conf (5):
The following steps provide a quick overview of how to use shared VGs.
More details can be found under SETUP DETAILS.
.P
.EX
use_lvmlockd = 1
.EE
.
.TP 8
.B sanlock
Assign each host a unique host_id in the range 1-2000 by setting
.I Devices
.P
Identify the shared device(s) that will be used in the shared VG,
and add them to each host's devices file (local device names often
differ, unless a WWN-based name from /dev/disk/by-id is used.)
.br
.I #DEFAULT_SYS_DIR#/lvmlocal.conf
local/host_id
.
.SS 3. start lvmlockd
.
Start the lvmlockd daemon.
.B $ lvmdevices --adddev
.I device
.P
.I Configuration
.P
Edit lvm.conf, setting
.B use_lvmlockd=1
on each host using a shared VG.
.P
Edit lvmlocal.conf, setting
.B host_id
on each host (only required when using sanlock.)
The host_id is a unique integer for each host between 1 and 2000.
.P
.I Locking
.P
Start lvmlockd and the external lock manager (sanlock or dlm) on
each host.
.P
.I VG
.P
Create a shared VG from one host (uses the running lock manager):
.br
Use systemctl, a cluster resource agent, or run directly, e.g.
.B $ vgcreate --shared
.I VG
.I devices
.P
.EX
systemctl start lvmlockd
.EE
.
.SS 4. start lock manager
.
.TP 8
.B sanlock
Start the sanlock and wdmd daemons.
Include vgcreate options to use Persistent Reservations (sanlock only):
.br
Use systemctl or run directly, e.g.
.sp
.EX
systemctl start wdmd sanlock
.EE
.
.TP
.B dlm
Start the dlm and corosync daemons.
.B --setpersist y --setlockargs persist,notimeout
.P
Start Persistent Reservations (if they are used):
.br
Use systemctl, a cluster resource agent, or run directly, e.g.
.sp
.EX
systemctl start corosync dlm
.EE
.
.SS 5. create VG on shared devices
.
vgcreate --shared <vgname> <devices>
.B $ vgchange --persist start
.I VG
.P
The shared option sets the VG lock type to sanlock or dlm depending on
which lock manager is running. LVM commands acquire locks from lvmlockd,
and lvmlockd uses the chosen lock manager.
.
.SS 6. start VG on all hosts
.
.EX
vgchange --lockstart
.EE
Start the lockspace for the shared VG on all hosts:
.br
.B $ vgchange --lockstart
.I VG
.P
Shared VGs must be started before they are used. Starting the VG performs
lock manager initialization that is necessary to begin using locks (i.e.
creating and joining a lockspace). Starting the VG may take some time,
and until the start completes the VG may not be modified or activated.
.
.SS 7. create and activate LVs
.
Standard lvcreate and lvchange commands are used to create and activate
LVs in a shared VG.
.I Usage
.P
An LV activated exclusively on one host cannot be activated on another.
When multiple hosts need to use the same LV concurrently, the LV can be
activated with a shared lock (see lvchange options -aey vs -asy.)
(Shared locks are disallowed for certain LV types that cannot be used from
multiple hosts.)
.
.SS Normal start up and shut down
.
After initial set up, start up and shut down include the following steps.
They can be performed directly or may be automated using systemd or a
cluster resource manager/agents. When using lvmlockd.service, daemon
options can be set in
.I /etc/sysconfig/lvmlockd
as OPTIONS='-x1 -y2'.
.
.IP \[bu] 2
start lvmlockd
.
.IP \[bu]
start lock manager
.
.IP \[bu]
vgchange --lockstart
.
.IP \[bu]
activate LVs in shared VGs
Begin using the VG, e.g. creating LVs.
.P
The shut down sequence is the reverse:
.IP \[bu] 2
deactivate LVs in shared VGs
.IP \[bu]
vgchange --lockstop
.IP \[bu]
stop lock manager
.IP \[bu]
stop lvmlockd
Regular shutdown steps:
.br
$ vgchange -an VG
.br
$ vgchange --lockstop [--persist stop] VG
.br
$ stop lvmlockd and lock manager
.br
.P
Regular startup steps:
.br
$ start lvmlockd and lock manager
.br
$ vgchange --lockstart [--persist start] VG
.P
.
.SH SETUP DETAILS
.P
.B Identifying devices
.br
Devices often have different local names on each host, e.g. /dev/sda
on one host is named /dev/sdb on another. One method to identify the
same device on each host is to run the command lsblk -o+WWN on each
host, looking for the same WWN, and its corresponding local device name.
Or, the WWN-based device symlinks under /dev/disk/by-id/ can be a
useful way to consistently identify a device across multiple hosts.
.P
.B Device access
.br
On each host, LVM needs to be given access to the shared devices by
adding them to the local system.devices file (unless the devices file
feature has been disabled.) Use the local device name identified
in the previous step, or a WWN-based device symlink, and run the
command lvmdevices --adddev device_path to add each of the shared
devices to the local system.devices file.
Alternatively, after the shared VG has been created from one host,
other hosts can run the command vgimportdevices VG to add devices
from VG to system.devices.
See
.BR lvmdevices (8)
for more information.
.P
.B Config files
.br
After #DEFAULT_SYS_DIR#/lvm.conf use_lvmlockd has been set to 1,
lvm commands will begin attempting to acquire locks from lvmlockd.
Failures to acquire the global lock from lvmlockd may appear until
the first shared VG is operational. These warnings won't interfere
with lvm commands doing read operations, but lvm commands attempting
to write may fail with a global lock error.
.P
The #DEFAULT_SYS_DIR#/lvmlocal.conf host_id setting is only required
when using VGs with lock type sanlock. Each host using sanlock VGs
must be configured with a unique host_id value. Valid host_ids are
integers in the range 1-2000. (The lvmlocal.conf descriptions of
host_id and sanlock_align_size mention special cases with 4K disks
in which the valid host_id range can be smaller, e.g. 1-250.)
.P
.B Lock managers
.br
A specific build of LVM may exclude support for sanlock or dlm
lock managers. To check this, run the command "lvm version" and
look for "--enable-lvmlockd-sanlock" or "--enable-lvmlockd-dlm".
.P
With the --shared option, vgcreate searches for a running lock manager
(dlm or sanlock), and uses the result for the VG lock type.
In place of --shared, vgcreate --locktype sanlock|dlm can be specified
directly.
.P
When using lvmlockd in a cluster which already uses corosync and
dlm, then the dlm lock type should be used for shared VGs. Otherwise,
using sanlock is usually more straight forward.
.P
Details on starting or setting up each lock manager are outside the
scope of LVM. sanlock can usually be started with a simple
"systemctl start wdmd sanlock". Steps for setting up and starting
corosync and dlm can be more complicated.
.P
.B Lock start
.br
Shared VGs must be started before they are used via vgchange --lockstart
VG. Starting the VG performs lock manager initialization that is necessary
to begin using locks (i.e. creating and joining a lockspace). Starting the
VG may take some time, and until the start completes the VG may not be
modified or activated. When shutting down, the lockspace is stopped with
vgchange --lockstop VG.
.P
.B Persistent Reservations
.br
A shared VG with locktype sanlock can take advantage of Persistent
Reservations (PR) for faster and more reliable recovery. This
requires that all of the shared devices in the VG support PR. Test
if PR is supported by a device with the command:
.br
.B $ lvmpersist devtest --device
.I device
.P
The vgcreate command options when enabling PR recovery with sanlock:
.br
.B $ vgcreate --shared --setpersist y --setlockargs persist,notimeout
.P
When enabled, PR needs to be started for the VG before locking:
.br
.B $ vgchange --persist start
.I VG
.
.SH TOPICS
.
.SS Protecting VGs on shared devices
.
The following terms are used to describe the different ways of accessing
VGs on shared devices.
.
.TP
.I shared VG
A shared VG exists on shared storage that is visible to multiple hosts.
LVM acquires locks through lvmlockd to coordinate access to shared VGs.
A shared VG has lock_type "dlm" or "sanlock", which specifies the lock
manager lvmlockd will use.
.sp
When the lock manager for the lock type is not available (e.g. not started
or failed), lvmlockd is unable to acquire locks for LVM commands. In this
situation, LVM commands are only allowed to read and display the VG;
changes and activation will fail.
.
.TP
.I local VG
A local VG is meant to be used by a single host. It has no lock type or
lock type "none". A local VG typically exists on local (non-shared)
devices and cannot be used concurrently from different hosts.
.sp
If a local VG does exist on shared devices, it should be owned by a single
host by having the system ID set, see
.BR lvmsystemid (7).
The host with a matching system ID can use the local VG and other hosts
will ignore it. A VG with no lock type and no system ID should be
excluded from all but one host using
.BR lvm.conf (5)
filters.
Without any of these protections, a local VG on shared devices
can be easily damaged or destroyed.
.
.TP
.I clvm VG
A clvm VG (or clustered VG) is a VG on shared storage (like a shared VG)
that requires clvmd for clustering and locking. See below for converting
a clvm/clustered VG to a shared VG.
.
.SS Shared VGs from hosts not using lvmlockd
.
Hosts that do not use shared VGs will not be running lvmlockd. In this
case, shared VGs that are still visible to the host will be ignored
(like foreign VGs, see
.BR lvmsystemid (7)).
.SS Displaying shared VGs
.P
The --shared option for reporting and display commands causes shared VGs
to be displayed on a host not using lvmlockd, like the --foreign option
does for foreign VGs.
The
.B vgs
command shows the letter
.B s
in the last (sixth) attr position for a shared VG:
.
.nf
.
.P
$ vgs
VG #PV #LV #SN Attr VSize VFree
vgfoo 1 0 0 wz--ns 992.00m 736.00m
.fi
.
.P
.
Or, the shared attribute can be displayed as a
.B vgs
reporting field:
.P
.nf
$ vgs -o+shared
VG #PV #LV #SN Attr VSize VFree Shared
vgfoo 1 0 0 wz--ns 992.00m 736.00m shared
.fi
.P
.
The
.B vgs
command can also display the lock type:
.
.P
.nf
$ vgs -o+locktype
VG #PV #LV #SN Attr VSize VFree LockType
vgfoo 1 0 0 wz--ns 992.00m 736.00m sanlock
.fi
.P
.
On hosts that are attached to the shared devices, but do not have
lvmlockd enabled, the
.B vgs
command will not display shared VGs unless the
.B --shared
option is added:
.
.P
.nf
$ vgs --shared
VG #PV #LV #SN Attr VSize VFree
vgfoo 1 0 0 wz--ns 992.00m 736.00m
.fi
.
.SS Persistent Reservations
.
To enable PR-based recovery ("fencing") in an existing VG:
.br
.B $ vgchange --setpersist y --setlockargs persist,notimeout
.I VG
.P
Changing the lock args requires the VG to be stopped on all other nodes.
.P
Once enabled, PR needs to be started before or with lockstart:
.br
.B $ vgchange --persist start
.I VG
.br
.B $ vgchange --persist start --lockstart
.I VG
.P
Display the VG attributes configured by setpersist and setlockargs:
.br
.B $ vgs -o+persist
.I VG
.br
.B $ vgs -o+lockargs
.I VG
.P
.B setpersist y
.br
With this setting, LVM requires that PR be started before
lockstart, and any VG modifications or activations require
that PR is started.
.br
.B setlockargs persist
.br
This lockargs setting causes lvmlockd to remove the PR key of a
failed host when a lock request fails due to a lock owned by the
failed host. sanlock is then permitted to grant the lock.
.br
.B setlockargs notimeout
.br
This lockargs setting causes lvmlockd to configure sanlock leases
to not time out. Removing the PR of a failed host replaces timeouts
as a faster mechanism for lock recovery. With timeouts disabled,
the local watchdog is not used by sanlock for the VG lockspace.
.P
For more information, see
.BR lvmpersist (8).
.
.SS System ID
.br
In contrast to a shared VG, a local VG can only be used by one host
at a time, and does not use lvmlockd or a lock manager. If a local VG
is located on shared devices, then the LVM system ID feature should be
used to assign one host ownership of the VG. See
.BR lvmsystemid (7).
.P
For additional protection, the shared devices in a local VG can be
excluded from the devices file (system.devices) on all hosts except
for the host that owns the VG.
.
.SS Creating the first sanlock VG
.
When use_lvmlockd is first enabled in
.BR lvm.conf (5),
When use_lvmlockd is first enabled in lvm.conf,
and before the first sanlock VG is created, no global lock will exist.
In this initial state, LVM commands try
and fail to acquire the global lock, producing a warning,
@@ -327,27 +432,12 @@ from concurrent use by another vgcreate on another host.
.P
See below for more information about managing the sanlock global lock.
.
.SS Using shared VGs
.SS Removing a shared VG
.
In the
.BR vgs (8)
command, shared VGs are indicated by "s" (for shared)
in the sixth attr field,
and by "shared" in the "--options shared" report field.
The specific lock type and lock args for a shared VG can be
displayed with:
.P
.EX
# vgs -o+locktype,lockargs
.EE
.P
Shared VGs need to be "started" and "stopped", unlike other types of VGs.
See the following section for a full description of starting and stopping.
.P
Removing a shared VG will fail if other hosts have the VG started. Run
vgchange --lockstop <vgname> on all other hosts before vgremove. (It may
take several seconds before vgremove recognizes that all hosts have
stopped a sanlock VG.)
Removing a shared VG will fail if other hosts have the VG started (it must
be started on the host running vgremove.) Run vgchange --lockstop <vgname>
on all other hosts before vgremove. (It may take several seconds before
vgremove recognizes that all hosts have stopped a sanlock VG.)
.
.SS Starting and stopping VGs
.
@@ -366,32 +456,6 @@ When using the lock type sanlock, starting a VG can take a long time
(potentially minutes if the host was previously shut down without cleanly
stopping the VG.)
.P
A shared VG can be started after all the following are true:
.P
\[bu]
lvmlockd is running
.br
\[bu]
the lock manager is running
.br
\[bu]
the VG's devices are visible on the system
.P
A shared VG can be stopped if all LVs are deactivated.
.P
All shared VGs can be started/stopped using:
.P
.EX
# vgchange --lockstart
# vgchange --lockstop
.EE
.P
Individual VGs can be started/stopped using:
.br
vgchange --lockstart <vgname> \&.\|.\|.
.br
vgchange --lockstop <vgname> \&.\|.\|.
.P
To make vgchange not wait for start to complete:
.br
vgchange --lockstart --lockopt nowait \&.\|.\|.
@@ -400,21 +464,6 @@ lvmlockd can be asked directly to stop all lockspaces:
.br
lvmlockctl -S|--stop-lockspaces
.P
To start only selected shared VGs, use the
.BR lvm.conf (5)
\fBactivation/lock_start_list\fP.
When defined, only VG names in this list are
started by vgchange. If the list is not defined (the default), all
visible shared VGs are started. To start only "vg1", use the following
.BR lvm.conf (5)
configuration:
.P
.EX
activation {
\ lock_start_list = [ "vg1" ]
\ \&...
}
.EE
.
.SS Internal command locking
.
@@ -664,7 +713,7 @@ dmsetup wipe_table -S "uuid=~LVM && vgname=$VG && lv_layer=\\"\\""
# check that the error target is in place
dmsetup table -c -S "uuid=~LVM && vgname=$VG && lv_layer=\\"\\"" |grep -vw error
if [[ $? -ne 0 ]] ; then
\ exit 0
exit 0
fi
exit 1
.EE
@@ -868,14 +917,11 @@ vgmerge
.
.SS lvmlockd changes from clvmd
.
(See above for converting an existing clvm VG to a shared VG.)
.P
While lvmlockd and clvmd are entirely different systems, LVM command usage
remains similar. Differences are more notable when using lvmlockd's
sanlock option.
.P
Visible usage differences between shared VGs (using lvmlockd) and
clvm/clustered VGs (using clvmd):
Prior to the introduction of lvmlockd, clvmd (CLVM) existed with similar
capabilities, but a very different design.
Some of the visible usage differences between shared VGs (using lvmlockd)
and cluster VGs (using clvmd):
.
.IP \[bu] 2
.BR lvm.conf (5)
@@ -945,9 +991,6 @@ unable to passively check the remote active or lock state of an LV.
.
.nh
.na
.BR lvm (8),
.BR lvmlockctl (8),
.BR lvchange (8),
.BR lvgs (8),
.BR vgs (8),
.BR lvm.conf (5)
.BR sanlock (8),
.BR dlm_controld (8)

View File

@@ -258,7 +258,7 @@ Display the settings.
.P
.SS VG PR commands
.P
vgchange --persist is used to perfom PR operations on the VG's devices.
vgchange --persist is used to perform PR operations on the VG's devices.
.P
.B vgchange --persist start
.I VG

View File

@@ -198,14 +198,6 @@ the options section.
]
.br
[
.O_noudevsync
]
.br
[
.O_reportformat
]
.br
[
.O_fs
]
.br
@@ -213,6 +205,14 @@ the options section.
.O_fsmode
]
.br
[
.O_noudevsync
]
.br
[
.O_reportformat
]
.br
[ COMMON_OPTIONS ]
.RE
.P

View File

@@ -293,10 +293,6 @@ Resize an LV by a specified size.
]
.br
[
.O_poolmetadatasize
]
.br
[
.O_fs
]
.br
@@ -304,6 +300,10 @@ Resize an LV by a specified size.
.O_fsmode
]
.br
[
.O_poolmetadatasize
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIPV\fP\ .\|.\|.\& ]

View File

@@ -233,11 +233,11 @@ lvs produces formatted output about LVs.
.B lvs
.RS
[
.O_history
.O_all
]
.br
[
.O_all
.O_history
]
.br
[
@@ -245,39 +245,11 @@ lvs produces formatted output about LVs.
]
.br
[
.O_select
]
.br
[
.O_sort
]
.br
[
.O_segments
]
.br
[
.O_foreign
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_shared
]
.br
[
.O_units
.O_select
]
.br
[
@@ -293,7 +265,7 @@ lvs produces formatted output about LVs.
]
.br
[
.O_logonly
.O_foreign
]
.br
[
@@ -301,6 +273,14 @@ lvs produces formatted output about LVs.
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_logonly
]
.br
[
.O_nameprefixes
]
.br
@@ -313,18 +293,38 @@ lvs produces formatted output about LVs.
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_rows
]
.br
[
.O_segments
]
.br
[
.O_separator
]
.br
[
.O_shared
]
.br
[
.O_unbuffered
]
.br
[
.O_units
]
.br
[
.O_unquoted
]
.br

View File

@@ -166,9 +166,9 @@ Change properties of all PVs.
.O_all
.RS
(
.O_allocatable
.in +2n
.O_uuid
.in +2n
.O_allocatable
.br
.O_addtag
.br
@@ -189,9 +189,9 @@ Change properties of specified PVs.
.B pvchange
.RS
(
.O_allocatable
.in +2n
.O_uuid
.in +2n
.O_allocatable
.br
.O_addtag
.br

View File

@@ -366,11 +366,11 @@ Check and print LVM headers and metadata on a device
]
.br
[
.O_settings
.O_pvmetadatacopies
]
.br
[
.O_pvmetadatacopies
.O_settings
]
.br
[ COMMON_OPTIONS ]

View File

@@ -276,6 +276,10 @@ pe_start value.
]
.br
[
.O_bootloaderareasize
]
.br
[
.O_dataalignment
]
.br
@@ -284,31 +288,23 @@ pe_start value.
]
.br
[
.O_bootloaderareasize
]
.br
[
.O_labelsector
]
.br
[
.O_pvmetadatacopies
]
.br
[
.O_metadatasize
]
.br
[
.O_metadataignore
]
.br
[
.O_metadatasize
]
.br
[
.O_norestorefile
]
.br
[
.O_setphysicalvolumesize
.O_pvmetadatacopies
]
.br
[
@@ -319,6 +315,10 @@ pe_start value.
.O_restorefile
]
.br
[
.O_setphysicalvolumesize
]
.br
[ COMMON_OPTIONS ]
.RE
.P

View File

@@ -374,11 +374,11 @@ Display output in columns like pvs.
]
.br
[
.O_select
.O_sort
]
.br
[
.O_sort
.O_select
]
.br
[
@@ -394,11 +394,11 @@ Display output in columns like pvs.
]
.br
[
.O_logonly
.O_headings
]
.br
[
.O_headings
.O_logonly
]
.br
[

View File

@@ -140,11 +140,11 @@ LVs allocated on it.
]
.br
[
.O_setphysicalvolumesize
.O_reportformat
]
.br
[
.O_reportformat
.O_setphysicalvolumesize
]
.br
[ COMMON_OPTIONS ]

View File

@@ -233,11 +233,11 @@ pvs produces formatted output about PVs.
.B pvs
.RS
[
.O_allpvs
.O_all
]
.br
[
.O_all
.O_allpvs
]
.br
[
@@ -245,39 +245,11 @@ pvs produces formatted output about PVs.
]
.br
[
.O_select
]
.br
[
.O_sort
]
.br
[
.O_segments
]
.br
[
.O_foreign
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_shared
]
.br
[
.O_units
.O_select
]
.br
[
@@ -293,7 +265,7 @@ pvs produces formatted output about PVs.
]
.br
[
.O_logonly
.O_foreign
]
.br
[
@@ -301,6 +273,14 @@ pvs produces formatted output about PVs.
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_logonly
]
.br
[
.O_nameprefixes
]
.br
@@ -313,18 +293,38 @@ pvs produces formatted output about PVs.
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_rows
]
.br
[
.O_segments
]
.br
[
.O_separator
]
.br
[
.O_shared
]
.br
[
.O_unbuffered
]
.br
[
.O_units
]
.br
[
.O_unquoted
]
.br

View File

@@ -315,6 +315,10 @@ Display PV information.
.B pvscan
.RS
[
.O_allpvs
]
.br
[
.O_exported
]
.br
@@ -331,10 +335,6 @@ Display PV information.
]
.br
[
.O_allpvs
]
.br
[
.O_ignorelockingfailure
]
.br
@@ -363,10 +363,6 @@ Record that a PV is online or offline.
]
.br
[
.O_reportformat
]
.br
[
.O_minor
]
.br
@@ -374,6 +370,10 @@ Record that a PV is online or offline.
.O_noudevsync
]
.br
[
.O_reportformat
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIString\fP|\fIPV\fP\ .\|.\|.\& ]
@@ -394,11 +394,11 @@ Record that a PV is online and autoactivate the VG if complete.
]
.br
[
.O_ignorelockingfailure
.O_autoactivation
]
.br
[
.O_reportformat
.O_ignorelockingfailure
]
.br
[
@@ -410,7 +410,7 @@ Record that a PV is online and autoactivate the VG if complete.
]
.br
[
.O_autoactivation
.O_reportformat
]
.br
[ COMMON_OPTIONS ]
@@ -430,7 +430,7 @@ Record that a PV is online and list the VG using the PV.
\fIPV\fP
.RS
[
.O_ignorelockingfailure
.O_autoactivation
]
.br
[
@@ -438,7 +438,7 @@ Record that a PV is online and list the VG using the PV.
]
.br
[
.O_vgonline
.O_ignorelockingfailure
]
.br
[
@@ -446,7 +446,7 @@ Record that a PV is online and list the VG using the PV.
]
.br
[
.O_autoactivation
.O_vgonline
]
.br
[ COMMON_OPTIONS ]
@@ -464,11 +464,11 @@ Record that a PV is online and list LVs using the PV.
\fIPV\fP
.RS
[
.O_ignorelockingfailure
.O_checkcomplete
]
.br
[
.O_checkcomplete
.O_ignorelockingfailure
]
.br
[

View File

@@ -238,8 +238,8 @@ List all VG metadata backups.
List one VG metadata backup file.
.P
.B vgcfgrestore
.O_list
.O_file
.O_list
.RS
[ COMMON_OPTIONS ]
.br

View File

@@ -403,27 +403,27 @@ required, after which the others are optional.
.in +2n
.O_maxphysicalvolumes
.br
.O_uuid
.br
.O_physicalextentsize
.br
.O_uuid
.br
.O_resizeable
.br
.O_addtag
.br
.O_deltag
.br
.O_alloc
.br
.O_pvmetadatacopies
.br
.O_vgmetadatacopies
.O_deltag
.br
.O_detachprofile
.br
.O_metadataprofile
.br
.O_pvmetadatacopies
.br
.O_setautoactivation
.br
.O_vgmetadatacopies
)
.in
[
@@ -431,15 +431,11 @@ required, after which the others are optional.
]
.br
[
.O_select
]
.br
[
.O_force
]
.br
[
.O_poll
.O_select
]
.br
[
@@ -451,6 +447,10 @@ required, after which the others are optional.
]
.br
[
.O_poll
]
.br
[
.O_reportformat
]
.br
@@ -473,15 +473,11 @@ Start or stop monitoring LVs from dmeventd.
]
.br
[
.O_select
]
.br
[
.O_force
]
.br
[
.O_sysinit
.O_select
]
.br
[
@@ -489,10 +485,6 @@ Start or stop monitoring LVs from dmeventd.
]
.br
[
.O_poll
]
.br
[
.O_ignoremonitoring
]
.br
@@ -501,9 +493,17 @@ Start or stop monitoring LVs from dmeventd.
]
.br
[
.O_poll
]
.br
[
.O_reportformat
]
.br
[
.O_sysinit
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIVG\fP|\fITag\fP|\fISelect\fP\ .\|.\|.\& ]
@@ -523,11 +523,11 @@ Start or stop processing LV conversions.
]
.br
[
.O_select
.O_force
]
.br
[
.O_force
.O_select
]
.br
[
@@ -561,6 +561,14 @@ Activate or deactivate LVs.
.O_activate
.RS
[
.O_autobackup
]
.br
[
.O_force
]
.br
[
.O_ignoreactivationskip
]
.br
@@ -569,27 +577,15 @@ Activate or deactivate LVs.
]
.br
[
.O_autobackup
]
.br
[
.O_select
]
.br
[
.O_force
]
.br
[
.O_activationmode
]
.br
[
.O_sysinit
]
.br
[
.O_readonly
.O_autoactivation
]
.br
[
@@ -597,33 +593,37 @@ Activate or deactivate LVs.
]
.br
[
.O_monitor
]
.br
[
.O_poll
]
.br
[
.O_autoactivation
]
.br
[
.O_persist
]
.br
[
.O_ignoremonitoring
]
.br
[
.O_monitor
]
.br
[
.O_noudevsync
]
.br
[
\fB--persist\fP \fIString\fP
]
.br
[
.O_poll
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_sysinit
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIVG\fP|\fITag\fP|\fISelect\fP\ .\|.\|.\& ]
@@ -643,15 +643,11 @@ Reactivate LVs using the latest metadata.
]
.br
[
.O_select
]
.br
[
.O_force
]
.br
[
.O_sysinit
.O_select
]
.br
[
@@ -659,10 +655,6 @@ Reactivate LVs using the latest metadata.
]
.br
[
.O_poll
]
.br
[
.O_ignoremonitoring
]
.br
@@ -671,9 +663,17 @@ Reactivate LVs using the latest metadata.
]
.br
[
.O_poll
]
.br
[
.O_reportformat
]
.br
[
.O_sysinit
]
.br
[ COMMON_OPTIONS ]
.br
[ \fIVG\fP|\fITag\fP|\fISelect\fP\ .\|.\|.\& ]
@@ -698,7 +698,7 @@ Change the system ID of a VG.
]
.br
[
.O_persist
\fB--persist\fP \fIString\fP
]
.br
[
@@ -723,7 +723,7 @@ Set or clear flags to control persistent reservation behavior.
]
.br
[
.O_persist
\fB--persist\fP \fBstart\fP
]
.br
[ COMMON_OPTIONS ]
@@ -740,21 +740,21 @@ Perform persistent reservation commands on devices.
\fIVG\fP|\fITag\fP|\fISelect\fP
.RS
[
.O_select
]
.br
[
.O_force
]
.br
[
.O_removekey
.O_select
]
.br
[
.O_majoritypvs
]
.br
[
.O_removekey
]
.br
[ COMMON_OPTIONS ]
.RE
.
@@ -772,7 +772,7 @@ Start the lockspace of a shared VG in lvmlockd.
]
.br
[
.O_persist
\fB--persist\fP \fBstart\fP
]
.br
[ COMMON_OPTIONS ]
@@ -794,7 +794,7 @@ Stop the lockspace of a shared VG in lvmlockd.
]
.br
[
.O_persist
\fB--persist\fP \fBstop\fP
]
.br
[ COMMON_OPTIONS ]
@@ -1254,12 +1254,14 @@ for individual LVs.
.TP
.O_setpersist
Set or clear flags to control persistent reservation behavior.
autostart: set flag, PR will be automatically started.
noautostart: clear autostart flag.
y: set require and autostart flags.
n: clear require and autostart flags.
require: set flag, PR will be required to write or activate VG.
norequire: clear require flag.
y: set autostart and require flags.
n: clear autostart and require flags.
autostart: set flag, PR will be automatically started.
noautostart: clear autostart flag.
ptpl: set flag, use persist through power loss on devices.
noptpl: clear ptpl flag.
When autostart is enabled, autoactivation and auto-lockstart
commands will first start PR.
lvmlocal.conf pr_key or host_id must be configured to use PR.

View File

@@ -161,15 +161,11 @@ convert VGs from the LVM1 format to LVM2.
]
.br
[
.O_labelsector
]
.br
[
.O_bootloaderareasize
]
.br
[
.O_pvmetadatacopies
.O_labelsector
]
.br
[
@@ -177,6 +173,10 @@ convert VGs from the LVM1 format to LVM2.
]
.br
[
.O_pvmetadatacopies
]
.br
[
.O_reportformat
]
.br

View File

@@ -134,6 +134,10 @@
.de O_nolocking
.OPS nolocking
..
.de O_persist
.OPA persist
\fIString\fP
..
.de O_physicalextentsize
.OPA s physicalextentsize
\fISize\fP[m|\:UNIT]
@@ -160,6 +164,10 @@
.OPA setautoactivation
\fBy\fP|\fBn\fP
..
.de O_setpersist
.OPA setpersist
\fIString\fP
..
.de O_shared
.OPS shared
..
@@ -235,11 +243,11 @@ device.
]
.br
[
.O_maxlogicalvolumes
.O_force
]
.br
[
.O_maxphysicalvolumes
.O_maxlogicalvolumes
]
.br
[
@@ -247,11 +255,11 @@ device.
]
.br
[
.O_physicalextentsize
.O_maxphysicalvolumes
]
.br
[
.O_force
.O_physicalextentsize
]
.br
[
@@ -267,7 +275,11 @@ device.
]
.br
[
.O_metadataprofile
.O_dataalignment
]
.br
[
.O_dataalignmentoffset
]
.br
[
@@ -275,27 +287,35 @@ device.
]
.br
[
.O_locktype
]
.br
[
.O_metadataprofile
]
.br
[
.O_metadatasize
]
.br
[
\fB--persist\fP \fBstart\fP
]
.br
[
.O_pvmetadatacopies
]
.br
[
.O_vgmetadatacopies
]
.br
[
.O_reportformat
]
.br
[
.O_dataalignment
.O_setautoactivation
]
.br
[
.O_dataalignmentoffset
.O_setpersist
]
.br
[
@@ -307,11 +327,7 @@ device.
]
.br
[
.O_locktype
]
.br
[
.O_setautoactivation
.O_vgmetadatacopies
]
.br
[ COMMON_OPTIONS ]
@@ -560,6 +576,20 @@ Disable locking. Use with caution, concurrent commands may produce
incorrect results.
.
.TP
.O_persist
Persistent Reservation operation.
start: register local key and acquire reservation.
stop: unregister local key, releasing reservation.
remove: preempt and abort another key.
clear: remove reservation and keys.
check: check if started.
autostart: start if the VG autostart flag is set.
lvmlocal.conf pr_key or host_id must be configured to use PR.
For local VGs, Write Exclusive (WE) is used, and for shared VGs
Write Exclusive, all registrants (WEAR) is used.
Use --setpersist to automate and/or require PR.
.
.TP
.O_physicalextentsize
Sets the physical extent size of PVs in the VG.
The value must be either a power of 2 of at least 1 sector
@@ -612,6 +642,18 @@ If autoactivation is enabled on a VG, autoactivation can be disabled
for individual LVs.
.
.TP
.O_setpersist
Set flags to control persistent reservation behavior.
y: set require and autostart flags.
require: PR will be required to write or activate VG.
autostart: PR will be automatically started.
ptpl: use persist through power loss on devices.
When autostart is enabled, autoactivation and auto-lockstart
commands will first start PR.
lvmlocal.conf pr_key or host_id must be configured to use PR.
For local VGs, enabling system_id is also recommended.
.
.TP
.O_shared
Create a shared VG using lvmlockd if LVM is compiled with lockd support.
lvmlockd will select lock type sanlock or dlm depending on which lock

View File

@@ -338,11 +338,11 @@ and more, using a more compact and configurable output format.
.B vgdisplay
.RS
[
.O_short
.O_activevolumegroups
]
.br
[
.O_activevolumegroups
.O_short
]
.br
[ COMMON_OPTIONS ]
@@ -368,11 +368,11 @@ Display output in columns like vgs.
]
.br
[
.O_select
.O_sort
]
.br
[
.O_sort
.O_select
]
.br
[
@@ -388,11 +388,11 @@ Display output in columns like vgs.
]
.br
[
.O_logonly
.O_headings
]
.br
[
.O_headings
.O_logonly
]
.br
[

View File

@@ -162,7 +162,7 @@ Export specified VGs.
]
.br
[
.O_persist
\fB--persist\fP \fBstop\fP
]
.br
[ COMMON_OPTIONS ]

View File

@@ -188,27 +188,11 @@ will initialize them. In this case pvcreate options can be used, e.g.
]
.br
[
.O_zero
]
.br
[
.O_metadatatype
]
.br
[
.O_labelsector
]
.br
[
.O_metadatasize
]
.br
[
.O_pvmetadatacopies
]
.br
[
.O_metadataignore
.O_zero
]
.br
[
@@ -220,6 +204,22 @@ will initialize them. In this case pvcreate options can be used, e.g.
]
.br
[
.O_labelsector
]
.br
[
.O_metadataignore
]
.br
[
.O_metadatasize
]
.br
[
.O_pvmetadatacopies
]
.br
[
.O_reportformat
]
.br

View File

@@ -152,7 +152,7 @@ Import specified VGs.
]
.br
[
.O_persist
\fB--persist\fP \fBstart\fP
]
.br
[ COMMON_OPTIONS ]

View File

@@ -136,11 +136,11 @@ changes the associated VG and PV UUIDs.
\fIPV\fP\ .\|.\|.\&
.RS
[
.O_basevgname
.O_import
]
.br
[
.O_import
.O_basevgname
]
.br
[

View File

@@ -235,35 +235,11 @@ vgs produces formatted output about VGs.
]
.br
[
.O_select
]
.br
[
.O_sort
]
.br
[
.O_foreign
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_shared
]
.br
[
.O_units
.O_select
]
.br
[
@@ -279,7 +255,7 @@ vgs produces formatted output about VGs.
]
.br
[
.O_logonly
.O_foreign
]
.br
[
@@ -287,6 +263,14 @@ vgs produces formatted output about VGs.
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_logonly
]
.br
[
.O_nameprefixes
]
.br
@@ -299,6 +283,14 @@ vgs produces formatted output about VGs.
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_rows
]
.br
@@ -307,10 +299,18 @@ vgs produces formatted output about VGs.
]
.br
[
.O_shared
]
.br
[
.O_unbuffered
]
.br
[
.O_units
]
.br
[
.O_unquoted
]
.br

View File

@@ -514,7 +514,7 @@ device_supports_type_str() {
fi
}
check_device_types() {
check_devices() {
err=0
FOUND_MPATH=0
FOUND_SCSI=0
@@ -559,11 +559,31 @@ check_device_types() {
if [[ $FOUND_SCSI -eq 1 ]]; then
which sg_persist > /dev/null || errorexit "sg_persist command not found."
which sg_turs > /dev/null || errorexit "sg_turs command not found."
fi
if [[ $FOUND_NVME -eq 1 ]]; then
which nvme > /dev/null || errorexit "nvme command not found."
fi
# Sometimes a device will return a Unit Attention error
# for an sg_persist/mpathpersist command, e.g. after the
# host's key was cleared. A single tur command clears
# the error. Alternatively, each command in the script
# could be retried if it fails due to a UA error.
for dev in "${DEVICES[@]}"; do
case "$dev" in
/dev/sd*)
;&
/dev/dm-*)
;&
/dev/mapper*)
sg_turs "$dev" >/dev/null 2>&1
ec=$?
test $ec -eq 0 || logmsg "test unit ready error $ec from $dev"
esac
done
}
undo_register() {
@@ -866,6 +886,7 @@ do_remove() {
for dev in "${DEVICES[@]}"; do
if ! key_is_on_device "$dev" "$OURKEY" ; then
logmsg "cannot remove $REMKEY from $dev without ourkey $OURKEY being registered"
err=1
continue
fi
@@ -1201,7 +1222,7 @@ fi
# subsequent string matching of keys fails.
DECDIGITS='^[0-9]+$'
HEXDIGITS='^[0-9a-zA-Z]+$'
HEXDIGITS='^[0-9a-fA-F]+$'
if [[ -n "$OURKEY" && "$OURKEY" == "0x0"* ]]; then
echo "Leading 0s are not permitted in keys."
@@ -1230,7 +1251,7 @@ if [[ -n "$OURKEY" && "$OURKEY" != "0x"* ]]; then
fi
if [[ -n "$OURKEY" && "$OURKEY" == "0x"* ]]; then
if [[ ! "$OURKEY" =~ $HEXDIGITS ]]; then
if [[ ! "${OURKEY:2}" =~ $HEXDIGITS ]]; then
echo "Invalid hex digits in key: $OURKEY"
exit 1
fi
@@ -1249,7 +1270,7 @@ if [[ -n "$REMKEY" && "$REMKEY" != "0x"* ]]; then
fi
if [[ -n "$REMKEY" && "$REMKEY" == "0x"* ]]; then
if [[ ! "$REMKEY" =~ $HEXDIGITS ]]; then
if [[ ! "${REMKEY:2}" =~ $HEXDIGITS ]]; then
echo "Invalid hex digits in key: $REMKEY"
exit 1
fi
@@ -1381,38 +1402,31 @@ else
fi
fi
#
# Main program function
#
check_devices
if [[ "$DO_START" -eq 1 && -n "$REMKEY" ]]; then
check_device_types
do_takeover
elif [[ "$DO_START" -eq 1 ]]; then
check_device_types
do_start
elif [[ "$DO_STOP" -eq 1 ]]; then
do_stop
elif [[ "$DO_REMOVE" -eq 1 ]]; then
do_remove
elif [[ "$DO_CLEAR" -eq 1 ]]; then
check_device_types
do_clear
elif [[ "$DO_DEVTEST" -eq 1 ]]; then
check_device_types
do_devtest
elif [[ "$DO_CHECKKEY" -eq 1 ]]; then
check_device_types
do_checkkey
elif [[ "$DO_READKEYS" -eq 1 ]]; then
check_device_types
do_readkeys
elif [[ "$DO_READRESERVATION" -eq 1 ]]; then
check_device_types
do_readreservation
elif [[ "$DO_READ" -eq 1 ]]; then
check_device_types
do_readkeys
do_readreservation
fi

View File

@@ -19,6 +19,11 @@ errorexit() {
exit 1
}
logerror() {
echo "$1" >&2
logger "${SCRIPTNAME}: $1"
}
logmsg() {
echo "$1"
logger "${SCRIPTNAME}: $1"
@@ -68,6 +73,72 @@ TMP_MOUNT_DONE=0
# Set to 1 if the fs resize command fails
RESIZEFS_FAILED=0
# Function to detect XFS mount options
detect_xfs_mount_options() {
local device=$1
local qflags_output qflags_hex
MOUNT_OPTIONS=""
# Get quota flags using xfs_db.
if ! qflags_output=$(xfs_db -r "$device" -c 'sb 0' -c 'p qflags'); then
logerror "xfs_db failed"
return 1
fi
# Extract the hex value from output that is in format "qflags = 0x<hex_number>".
qflags_hex="${qflags_output#qflags = }"
# No flags set, no extra mount options needed.
if [[ "$qflags_hex" == "0" ]]; then
return 0
fi
if [[ ! "$qflags_hex" =~ ^0x[0-9a-fA-F]+$ ]]; then
logerror "xfs_db unexpected output"
return 1
fi
# Check XFS quota flags and set MOUNT_OPTIONS appropriately
# The quota flags as defined in Linux kernel source: fs/xfs/libxfs/xfs_log_format.h:
# XFS_UQUOTA_ACCT = 0x0001
# XFS_UQUOTA_ENFD = 0x0002
# XFS_GQUOTA_ACCT = 0x0040
# XFS_GQUOTA_ENFD = 0x0080
# XFS_PQUOTA_ACCT = 0x0008
# XFS_PQUOTA_ENFD = 0x0200
if [ $(($qflags_hex & 0x0001)) -ne 0 ]; then
if [ $(($qflags_hex & 0x0002)) -ne 0 ]; then
MOUNT_OPTIONS="${MOUNT_OPTIONS}uquota,"
else
MOUNT_OPTIONS="${MOUNT_OPTIONS}uqnoenforce,"
fi
fi
if [ $(($qflags_hex & 0x0040)) -ne 0 ]; then
if [ $(($qflags_hex & 0x0080)) -ne 0 ]; then
MOUNT_OPTIONS="${MOUNT_OPTIONS}gquota,"
else
MOUNT_OPTIONS="${MOUNT_OPTIONS}gqnoenforce,"
fi
fi
if [ $(($qflags_hex & 0x0008)) -ne 0 ]; then
if [ $(($qflags_hex & 0x0200)) -ne 0 ]; then
MOUNT_OPTIONS="${MOUNT_OPTIONS}pquota,"
else
MOUNT_OPTIONS="${MOUNT_OPTIONS}pqnoenforce,"
fi
fi
# Trim trailing comma
MOUNT_OPTIONS="${MOUNT_OPTIONS%,}"
if [[ -n "$MOUNT_OPTIONS" ]]; then
logmsg "mount options for xfs: ${MOUNT_OPTIONS}"
fi
}
fsextend() {
if [ "$DO_UNMOUNT" -eq 1 ]; then
logmsg "unmount ${MOUNTDIR}"
@@ -98,7 +169,7 @@ fsextend() {
fi
fi
fi
if [ "$DO_CRYPTRESIZE" -eq 1 ]; then
logmsg "cryptsetup resize ${DEVPATH}"
if cryptsetup resize "$DEVPATH"; then
@@ -110,8 +181,12 @@ fsextend() {
fi
if [ "$DO_MOUNT" -eq 1 ]; then
if [[ "$FSTYPE" == "xfs" ]]; then
detect_xfs_mount_options "$DEVPATH" || logmsg "not using XFS mount options"
fi
logmsg "mount ${DEVPATH} ${TMPDIR}"
if mount -t "$FSTYPE" "$DEVPATH" "$TMPDIR"; then
if mount -t "$FSTYPE" ${MOUNT_OPTIONS:+-o "$MOUNT_OPTIONS"} "$DEVPATH" "$TMPDIR"; then
logmsg "mount done"
TMP_MOUNT_DONE=1
else
@@ -170,8 +245,12 @@ fsextend() {
# If the fs was temporarily unmounted, now remount it.
# Not considered a command failure if this fails.
if [[ $DO_UNMOUNT -eq 1 && $REMOUNT -eq 1 ]]; then
if [[ "$FSTYPE" == "xfs" ]]; then
detect_xfs_mount_options "$DEVPATH" || logmsg "not using XFS mount options"
fi
logmsg "remount ${DEVPATH} ${MOUNTDIR}"
if mount -t "$FSTYPE" "$DEVPATH" "$MOUNTDIR"; then
if mount -t "$FSTYPE" ${MOUNT_OPTIONS:+-o "$MOUNT_OPTIONS"} "$DEVPATH" "$MOUNTDIR"; then
logmsg "remount done"
else
logmsg "remount failed"
@@ -384,6 +463,9 @@ DO_FSCK=0
# mounted and the script unmounted it.
REMOUNT=0
# Initialize MOUNT_OPTIONS to ensure clean state
MOUNT_OPTIONS=""
if [ "$UID" != 0 ] && [ "$EUID" != 0 ]; then
errorexit "${SCRIPTNAME} must be run as root."
fi

View File

@@ -2003,8 +2003,8 @@ have_raid_resizable() {
# array resync, so it's better to skip the test for affected kernels.
case "$(uname -r)" in
6.1[34]*) return 1 ;;
5.14.0-611.el9.*) return 1 ;; # Kernel is missing fixing commit!
6.12.0-124.el10.*) return 1 ;; # -- '' --
5.14.0-61[123].el9.*) return 1 ;; # Kernel is missing fixing commit!
6.12.0-12[456].el10.*) return 1 ;; # -- '' --
esac
}

View File

@@ -89,12 +89,24 @@ check lv_field $vg/$lv lv_size "380.00m"
df --output=size "$mount_dir" |tee df2
not diff df1 df2
# lvextend, xfs, active, not mounted, quotas defined, --fs resize
umount "$mount_dir"
mount -o uquota,gquota,pquota "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
umount "$mount_dir"
lvextend -y --fs resize -L+10M $vg/$lv | tee out
grep "mount options for xfs: uquota,gquota,pquota" out # must preserve the mount options!
# lvextend, xfs, active, not mounted, quotas not defined, --fs resize
mount "$DM_DEV_DIR/$vg/$lv" "$mount_dir"
umount "$mount_dir"
lvextend -y --fs resize -L+10M $vg/$lv | tee out
not grep "mount options for xfs" out # mount options not needed
lvchange -an $vg/$lv
# lvextend, xfs, inactive, --fs ignore
lvextend --fs ignore -L+20M $vg/$lv
check lv_field $vg/$lv lv_size "400.00m"
check lv_field $vg/$lv lv_size "420.00m"
lvremove -f $vg/$lv

View File

@@ -40,25 +40,15 @@ arg(activationmode_ARG, '\0', "activationmode", activationmode_VAL, 0, 0,
"For default, see \\fBlvm.conf\\fP(5) activation_mode.\n"
"See \\fBlvmraid\\fP(7) for more information.\n")
arg(addtag_ARG, '\0', "addtag", tag_VAL, ARG_GROUPABLE, 0,
"Adds a tag to a PV, VG or LV. This option can be repeated to add\n"
"multiple tags at once. See \\fBlvm\\fP(8) for information about tags.\n")
arg(adddev_ARG, '\0', "adddev", pv_VAL, 0, 0,
"Add a device to the devices file.\n")
arg(deldev_ARG, '\0', "deldev", string_VAL, 0, 0,
"Remove a device from the devices file.\n"
"When used alone, --deldev specifies a device name.\n"
"When used with --deviceidtype, --deldev specifies a device id.\n")
arg(delnotfound_ARG, '\0', "delnotfound", 0, 0, 0,
"Remove devices file entries with no matching device.\n")
arg(addpvid_ARG, '\0', "addpvid", string_VAL, 0, 0,
"Find a device with the PVID and add the device to the devices file.\n")
arg(delpvid_ARG, '\0', "delpvid", string_VAL, 0, 0,
"Remove a device with the PVID from the devices file.\n")
arg(addtag_ARG, '\0', "addtag", tag_VAL, ARG_GROUPABLE, 0,
"Adds a tag to a PV, VG or LV. This option can be repeated to add\n"
"multiple tags at once. See \\fBlvm\\fP(8) for information about tags.\n")
arg(aligned_ARG, '\0', "aligned", 0, 0, 0,
"Use with --separator to align the output columns.\n")
@@ -108,17 +98,6 @@ arg(autoactivation_ARG, '\0', "autoactivation", string_VAL, 0, 0,
"to event activation, such as device scanning optimizations\n"
"using pvs_online files created by event-based pvscans.\n")
arg(setautoactivation_ARG, '\0', "setautoactivation", bool_VAL, 0, 0,
"Set the autoactivation property on a VG or LV.\n"
"Display the property with vgs or lvs \"-o autoactivation\".\n"
"When the autoactivation property is disabled, the VG or LV\n"
"will not be activated by a command doing autoactivation\n"
"(vgchange, lvchange, or pvscan using -aay.)\n"
"If autoactivation is disabled on a VG, no LVs will be autoactivated\n"
"in that VG, and the LV autoactivation property has no effect.\n"
"If autoactivation is enabled on a VG, autoactivation can be disabled\n"
"for individual LVs.\n")
arg(binary_ARG, '\0', "binary", 0, 0, 0,
"Use binary values \"0\" or \"1\" instead of descriptive literal values\n"
"for columns that have exactly two valid values to report (not counting\n"
@@ -145,6 +124,9 @@ arg(cache_long_ARG, '\0', "cache", 0, ARG_LONG_OPT, 0,
"#lvscan\n"
"This option is no longer used.\n")
arg(cachedevice_ARG, '\0', "cachedevice", pv_VAL, ARG_GROUPABLE, 0,
"The name of a device to use for a cache.\n")
arg(cachemetadataformat_ARG, '\0', "cachemetadataformat", cachemetadataformat_VAL, 0, 0,
"Specifies the cache metadata format used by cache target.\n")
@@ -161,22 +143,40 @@ arg(cachemode_ARG, '\0', "cachemode", cachemode_VAL, 0, 0,
"forwarded to the origin LV; additionally, write hits cause cache\n"
"block invalidates. See \\fBlvmcache\\fP(7) for more information.\n")
arg(cachepolicy_ARG, '\0', "cachepolicy", string_VAL, 0, 0,
"Specifies the cache policy for a cache LV.\n"
"See \\fBlvmcache\\fP(7) for more information.\n")
arg(cachepool_ARG, '\0', "cachepool", lv_VAL, 0, 0,
"The name of a cache pool.\n")
arg(cachevol_ARG, '\0', "cachevol", lv_VAL, 0, 0,
"The name of a cache volume.\n")
arg(cachedevice_ARG, '\0', "cachedevice", pv_VAL, ARG_GROUPABLE, 0,
"The name of a device to use for a cache.\n")
arg(cachesettings_ARG, '\0', "cachesettings", string_VAL, ARG_GROUPABLE, 0,
"Specifies tunable kernel options for dm-cache or dm-writecache LVs.\n"
"Use the form 'option=value' or 'option1=value option2=value', or\n"
"repeat --cachesettings for each option being set.\n"
"These settings override the default kernel behaviors which are\n"
"usually adequate. To remove cachesettings and revert to the default\n"
"kernel behaviors, use --cachesettings 'default' for dm-cache or\n"
"an empty string --cachesettings '' for dm-writecache.\n"
"See \\fBlvmcache\\fP(7) for more information.\n")
arg(cachesize_ARG, '\0', "cachesize", sizemb_VAL, 0, 0,
"The size of cache to use.\n")
arg(cachevol_ARG, '\0', "cachevol", lv_VAL, 0, 0,
"The name of a cache volume.\n")
arg(check_ARG, '\0', "check", 0, 0, 0,
"Checks the content of the devices file.\n"
"Reports incorrect device names or PVIDs for entries.\n")
arg(checkcomplete_ARG, '\0', "checkcomplete", 0, 0, 0,
"Check if all the devices used by a VG or LV are present,\n"
"and print \"complete\" or \"incomplete\" for each listed\n"
"VG or LV. This option is used as a part of event-based\n"
"autoactivation, so pvscan will do nothing if this option\n"
"is set and event_activation=0 in the config settings.\n")
arg(commandprofile_ARG, '\0', "commandprofile", string_VAL, 0, 0,
"The command profile to use for command configuration.\n"
"See \\fBlvm.conf\\fP(5) for more information about profiles.\n")
@@ -194,40 +194,6 @@ arg(config_ARG, '\0', "config", string_VAL, 0, 0,
arg(configreport_ARG, '\0', "configreport", configreport_VAL, ARG_GROUPABLE, 1,
"See \\fBlvmreport\\fP(7).\n")
arg(configtype_ARG, '\0', "typeconfig", configtype_VAL, 0, 0,
"\\fBcurrent\\fP prints the config settings that would be applied\n"
"to an lvm command (assuming the command does not override them\n"
"on the command line.) This includes:\n"
"settings that have been modified in lvm config files,\n"
"settings that get their default values from config files,\n"
"and default settings that have been uncommented in config files.\n"
"\\fBdefault\\fP prints all settings with their default values.\n"
"Changes made in lvm config files are not reflected in the output.\n"
"Some settings get their default values internally,\n"
"and these settings are printed as comments.\n"
"Other settings get their default values from config files,\n"
"and these settings are not printed as comments.\n"
"\\fBdiff\\fP prints only config settings that have been modified\n"
"from their default values in config files (the difference between\n"
"current and default.)\n"
"\\fBfull\\fP prints every setting uncommented and set to the\n"
"current value, i.e. how it would be used by an lvm command.\n"
"This includes settings modified in config files, settings that usually\n"
"get defaults internally, and settings that get defaults from config files.\n"
"\\fBlist\\fP prints all config names without values.\n"
"\\fBmissing\\fP prints settings that are missing from the\n"
"lvm config files. A missing setting that usually gets its default\n"
"from config files is printed uncommented and set to the internal default.\n"
"Settings that get their default internally and are not set in config files\n"
"are printed commented with the internal default.\n"
"\\fBnew\\fP prints config settings that have been added since\n"
"the lvm version specified by --sinceversion. They are printed\n"
"with their default values.\n"
"\\fBprofilable\\fP prints settings with their default values that can be set from a profile.\n"
"\\fBprofilable-command\\fP prints settings with their default values that can be set from a command profile.\n"
"\\fBprofilable-metadata\\fP prints settings with their default values that can be set from a metadata profile.\n"
"Also see \\fBlvm.conf\\fP(5).\n")
arg(dataalignment_ARG, '\0', "dataalignment", sizekb_VAL, 0, 0,
"Align the start of a PV data area with a multiple of this number.\n"
"To see the location of the first Physical Extent (PE) of an existing PV,\n"
@@ -242,6 +208,17 @@ arg(deduplication_ARG, '\0', "deduplication", bool_VAL, 0, 0,
"Controls whether deduplication is enabled or disabled for VDO volume.\n"
"See \\fBlvmvdo\\fP(7) for more information about VDO usage.\n")
arg(deldev_ARG, '\0', "deldev", string_VAL, 0, 0,
"Remove a device from the devices file.\n"
"When used alone, --deldev specifies a device name.\n"
"When used with --deviceidtype, --deldev specifies a device id.\n")
arg(delnotfound_ARG, '\0', "delnotfound", 0, 0, 0,
"Remove devices file entries with no matching device.\n")
arg(delpvid_ARG, '\0', "delpvid", string_VAL, 0, 0,
"Remove a device with the PVID from the devices file.\n")
arg(deltag_ARG, '\0', "deltag", tag_VAL, ARG_GROUPABLE, 0,
"Deletes a tag from a PV, VG or LV. This option can be repeated to delete\n"
"multiple tags at once. See \\fBlvm\\fP(8) for information about tags.\n")
@@ -386,6 +363,10 @@ arg(ignoreunsupported_ARG, '\0', "ignoreunsupported", 0, 0, 0,
arg(importdevices_ARG, '\0', "importdevices", 0, 0, 0,
"Add devices to the devices file.\n")
arg(integritysettings_ARG, '\0', "integritysettings", string_VAL, ARG_GROUPABLE, 0,
"Specifies tunable kernel options for dm-integrity.\n"
"See \\fBlvmraid\\fP(7) for more information.\n")
arg(journal_ARG, '\0', "journal", string_VAL, 0, 0,
"Record information in the systemd journal.\n"
"This information is in addition to information\n"
@@ -406,13 +387,6 @@ arg(listlvs_ARG, '\0', "listlvs", 0, 0, 0,
arg(listvg_ARG, '\0', "listvg", 0, 0, 0,
"Print the VG that uses the device.\n")
arg(checkcomplete_ARG, '\0', "checkcomplete", 0, 0, 0,
"Check if all the devices used by a VG or LV are present,\n"
"and print \"complete\" or \"incomplete\" for each listed\n"
"VG or LV. This option is used as a part of event-based\n"
"autoactivation, so pvscan will do nothing if this option\n"
"is set and event_activation=0 in the config settings.\n")
arg(lockopt_ARG, '\0', "lockopt", string_VAL, 0, 0,
"Used to pass options for special cases to lvmlockd.\n"
"See \\fBlvmlockd\\fP(8) for more information.\n")
@@ -455,6 +429,15 @@ arg(merge_ARG, '\0', "merge", 0, 0, 0,
"An alias for --mergethin, --mergemirrors, or --mergesnapshot,\n"
"depending on the type of LV.\n")
arg(mergedconfig_ARG, '\0', "mergedconfig", 0, 0, 0,
"When the command is run with --config\n"
"and/or --commandprofile (or using LVM_COMMAND_PROFILE\n"
"environment variable), --profile, or --metadataprofile,\n"
"merge all the contents of the \"config cascade\" before displaying it.\n"
"Without merging, only the configuration at the front of the\n"
"cascade is displayed.\n"
"See \\fBlvm.conf\\fP(5) for more information about config.\n")
arg(mergemirrors_ARG, '\0', "mergemirrors", 0, 0, 0,
"Merge LV images that were split from a raid1 LV.\n"
"See --splitmirrors with --trackchanges.\n")
@@ -479,15 +462,6 @@ arg(mergethin_ARG, '\0', "mergethin", 0, 0, 0,
"and the thin snapshot LV is removed.\n"
"See \\fBlvmthin\\fP(7) for more information.\n")
arg(mergedconfig_ARG, '\0', "mergedconfig", 0, 0, 0,
"When the command is run with --config\n"
"and/or --commandprofile (or using LVM_COMMAND_PROFILE\n"
"environment variable), --profile, or --metadataprofile,\n"
"merge all the contents of the \"config cascade\" before displaying it.\n"
"Without merging, only the configuration at the front of the\n"
"cascade is displayed.\n"
"See \\fBlvm.conf\\fP(5) for more information about config.\n")
arg(metadataignore_ARG, '\0', "metadataignore", bool_VAL, 0, 0,
"Specifies the metadataignore property of a PV.\n"
"If yes, metadata areas on the PV are ignored, and lvm will\n"
@@ -601,15 +575,6 @@ arg(originname_ARG, '\0', "originname", lv_VAL, 0, 0,
"to a thin LV. The LV being converted becomes a read-only external origin\n"
"with this name.\n")
arg(setphysicalvolumesize_ARG, '\0', "setphysicalvolumesize", sizemb_VAL, 0, 0,
"Overrides the automatically detected size of the PV.\n"
"Use with care, or prior to reducing the physical size of the device.\n")
arg(settings_ARG, '\0', "settings", string_VAL, ARG_GROUPABLE, 0,
"Specifies command specific settings in \"Key = Value\" form.\n"
"Combine multiple settings in quotes, or repeat the settings\n"
"option for each.\n")
arg(persist_ARG, '\0', "persist", string_VAL, 0, 0,
"Persistent Reservation operation.\n"
"start: register local key and acquire reservation.\n"
@@ -623,49 +588,6 @@ arg(persist_ARG, '\0', "persist", string_VAL, 0, 0,
"Write Exclusive, all registrants (WEAR) is used.\n"
"Use --setpersist to automate and/or require PR.\n")
arg(setpersist_ARG, '\0', "setpersist", string_VAL, 0, 0,
"#vgcreate\n"
"Set flags to control persistent reservation behavior.\n"
"y: set require and autostart flags.\n"
"require: PR will be required to write or activate VG.\n"
"autostart: PR will be automatically started.\n"
"ptpl: use persist through power loss on devices.\n"
"When autostart is enabled, autoactivation and auto-lockstart\n"
"commands will first start PR.\n"
"lvmlocal.conf pr_key or host_id must be configured to use PR.\n"
"For local VGs, enabling system_id is also recommended.\n"
"#vgchange\n"
"Set or clear flags to control persistent reservation behavior.\n"
"y: set require and autostart flags.\n"
"n: clear require and autostart flags.\n"
"require: set flag, PR will be required to write or activate VG.\n"
"norequire: clear require flag.\n"
"autostart: set flag, PR will be automatically started.\n"
"noautostart: clear autostart flag.\n"
"ptpl: set flag, use persist through power loss on devices.\n"
"noptpl: clear ptpl flag.\n"
"When autostart is enabled, autoactivation and auto-lockstart\n"
"commands will first start PR.\n"
"lvmlocal.conf pr_key or host_id must be configured to use PR.\n"
"For local VGs, enabling system_id is also recommended.\n")
arg(setlockargs_ARG, '\0', "setlockargs", string_VAL, 0, 0,
"Add or remove lock_args settings for a shared VG.\n"
"The lock_args determine lock manager behavior for the VG.\n"
"These settings are only allowed for lock_type sanlock.\n"
"persist: use persistent reservations for lock recovery.\n"
"lvmlockd will preempt-abort the persistent reservation of a failed\n"
"lock owner so that the lock can be acquired.\n"
"notimeout: use locks that do not time out when the owner fails.\n"
"In this case, a lock owned by a failed host can only be acquired\n"
"using the persist feature.\n"
"nopersist: do not use the persist feature.\n"
"timeout: do not use the notimeout feature.\n"
"The default behavior with no settings configured is: nopersist and timeout.\n")
arg(removekey_ARG, '\0', "removekey", string_VAL, 0, 0,
"A persistent reservation key to remove.\n")
arg(poll_ARG, '\0', "poll", bool_VAL, 0, 0,
"When yes, start the background transformation of an LV.\n"
"An incomplete transformation, e.g. pvmove or lvconvert interrupted\n"
@@ -740,6 +662,14 @@ arg(readonly_ARG, '\0', "readonly", 0, 0, 0,
"Prevent the command from making changes, including activation and\n"
"metadata updates. (See --permission r for read only LVs.)\n")
arg(rebuild_ARG, '\0', "rebuild", pv_VAL, ARG_GROUPABLE, 0,
"Selects a PV to rebuild in a raid LV. Multiple PVs can be rebuilt by\n"
"repeating this option.\n"
"Use this option in place of --resync or --syncaction repair when the\n"
"PVs with corrupted data are known, and their data should be reconstructed\n"
"rather than reconstructing default (rotating) data.\n"
"See \\fBlvmraid\\fP(7) for more information.\n")
arg(refresh_ARG, '\0', "refresh", 0, 0, 0,
"#lvmdevices\n"
"Search for missing PVs on new devices, and update the devices file\n"
@@ -763,6 +693,9 @@ arg(refresh_ARG, '\0', "refresh", 0, 0, 0,
"Also, this operation may be useful if something has gone wrong,\n"
"or if some form of manual LV sharing is being used.\n")
arg(removekey_ARG, '\0', "removekey", string_VAL, 0, 0,
"A persistent reservation key to remove.\n")
arg(removemissing_ARG, '\0', "removemissing", 0, 0, 0,
"Removes all missing PVs from the VG, if there are no LVs allocated\n"
"on them. This resumes normal operation of the VG (new LVs may again\n"
@@ -775,14 +708,6 @@ arg(removemissing_ARG, '\0', "removemissing", 0, 0, 0,
"If LVs spanned several disks, including ones that are lost, salvaging\n"
"some data first may be possible by activating LVs in partial mode.\n")
arg(rebuild_ARG, '\0', "rebuild", pv_VAL, ARG_GROUPABLE, 0,
"Selects a PV to rebuild in a raid LV. Multiple PVs can be rebuilt by\n"
"repeating this option.\n"
"Use this option in place of --resync or --syncaction repair when the\n"
"PVs with corrupted data are known, and their data should be reconstructed\n"
"rather than reconstructing default (rotating) data.\n"
"See \\fBlvmraid\\fP(7) for more information.\n")
arg(repair_ARG, '\0', "repair", 0, 0, 0,
"#lvconvert\n"
"Replace failed PVs in a raid or mirror LV, or run a repair\n"
@@ -850,6 +775,66 @@ arg(segments_ARG, '\0', "segments", 0, 0, 0,
arg(separator_ARG, '\0', "separator", string_VAL, 0, 0,
"String to use to separate each column. Useful if grepping the output.\n")
arg(setautoactivation_ARG, '\0', "setautoactivation", bool_VAL, 0, 0,
"Set the autoactivation property on a VG or LV.\n"
"Display the property with vgs or lvs \"-o autoactivation\".\n"
"When the autoactivation property is disabled, the VG or LV\n"
"will not be activated by a command doing autoactivation\n"
"(vgchange, lvchange, or pvscan using -aay.)\n"
"If autoactivation is disabled on a VG, no LVs will be autoactivated\n"
"in that VG, and the LV autoactivation property has no effect.\n"
"If autoactivation is enabled on a VG, autoactivation can be disabled\n"
"for individual LVs.\n")
arg(setlockargs_ARG, '\0', "setlockargs", string_VAL, 0, 0,
"Add or remove lock_args settings for a shared VG.\n"
"The lock_args determine lock manager behavior for the VG.\n"
"These settings are only allowed for lock_type sanlock.\n"
"persist: use persistent reservations for lock recovery.\n"
"lvmlockd will preempt-abort the persistent reservation of a failed\n"
"lock owner so that the lock can be acquired.\n"
"notimeout: use locks that do not time out when the owner fails.\n"
"In this case, a lock owned by a failed host can only be acquired\n"
"using the persist feature.\n"
"nopersist: do not use the persist feature.\n"
"timeout: do not use the notimeout feature.\n"
"The default behavior with no settings configured is: nopersist and timeout.\n")
arg(setpersist_ARG, '\0', "setpersist", string_VAL, 0, 0,
"#vgcreate\n"
"Set flags to control persistent reservation behavior.\n"
"y: set require and autostart flags.\n"
"require: PR will be required to write or activate VG.\n"
"autostart: PR will be automatically started.\n"
"ptpl: use persist through power loss on devices.\n"
"When autostart is enabled, autoactivation and auto-lockstart\n"
"commands will first start PR.\n"
"lvmlocal.conf pr_key or host_id must be configured to use PR.\n"
"For local VGs, enabling system_id is also recommended.\n"
"#vgchange\n"
"Set or clear flags to control persistent reservation behavior.\n"
"y: set require and autostart flags.\n"
"n: clear require and autostart flags.\n"
"require: set flag, PR will be required to write or activate VG.\n"
"norequire: clear require flag.\n"
"autostart: set flag, PR will be automatically started.\n"
"noautostart: clear autostart flag.\n"
"ptpl: set flag, use persist through power loss on devices.\n"
"noptpl: clear ptpl flag.\n"
"When autostart is enabled, autoactivation and auto-lockstart\n"
"commands will first start PR.\n"
"lvmlocal.conf pr_key or host_id must be configured to use PR.\n"
"For local VGs, enabling system_id is also recommended.\n")
arg(setphysicalvolumesize_ARG, '\0', "setphysicalvolumesize", sizemb_VAL, 0, 0,
"Overrides the automatically detected size of the PV.\n"
"Use with care, or prior to reducing the physical size of the device.\n")
arg(settings_ARG, '\0', "settings", string_VAL, ARG_GROUPABLE, 0,
"Specifies command specific settings in \"Key = Value\" form.\n"
"Combine multiple settings in quotes, or repeat the settings\n"
"option for each.\n")
arg(shared_ARG, '\0', "shared", 0, 0, 0,
"#vgcreate\n"
"Create a shared VG using lvmlockd if LVM is compiled with lockd support.\n"
@@ -868,6 +853,21 @@ arg(shared_ARG, '\0', "shared", 0, 0, 0,
"lvmlockd is not being used on the host.\n"
"See \\fBlvmlockd\\fP(8) for more information about shared VGs.\n")
arg(showdeprecated_ARG, '\0', "showdeprecated", 0, 0, 0,
"Include deprecated configuration settings in the output. These settings\n"
"are deprecated after a certain version. If a concrete version is specified\n"
"with --atversion, deprecated settings are automatically included\n"
"if the specified version is lower than the version in which the settings were\n"
"deprecated. The current and diff types include deprecated settings\n"
"in their output by default, all the other types ignore deprecated settings.\n")
arg(showunsupported_ARG, '\0', "showunsupported", 0, 0, 0,
"Include unsupported configuration settings in the output. These settings\n"
"are either used for debugging or development purposes only, or their support\n"
"is not yet complete and they are not meant to be used in production. The\n"
"current and diff types include unsupported settings in their\n"
"output by default, all the other types ignore unsupported settings.\n")
arg(sinceversion_ARG, '\0', "sinceversion", string_VAL, 0, 0,
"Specify an LVM version in x.y.z format where x is the major version,\n"
"the y is the minor version and z is the patchlevel (e.g. 2.2.106).\n"
@@ -890,21 +890,6 @@ arg(splitsnapshot_ARG, '\0', "splitsnapshot", 0, 0, 0,
"contains the chunks that differ from the origin LV along with metadata\n"
"describing them. This LV can be wiped and then destroyed with lvremove.\n")
arg(showdeprecated_ARG, '\0', "showdeprecated", 0, 0, 0,
"Include deprecated configuration settings in the output. These settings\n"
"are deprecated after a certain version. If a concrete version is specified\n"
"with --atversion, deprecated settings are automatically included\n"
"if the specified version is lower than the version in which the settings were\n"
"deprecated. The current and diff types include deprecated settings\n"
"in their output by default, all the other types ignore deprecated settings.\n")
arg(showunsupported_ARG, '\0', "showunsupported", 0, 0, 0,
"Include unsupported configuration settings in the output. These settings\n"
"are either used for debugging or development purposes only, or their support\n"
"is not yet complete and they are not meant to be used in production. The\n"
"current and diff types include unsupported settings in their\n"
"output by default, all the other types ignore unsupported settings.\n")
arg(startpoll_ARG, '\0', "startpoll", 0, 0, 0,
"Start polling an LV to continue processing a conversion.\n")
@@ -991,6 +976,40 @@ arg(type_ARG, '\0', "type", segtype_VAL, 0, 0,
"--thin, --cache, --vdo).\n"
"Use inferred types with care because it can lead to unexpected results.\n")
arg(configtype_ARG, '\0', "typeconfig", configtype_VAL, 0, 0,
"\\fBcurrent\\fP prints the config settings that would be applied\n"
"to an lvm command (assuming the command does not override them\n"
"on the command line.) This includes:\n"
"settings that have been modified in lvm config files,\n"
"settings that get their default values from config files,\n"
"and default settings that have been uncommented in config files.\n"
"\\fBdefault\\fP prints all settings with their default values.\n"
"Changes made in lvm config files are not reflected in the output.\n"
"Some settings get their default values internally,\n"
"and these settings are printed as comments.\n"
"Other settings get their default values from config files,\n"
"and these settings are not printed as comments.\n"
"\\fBdiff\\fP prints only config settings that have been modified\n"
"from their default values in config files (the difference between\n"
"current and default.)\n"
"\\fBfull\\fP prints every setting uncommented and set to the\n"
"current value, i.e. how it would be used by an lvm command.\n"
"This includes settings modified in config files, settings that usually\n"
"get defaults internally, and settings that get defaults from config files.\n"
"\\fBlist\\fP prints all config names without values.\n"
"\\fBmissing\\fP prints settings that are missing from the\n"
"lvm config files. A missing setting that usually gets its default\n"
"from config files is printed uncommented and set to the internal default.\n"
"Settings that get their default internally and are not set in config files\n"
"are printed commented with the internal default.\n"
"\\fBnew\\fP prints config settings that have been added since\n"
"the lvm version specified by --sinceversion. They are printed\n"
"with their default values.\n"
"\\fBprofilable\\fP prints settings with their default values that can be set from a profile.\n"
"\\fBprofilable-command\\fP prints settings with their default values that can be set from a command profile.\n"
"\\fBprofilable-metadata\\fP prints settings with their default values that can be set from a metadata profile.\n"
"Also see \\fBlvm.conf\\fP(5).\n")
arg(udevoutput_ARG, '\0', "udevoutput", 0, 0, 0,
"Command output is modified to be imported from a udev rule.\n")
@@ -1001,23 +1020,6 @@ arg(uncache_ARG, '\0', "uncache", 0, 0, 0,
"Separates a cache pool from a cache LV, and deletes the unused cache pool LV.\n"
"Before the separation, the cache is flushed. Also see --splitcache.\n")
arg(update_ARG, '\0', "update", 0, 0, 0,
"Update the content of the devices file.\n")
arg(cachepolicy_ARG, '\0', "cachepolicy", string_VAL, 0, 0,
"Specifies the cache policy for a cache LV.\n"
"See \\fBlvmcache\\fP(7) for more information.\n")
arg(cachesettings_ARG, '\0', "cachesettings", string_VAL, ARG_GROUPABLE, 0,
"Specifies tunable kernel options for dm-cache or dm-writecache LVs.\n"
"Use the form 'option=value' or 'option1=value option2=value', or\n"
"repeat --cachesettings for each option being set.\n"
"These settings override the default kernel behaviors which are\n"
"usually adequate. To remove cachesettings and revert to the default\n"
"kernel behaviors, use --cachesettings 'default' for dm-cache or\n"
"an empty string --cachesettings '' for dm-writecache.\n"
"See \\fBlvmcache\\fP(7) for more information.\n")
arg(unconfigured_ARG, '\0', "unconfigured", 0, 0, 0,
"Internal option used for generating config file during build.\n")
@@ -1033,6 +1035,21 @@ arg(unquoted_ARG, '\0', "unquoted", 0, 0, 0,
"When used with --nameprefixes, output values in the field=value\n"
"pairs are not quoted.\n")
arg(update_ARG, '\0', "update", 0, 0, 0,
"Update the content of the devices file.\n")
arg(updatemetadata_ARG, '\0', "updatemetadata", 0, 0, 0,
"Update VG metadata to correct problems.\n"
"If VG metadata was updated while a PV was missing, and the PV\n"
"reappears with an old version of metadata, then this option\n"
"(or any other command that writes metadata) will update the\n"
"metadata on the previously missing PV. If a PV was removed\n"
"from a VG while it was missing, and the PV reappears, using\n"
"this option will clear the outdated metadata from the previously\n"
"missing PV. If metadata text is damaged on one PV, using this\n"
"option will replace the damaged metadata text. For more severe\n"
"damage, e.g. with headers, see \\fBpvck\\fP(8).\n")
arg(usepolicies_ARG, '\0', "usepolicies", 0, 0, 0,
"Perform an operation according to the policy configured in \\fBlvm.conf\\fP(5)\n"
"or a profile.\n")
@@ -1088,9 +1105,6 @@ arg(vgonline_ARG, '\0', "vgonline", 0, 0, 0,
"The first command to see a complete VG will report it uniquely.\n"
"Other commands to see the complete VG will report it differently.\n")
arg(withsummary_ARG, '\0', "withsummary", 0, 0, 0,
"Display a one line comment for each configuration node.\n")
arg(withcomments_ARG, '\0', "withcomments", 0, 0, 0,
"Display a full comment for each configuration node. For deprecated\n"
"settings, also display comments about deprecation.\n")
@@ -1104,6 +1118,9 @@ arg(withlocalpreamble_ARG, '\0', "withlocalpreamble", 0, 0, 0,
arg(withspaces_ARG, '\0', "withspaces", 0, 0, 0,
"Where appropriate, add more spaces in output for better readability.\n")
arg(withsummary_ARG, '\0', "withsummary", 0, 0, 0,
"Display a one line comment for each configuration node.\n")
arg(withversions_ARG, '\0', "withversions", 0, 0, 0,
"Also display a comment containing the version of introduction for\n"
"each configuration node. If the setting is deprecated, also display\n"
@@ -1141,24 +1158,28 @@ arg(writemostly_ARG, '\0', "writemostly", writemostly_VAL, ARG_GROUPABLE, 0,
* recognizes some of these and prints the option name to include
* the variant, e.g. man page generation prints --[raid]writebehind.
*/
arg(corelog_ARG, '\0', "corelog", 0, 0, 0, NULL)
arg(resizable_ARG, '\0', "resizable", bool_VAL, 0, 0, NULL)
arg(allocation_ARG, '\0', "allocation", bool_VAL, 0, 0, NULL)
arg(available_ARG, '\0', "available", activation_VAL, 0, 0, NULL)
arg(corelog_ARG, '\0', "corelog", 0, 0, 0, NULL)
arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_VAL, 0, 0, NULL)
arg(raidmaxrecoveryrate_ARG, '\0', "raidmaxrecoveryrate", sizekb_VAL, 0, 0, NULL)
arg(raidminrecoveryrate_ARG, '\0', "raidminrecoveryrate", sizekb_VAL, 0, 0, NULL)
arg(raidrebuild_ARG, '\0', "raidrebuild", pv_VAL, ARG_GROUPABLE, 0, NULL)
arg(raidsyncaction_ARG, '\0', "raidsyncaction", syncaction_VAL, 0, 0, NULL)
arg(raidwritemostly_ARG, '\0', "raidwritemostly", writemostly_VAL, ARG_GROUPABLE, 0, NULL)
arg(raidminrecoveryrate_ARG, '\0', "raidminrecoveryrate", sizekb_VAL, 0, 0, NULL)
arg(raidmaxrecoveryrate_ARG, '\0', "raidmaxrecoveryrate", sizekb_VAL, 0, 0, NULL)
arg(raidwritebehind_ARG, '\0', "raidwritebehind", number_VAL, 0, 0, NULL)
arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", sizemb_VAL, 0, 0, NULL)
arg(raidwritemostly_ARG, '\0', "raidwritemostly", writemostly_VAL, ARG_GROUPABLE, 0, NULL)
arg(resizable_ARG, '\0', "resizable", bool_VAL, 0, 0, NULL)
arg(split_ARG, '\0', "split", 0, 0, 0, NULL)
arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_VAL, 0, 0, NULL)
arg(virtualoriginsize_ARG, '\0', "virtualoriginsize", sizemb_VAL, 0, 0, NULL)
/*
* ... and now the short args.
*/
/* Not used */
arg(help2_ARG, '?', "", 0, 0, 0, NULL)
arg(activate_ARG, 'a', "activate", activation_VAL, 0, 0,
"#pvscan\n"
"Auto-activate LVs in a VG when the PVs scanned have completed the VG.\n"
@@ -1231,11 +1252,6 @@ arg(all_ARG, 'a', "all", 0, 0, 0,
"Show information about devices that have not been initialized\n"
"by LVM, i.e. they are not PVs.\n")
arg(autobackup_ARG, 'A', "autobackup", bool_VAL, 0, 0,
"Specifies if metadata should be backed up automatically after a change.\n"
"Enabling this is strongly advised!\n"
"See \\fBvgcfgbackup\\fP(8) for more information.\n")
arg(activevolumegroups_ARG, 'A', "activevolumegroups", 0, 0, 0,
"Only select active VGs. The VG is considered active\n"
"if at least one of its LVs is active.\n")
@@ -1248,18 +1264,16 @@ arg(allpvs_ARG, 'A', "allpvs", 0, 0, 0,
"Show information about PVs outside the devices file.\n"
"Displays the device ID for PVs included in the devices file.\n")
arg(autobackup_ARG, 'A', "autobackup", bool_VAL, 0, 0,
"Specifies if metadata should be backed up automatically after a change.\n"
"Enabling this is strongly advised!\n"
"See \\fBvgcfgbackup\\fP(8) for more information.\n")
arg(background_ARG, 'b', "background", 0, 0, 0,
"If the operation requires polling, this option causes the command to\n"
"return before the operation is complete, and polling is done in the\n"
"background.\n")
arg(basevgname_ARG, 'n', "basevgname", string_VAL, 0, 0,
"By default the snapshot VG will be renamed to the original name plus a\n"
"numeric suffix to avoid duplicate naming (e.g. 'test_vg' would be renamed\n"
"to 'test_vg1'). This option will override the base VG name that is\n"
"used for all VG renames. If a VG already exists with the specified name\n"
"a numeric suffix will be added (like the previous example) to make it unique.\n")
arg(blockdevice_ARG, 'b', "blockdevice", 0, 0, 0,
"No longer used.\n")
@@ -1402,9 +1416,6 @@ arg(history_ARG, 'H', "history", 0, 0, 0,
"(This has no effect unless LVs were removed while\n"
"\\fBlvm.conf\\fP(5) \\fBmetadata/record_lvs_history\\fP was enabled.\n")
/* Not used */
arg(help2_ARG, '?', "", 0, 0, 0, NULL)
arg(import_ARG, 'i', "import", 0, 0, 0,
"Import exported VGs. Otherwise VGs that have been exported\n"
"will not be changed (nor will their associated PVs).\n")
@@ -1433,11 +1444,24 @@ arg(stripesize_ARG, 'I', "stripesize", sizekb_VAL, 0, 0,
"The amount of data that is written to one device before\n"
"moving to the next in a striped LV.\n")
arg(logicalvolume_ARG, 'l', "logicalvolume", uint32_VAL, 0, 0,
"Sets the maximum number of LVs allowed in a VG.\n")
arg(major_ARG, 'j', "major", number_VAL, ARG_GROUPABLE, 0,
"#lvcreate\n"
"#lvchange\n"
"Sets the major number of an LV block device.\n"
"#pvscan\n"
"The major number of a device.\n")
arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", uint32_VAL, 0, 0,
"Sets the maximum number of LVs allowed in a VG.\n")
arg(setactivationskip_ARG, 'k', "setactivationskip", bool_VAL, 0, 0,
"Persistently sets (yes) or clears (no) the \"activation skip\" flag on an LV.\n"
"An LV with this flag set is not activated unless the\n"
"--ignoreactivationskip option is used by the activation command.\n"
"This flag is set by default on new thin snapshot LVs.\n"
"The flag is not applied to deactivation.\n"
"The current value of the flag is indicated in the lvs lv_attr bits.\n")
arg(ignoreactivationskip_ARG, 'K', "ignoreactivationskip", 0, 0, 0,
"Ignore the \"activation skip\" LV flag during activation\n"
"to allow LVs with the flag set to be activated.\n")
/*
* The extents_VAL is overridden in configure_command_option_values()
@@ -1495,9 +1519,15 @@ arg(list_ARG, 'l', "list", 0, 0, 0,
"#vgmerge\n"
"Display merged destination VG like vgdisplay -v.\n")
arg(logicalvolume_ARG, 'l', "logicalvolume", uint32_VAL, 0, 0,
"Sets the maximum number of LVs allowed in a VG.\n")
arg(lvmpartition_ARG, 'l', "lvmpartition", 0, 0, 0,
"Only report PVs.\n")
arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", uint32_VAL, 0, 0,
"Sets the maximum number of LVs allowed in a VG.\n")
/*
* The sizemb_VAL is overridden in configure_command_option_values()
* according to the command being run. Different commands accept
@@ -1520,32 +1550,6 @@ arg(size_ARG, 'L', "size", sizemb_VAL, 0, 0,
"the value is not an absolute size, but is relative and added or subtracted\n"
"from the current size.\n")
arg(persistent_ARG, 'M', "persistent", bool_VAL, 0, 0,
"When yes, makes the specified minor number persistent.\n")
arg(major_ARG, 'j', "major", number_VAL, ARG_GROUPABLE, 0,
"#lvcreate\n"
"#lvchange\n"
"Sets the major number of an LV block device.\n"
"#pvscan\n"
"The major number of a device.\n")
arg(setactivationskip_ARG, 'k', "setactivationskip", bool_VAL, 0, 0,
"Persistently sets (yes) or clears (no) the \"activation skip\" flag on an LV.\n"
"An LV with this flag set is not activated unless the\n"
"--ignoreactivationskip option is used by the activation command.\n"
"This flag is set by default on new thin snapshot LVs.\n"
"The flag is not applied to deactivation.\n"
"The current value of the flag is indicated in the lvs lv_attr bits.\n")
arg(ignoreactivationskip_ARG, 'K', "ignoreactivationskip", 0, 0, 0,
"Ignore the \"activation skip\" LV flag during activation\n"
"to allow LVs with the flag set to be activated.\n")
arg(integritysettings_ARG, '\0', "integritysettings", string_VAL, ARG_GROUPABLE, 0,
"Specifies tunable kernel options for dm-integrity.\n"
"See \\fBlvmraid\\fP(7) for more information.\n")
arg(maps_ARG, 'm', "maps", 0, 0, 0,
"#lvdisplay\n"
"Display the mapping of logical extents to PVs and physical extents.\n"
@@ -1596,6 +1600,16 @@ arg(metadatatype_ARG, 'M', "metadatatype", metadatatype_VAL, 0, 0,
"\\fBlvm2\\fP (or just \\fB2\\fP) is the current, standard format.\n"
"\\fBlvm1\\fP (or just \\fB1\\fP) is no longer used.\n")
arg(persistent_ARG, 'M', "persistent", bool_VAL, 0, 0,
"When yes, makes the specified minor number persistent.\n")
arg(basevgname_ARG, 'n', "basevgname", string_VAL, 0, 0,
"By default the snapshot VG will be renamed to the original name plus a\n"
"numeric suffix to avoid duplicate naming (e.g. 'test_vg' would be renamed\n"
"to 'test_vg1'). This option will override the base VG name that is\n"
"used for all VG renames. If a VG already exists with the specified name\n"
"a numeric suffix will be added (like the previous example) to make it unique.\n")
arg(name_ARG, 'n', "name", string_VAL, 0, 0,
"#lvcreate\n"
"#lvconvert\n"
@@ -1680,14 +1694,14 @@ arg(resizefs_ARG, 'r', "resizefs", 0, 0, 0,
"mounting behavior, and --nofsck to disable fsck. See --fs for more options\n"
"(--resizefs is equivalent to --fs resize.)\n")
/* Not used */
arg(reset_ARG, 'R', "reset", 0, 0, 0, NULL)
arg(regionsize_ARG, 'R', "regionsize", regionsizemb_VAL, 0, 0,
"Size of each raid or mirror synchronization region.\n"
"\\fBlvm.conf\\fP(5) \\fBactivation/raid_region_size\\fP can be used to\n"
"configure a default.\n")
/* Not used */
arg(reset_ARG, 'R', "reset", 0, 0, 0, NULL)
arg(physicalextentsize_ARG, 's', "physicalextentsize", sizemb_VAL, 0, 0,
"#vgcreate\n"
"Sets the physical extent size of PVs in the VG.\n"
@@ -1708,6 +1722,14 @@ arg(physicalextentsize_ARG, 's', "physicalextentsize", sizemb_VAL, 0, 0,
"contiguous range of extents used in a LV must start\n"
"and end on an extent boundary.\n")
arg(short_ARG, 's', "short", 0, 0, 0,
"#pvdisplay\n"
"Only display the size of the given PVs.\n"
"#vgdisplay\n"
"Give a short listing showing the existence of VGs.\n"
"#pvscan\n"
"Short listing format.\n")
arg(snapshot_ARG, 's', "snapshot", 0, 0, 0,
"#lvcreate\n"
"Create a snapshot. Snapshots provide a \"frozen image\" of an origin LV.\n"
@@ -1739,14 +1761,6 @@ arg(snapshot_ARG, 's', "snapshot", 0, 0, 0,
"Combine a former COW snapshot LV with a former origin LV to reverse\n"
"a previous --splitsnapshot command.\n")
arg(short_ARG, 's', "short", 0, 0, 0,
"#pvdisplay\n"
"Only display the size of the given PVs.\n"
"#vgdisplay\n"
"Give a short listing showing the existence of VGs.\n"
"#pvscan\n"
"Short listing format.\n")
/* Not used */
arg(stdin_ARG, 's', "stdin", 0, 0, 0, NULL)
@@ -1774,18 +1788,6 @@ arg(thin_ARG, 'T', "thin", 0, 0, 0,
"See --type thin, --type thin-pool, and --virtualsize.\n"
"See \\fBlvmthin\\fP(7) for more information about LVM thin provisioning.\n")
arg(updatemetadata_ARG, '\0', "updatemetadata", 0, 0, 0,
"Update VG metadata to correct problems.\n"
"If VG metadata was updated while a PV was missing, and the PV\n"
"reappears with an old version of metadata, then this option\n"
"(or any other command that writes metadata) will update the\n"
"metadata on the previously missing PV. If a PV was removed\n"
"from a VG while it was missing, and the PV reappears, using\n"
"this option will clear the outdated metadata from the previously\n"
"missing PV. If metadata text is damaged on one PV, using this\n"
"option will replace the damaged metadata text. For more severe\n"
"damage, e.g. with headers, see \\fBpvck\\fP(8).\n")
arg(uuid_ARG, 'u', "uuid", 0, 0, 0,
"#pvchange\n"
"Generate new random UUID for specified PVs.\n"
@@ -1811,9 +1813,6 @@ arg(verbose_ARG, 'v', "verbose", 0, ARG_COUNTABLE, 0,
"Set verbose level. Repeat from 1 to 4 times to increase the detail\n"
"of messages sent to stdout and stderr.\n")
/* Not used */
arg(volumegroup_ARG, 'V', "volumegroup", 0, 0, 0, NULL)
arg(virtualsize_ARG, 'V', "virtualsize", sizemb_VAL, 0, 0,
"The virtual size of a new thin LV.\n"
"See \\fBlvmthin\\fP(7) for more information about LVM thin provisioning.\n"
@@ -1828,6 +1827,9 @@ arg(virtualsize_ARG, 'V', "virtualsize", sizemb_VAL, 0, 0,
"Snapshots are less efficient than thin provisioning when creating\n"
"large sparse LVs (GiB).\n")
/* Not used */
arg(volumegroup_ARG, 'V', "volumegroup", 0, 0, 0, NULL)
arg(wipesignatures_ARG, 'W', "wipesignatures", bool_VAL, 0, 0,
"Controls detection and subsequent wiping of signatures on new LVs.\n"
"There is a prompt for each signature detected to confirm its wiping\n"

View File

@@ -1815,7 +1815,7 @@ DESC: Start or stop processing LV conversions.
vgchange --activate Active
OO: --activationmode ActivationMode, --ignoreactivationskip, --partial, --sysinit,
--readonly, --ignorelockingfailure, --monitor Bool, --poll Bool,
--autoactivation String, --persist start, OO_VGCHANGE
--autoactivation String, --persist String, OO_VGCHANGE
OP: VG|Tag|Select ...
IO: --ignoreskippedcluster
ID: vgchange_activate

View File

@@ -387,24 +387,60 @@ static uint64_t _lv_to_bits(struct command *cmd, char *name)
static unsigned _find_lvm_command_enum(const char *name)
{
#ifdef MAN_PAGE_GENERATOR
/* Validate cmd_names & command_names arrays are properly sorted */
/* Validate cmd_names & command_names arrays are properly sorted.
* Also validate args.h options are sorted according to these rules:
* 1. sorted options without 'short_opt'st
* 2. sorted alias options (option without any description)
* 3. sorted options with and by short opt, long option name is secondary
* (Capital shorts opts are sorted after lowercase variant)
*/
static int _names_validated = 0;
int i;
int shorts_only = 0;
if (!_names_validated) {
if (!_names_validated++) {
for (i = 1; i < CMD_COUNT - 1; i++)
if (strcmp(cmd_names[i].name, cmd_names[i + 1].name) > 0) {
log_error("File cmds.h has unsorted name entry %s.",
cmd_names[i].name);
return 0;
log_error("File cmds.h has unsorted name entry (%s > %s).",
cmd_names[i].name, cmd_names[i + 1].name);
_names_validated = 0;
}
for (i = 0; i < LVM_COMMAND_COUNT - 1; ++i) /* assume > 1 */
if (strcmp(command_names[i].name, command_names[i + 1].name) > 0) {
log_error("File commands.h has unsorted name entry %s.",
command_names[i].name);
return 0;
log_error("File commands.h has unsorted name entry (%s > %s).",
command_names[i].name, command_names[i + 1].name);
_names_validated = 0;
}
_names_validated = 1;
for (i = 0; i < ARG_COUNT - 1; ++i) /* assume > 1 */
if (opt_names[i + 1].short_opt) {
shorts_only = 1;
if (toupper(opt_names[i].short_opt) > toupper(opt_names[i + 1].short_opt) ||
((toupper(opt_names[i].short_opt) == toupper(opt_names[i + 1].short_opt)) &&
(opt_names[i].short_opt < opt_names[i + 1].short_opt))) {
log_error("File args.h has unsorted short option name entry (%c,%s > %c,%s).",
opt_names[i].short_opt, opt_names[i].long_opt,
opt_names[i + 1].short_opt, opt_names[i + 1].long_opt);
_names_validated = 0;
} else if (opt_names[i].short_opt == opt_names[i + 1].short_opt)
goto comp_long;
} else {
if (shorts_only) {
log_error("File args.h has long option listed within the short option name "
"entry (%s).", opt_names[i + 1].long_opt);
_names_validated = 0;
}
comp_long:
if (opt_names[i].desc && opt_names[i + 1].desc &&
strcmp(opt_names[i].long_opt, opt_names[i + 1].long_opt) > 0) {
log_error("File args.h has unsorted long option name entry (%s > %s.",
opt_names[i].long_opt, opt_names[i + 1].long_opt);
_names_validated = 0;
}
}
if (!_names_validated)
return 0;
}
#endif
if ((name = bsearch(name, command_names[0].name, LVM_COMMAND_COUNT,
@@ -1244,8 +1280,15 @@ static int _long_name_compare(const void *on1, const void *on2)
{
const struct opt_name * const *optname1 = on1;
const struct opt_name * const *optname2 = on2;
int result;
return strcmp((*optname1)->long_opt + 2, (*optname2)->long_opt + 2);
result = strcmp((*optname1)->long_opt + 2, (*optname2)->long_opt + 2);
/* Use opt_enum as tiebreaker for stable sorting when long option names are identical */
if (result == 0)
result = (*optname1)->opt_enum - (*optname2)->opt_enum;
return result;
}
/* Create list of option names for printing alphabetically. */
@@ -1273,6 +1316,44 @@ static int _copy_line(const char **line, size_t max_line, int *position)
return len;
}
/*
* Comparison function for qsort to sort opt_args by opt field.
* This ensures options are ordered by their creation order from args.h.
*/
static int _compare_opt_args(const void *a, const void *b)
{
const struct opt_arg *opt_a = (const struct opt_arg *)a;
const struct opt_arg *opt_b = (const struct opt_arg *)b;
return opt_a->opt - opt_b->opt;
}
/*
* Sort optional_opt_args and required_opt_arg by opts field for
* consistent ordering in man page and help generation.
*/
static void _sort_opt_args(void)
{
struct command *cmd;
unsigned i;
for (i = 0; i < COMMAND_COUNT; i++) {
cmd = &commands[i];
if (cmd->oo_count > 1)
qsort(cmd->optional_opt_args, cmd->oo_count,
sizeof(struct opt_arg), _compare_opt_args);
if (cmd->ro_count > 1)
qsort(cmd->required_opt_args, cmd->ro_count,
sizeof(struct opt_arg), _compare_opt_args);
if (cmd->any_ro_count > 1)
qsort(&cmd->required_opt_args[cmd->ro_count], cmd->any_ro_count,
sizeof(struct opt_arg), _compare_opt_args);
}
}
int define_commands(struct cmd_context *cmdtool, const char *run_name)
{
struct command *cmd = NULL;
@@ -1472,6 +1553,8 @@ int define_commands(struct cmd_context *cmdtool, const char *run_name)
memset(&_oo_lines, 0, sizeof(_oo_lines));
_oo_line_count = 0;
_sort_opt_args();
return 1;
}

View File

@@ -691,7 +691,22 @@ static void _print_man_usage(char *lvmname, struct command *cmd)
if (_is_lvm_all_opt(opt_enum))
continue;
_print_bracket_ds_opt_name(opt_enum);
switch (opt_enum) {
case persist_ARG:
/* --persist may require specific argument (printed in bold) */
printf("[\n");
_print_man_option(cmd->name, opt_enum);
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
_print_def_man(cname, opt_enum, &cmd->optional_opt_args[oo].def, 1, NULL);
}
printf("\n]\n");
break;
default:
_print_bracket_ds_opt_name(opt_enum);
}
printf(".br\n");
}

View File

@@ -205,6 +205,7 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
const struct lv_list *lvl;
struct pv_list *pvl;
int do_activate = is_change_activating(activate);
const char *pr_op = NULL;
/*
* We can get here in the odd case where an LV is already active in
@@ -233,8 +234,23 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
}
}
if (do_activate && !persist_start_include(cmd, vg, (activate == CHANGE_AAY), 0, NULL))
return 0;
if (arg_is_set(cmd, persist_ARG))
pr_op = arg_str_value(cmd, persist_ARG, NULL);
/*
* vgchange -ay --persist start
* This command bypasses the persist_is_started check in vg_read (disable_pr_required.)
* It is not permitted for shared VGs, where PR start happens before lockstart.
* For non-shared VGs, require a successful persist_start() here before activating.
*/
if (do_activate && pr_op && !strcmp(pr_op, "start") && cmd->disable_pr_required) {
if (vg_is_shared(vg)) {
log_error("Activation with persist start not permitted for shared VG %s.", vg->name);
return 0;;
}
if (!persist_start_include(cmd, vg, (activate == CHANGE_AAY), 0, NULL))
return_0;
}
/*
* Safe, since we never write out new metadata here. Required for
@@ -284,6 +300,18 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
r = 0;
}
if (!do_activate && pr_op && !strcmp(pr_op, "stop")) {
/* For a shared VG, PR stop happens after lockstop. */
if (vg_is_shared(vg))
log_warn("WARNING: skipping persist stop for shared VG.");
else if (lvs_in_vg_activated(vg))
log_warn("WARNING: skipping persist stop for incomplete deactivation.");
else if (!persist_stop(cmd, vg)) {
log_error("Failed to stop persistent reservation.");
r = 0;
}
}
/*
* Possibly trigger auto-generation of system.devices:
* - if root_dm_uuid contains vg->id, and
@@ -1100,10 +1128,37 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
if (noupdate)
cmd->ignore_device_name_mismatch = 1;
/* Allow LVs to be deactivated without PR started. */
if (arg_is_set(cmd, activate_ARG) &&
!is_change_activating((activation_change_t)arg_uint_value(cmd, activate_ARG, CHANGE_AY)))
cmd->disable_pr_required = 1;
/*
* PR usage with activation/deactivation.
*/
if (arg_is_set(cmd, activate_ARG)) {
int is_activating = is_change_activating((activation_change_t)arg_uint_value(cmd, activate_ARG, CHANGE_AY));
/* Always allow deactivation without PR being started. */
if (!is_activating)
cmd->disable_pr_required = 1;
/* Either "-ay --persist start", or "-an --persist stop". */
if (arg_is_set(cmd, persist_ARG)) {
const char *pr_op = arg_str_value(cmd, persist_ARG, NULL);
if (strcmp(pr_op, "start") && strcmp(pr_op, "stop")) {
log_error("Invalid --persist usage.");
return ECMD_FAILED;
}
if ((!strcmp(pr_op, "start") && !is_activating) ||
(!strcmp(pr_op, "stop") && is_activating)) {
log_error("Invalid --persist usage.");
return ECMD_FAILED;
}
/*
* Setting disable_pr_required to bypass the
* persist_is_started check in vg_read requires
* persist_start in vgchange_activate.
*/
if (!strcmp(pr_op, "start") && is_activating)
cmd->disable_pr_required = 1;
}
}
/*
* If the devices file includes PVs stacked on LVs, then

View File

@@ -117,8 +117,8 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
!vg_set_max_pv(vg, vp_new.max_pv) ||
!vg_set_alloc_policy(vg, vp_new.alloc) ||
!vg_set_system_id(vg, vp_new.system_id) ||
!vg_set_persist(vg, pp.setpersist_flags) ||
!vg_set_mda_copies(vg, vp_new.vgmetadatacopies))
!vg_set_mda_copies(vg, vp_new.vgmetadatacopies) ||
!vg_set_persist(vg, pp.setpersist_flags))
goto_bad;
if (arg_is_set(cmd, setautoactivation_ARG) && !arg_int_value(cmd, setautoactivation_ARG, 1))
@@ -181,13 +181,15 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
* read without locks until the lockspace is done starting.)
*/
if (vg_is_shared(vg)) {
uint64_t our_key = 0;
if (pp.setpersist_flags &&
!persist_vgcreate_update(cmd, vg, pp.setpersist_flags)) {
!persist_vgcreate_update(cmd, vg, pp.setpersist_flags, &our_key)) {
log_error("Failed to start PR");
goto out;
}
if (!lockd_start_vg(cmd, vg, 0, NULL)) {
if (!lockd_start_vg(cmd, vg, our_key, NULL)) {
log_error("Failed to start locking");
goto out;
}

View File

@@ -74,6 +74,9 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
!lvremove_single(cmd, vg->pool_metadata_spare_lv, &void_handle))
return_ECMD_FAILED;
if (pr_stop && !persist_vgremove_before(cmd, vg, &pr_devs, &pr_key))
return_ECMD_FAILED;
if (!lockd_free_vg_before(cmd, vg, 0, arg_count(cmd, yes_ARG)))
return_ECMD_FAILED;
@@ -82,9 +85,6 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
online_vgremove(vg);
if (pr_stop && !persist_stop_prepare(cmd, vg, &pr_devs, &pr_key))
return_ECMD_FAILED;
vg_remove_pvs(vg);
if (!vg_remove(vg))
@@ -92,11 +92,8 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
lockd_free_vg_final(cmd, vg);
if (pr_stop) {
if (!persist_stop_run(cmd, vg, &pr_devs, pr_key))
log_warn("WARNING: persistent reservation not removed from devices.");
persist_key_file_remove(cmd, vg->name);
}
if (pr_stop)
persist_vgremove_after(cmd, vg, &pr_devs, pr_key);
return ECMD_PROCESSED;
}