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

Compare commits

..

1 Commits

Author SHA1 Message Date
David Teigland
813d333e0c vgcreate: support --setpersist
Previously, setpersist was only supported from 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-10 13:36:40 -05:00
66 changed files with 1567 additions and 3869 deletions

View File

@@ -1,6 +1,5 @@
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 hexadecimal.
# The local persistent reservation key in hexidecimal.
# 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,12 +934,9 @@ AC_MSG_RESULT([$BUILD_LOCKDSANLOCK])
dnl -- Look for sanlock libraries
AS_IF([test "$BUILD_LOCKDSANLOCK" = "yes"], [
# FIXME: forcing sanlock 4.2.0 for testing, default should be 370
# LOCKDSANLOCK_SUPPORT=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,7 +15,6 @@
#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>
@@ -144,7 +143,7 @@ int dmeventd_lvm2_command(struct dm_pool *mem, char *buffer, size_t size,
}
/* strip off the mirror component designations */
if ((layer = strstr(lv, MIRROR_SYNC_LAYER)) ||
if ((layer = strstr(lv, "_mimagetmp")) ||
(layer = strstr(lv, "_mlog")))
*layer = '\0';

View File

@@ -15,7 +15,7 @@ srcdir = @srcdir@
top_srcdir = @top_srcdir@
top_builddir = @top_builddir@
SOURCES = lvmlockd-core.c lvmlockd-helper.c
SOURCES = lvmlockd-core.c
SOURCES2 = lvmlockctl.c
TARGETS = lvmlockd lvmlockctl

View File

@@ -60,11 +60,4 @@ static inline void lvmlockd_close(daemon_handle h)
#define EIOTIMEOUT 225
#define ELOCKREPAIR 226
#define LOCKARGS_VERSION 0x00000001 /* meta only */
#define LOCKARGS_LVMLOCK 0x00000002 /* meta only */
#define LOCKARGS_TIMEOUT 0x00000004 /* user only */
#define LOCKARGS_NOTIMEOUT 0x00000008 /* meta or user */
#define LOCKARGS_PERSIST 0x00000010 /* meta or user */
#define LOCKARGS_NOPERSIST 0x00000020 /* user only */
#endif /* _LVM_LVMLOCKD_CLIENT_H */

File diff suppressed because it is too large Load Diff

View File

@@ -76,7 +76,7 @@ static int check_args_version(char *vg_args)
unsigned int major = 0;
int rv;
rv = lockd_lockargs_get_version(vg_args, &major, NULL, NULL);
rv = version_from_args(vg_args, &major, NULL, NULL);
if (rv < 0) {
log_error("check_args_version %s error %d", vg_args, rv);
return rv;

View File

@@ -1,264 +0,0 @@
/*
* Copyright 2025 Red Hat, Inc.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v2 or (at your option) any later version.
*/
#include <inttypes.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <poll.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <time.h>
#include <stdarg.h>
#include <signal.h>
#include <ctype.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/prctl.h>
#include <grp.h>
#include <syslog.h>
#include "lvmlockd-internal.h"
struct list_head commands; /* helper_msg_list entries */
static int _log_stderr;
#define log_helper(fmt, args...) \
do { \
if (_log_stderr) \
fprintf(stderr, fmt "\n", ##args); \
} while (0)
static void _save_command(struct helper_msg *msg)
{
struct helper_msg_list *ml;
ml = malloc(sizeof(struct helper_msg_list));
if (!ml)
return;
memcpy(&ml->msg, msg, sizeof(struct helper_msg));
list_add_tail(&ml->list, &commands);
}
static struct helper_msg_list *_get_command(int pid)
{
struct helper_msg_list *ml;
list_for_each_entry(ml, &commands, list) {
if (ml->msg.pid == pid)
return ml;
}
return NULL;
}
static int read_msg(int fd, struct helper_msg *msg)
{
int rv;
retry:
rv = read(fd, msg, sizeof(struct helper_msg));
if (rv == -1 && errno == EINTR)
goto retry;
if (rv != sizeof(struct helper_msg))
return -1;
return 0;
}
static void exec_command(char *cmd_str)
{
char arg[ONE_ARG_LEN];
char *av[MAX_AV_COUNT + 1]; /* +1 for NULL */
int av_count = 0;
int i, arg_len, cmd_len;
for (i = 0; i < MAX_AV_COUNT + 1; i++)
av[i] = NULL;
if (!cmd_str[0])
return;
/* this should already be done, but make sure */
cmd_str[RUN_COMMAND_LEN - 1] = '\0';
memset(&arg, 0, sizeof(arg));
arg_len = 0;
cmd_len = strlen(cmd_str);
for (i = 0; i < cmd_len; i++) {
if (!cmd_str[i])
break;
if (av_count == MAX_AV_COUNT)
break;
if (cmd_str[i] == '\\') {
if (i == (cmd_len - 1))
break;
i++;
if (cmd_str[i] == '\\') {
arg[arg_len++] = cmd_str[i];
continue;
}
if (isspace(cmd_str[i])) {
arg[arg_len++] = cmd_str[i];
continue;
} else {
break;
}
}
if (isalnum(cmd_str[i]) || ispunct(cmd_str[i])) {
arg[arg_len++] = cmd_str[i];
} else if (isspace(cmd_str[i])) {
if (arg_len)
av[av_count++] = strdup(arg);
memset(arg, 0, sizeof(arg));
arg_len = 0;
} else {
break;
}
}
if ((av_count < MAX_AV_COUNT) && arg_len) {
av[av_count++] = strdup(arg);
}
execvp(av[0], av);
}
static int send_result(struct helper_msg *msg, int fd)
{
int rv;
rv = write(fd, msg, sizeof(struct helper_msg));
if (rv == sizeof(struct helper_msg))
return 0;
return -1;
}
#define IDLE_TIMEOUT_MS (30 * 1000)
#define ACTIVE_TIMEOUT_MS 500
__attribute__((noreturn)) void helper_main(int in_fd, int out_fd, int log_stderr)
{
struct pollfd pollfd;
struct helper_msg msg;
struct helper_msg_list *ml;
siginfo_t info;
unsigned int fork_count = 0;
unsigned int done_count = 0;
int timeout = IDLE_TIMEOUT_MS;
int rv, pid;
INIT_LIST_HEAD(&commands);
_log_stderr = log_stderr;
rv = setgroups(0, NULL);
if (rv < 0)
log_helper("error clearing helper groups errno %i", errno);
memset(&pollfd, 0, sizeof(pollfd));
pollfd.fd = in_fd;
pollfd.events = POLLIN;
openlog("lvmlockd-helper", LOG_CONS | LOG_PID, LOG_LOCAL4);
while (1) {
rv = poll(&pollfd, 1, timeout);
if (rv == -1 && errno == EINTR)
continue;
if (rv < 0)
exit(0);
if (pollfd.revents & POLLIN) {
memset(&msg, 0, sizeof(msg));
rv = read_msg(in_fd, &msg);
if (rv)
continue;
if (msg.type == HELPER_COMMAND) {
pid = fork();
if (!pid) {
exec_command(msg.command);
exit(1);
}
msg.pid = pid;
_save_command(&msg);
fork_count++;
}
}
if (pollfd.revents & (POLLERR | POLLHUP | POLLNVAL))
exit(0);
/* collect child exits until no more children exist (ECHILD)
or none are ready (WNOHANG) */
while (1) {
memset(&info, 0, sizeof(info));
rv = waitid(P_ALL, 0, &info, WEXITED | WNOHANG);
if ((rv < 0) && (errno == ECHILD)) {
/*
log_helper("helper no children exist fork_count %d done_count %d", fork_count, done_count);
*/
timeout = IDLE_TIMEOUT_MS;
}
else if (!rv && !info.si_pid) {
log_helper("helper no children ready fork_count %d done_count %d", fork_count, done_count);
timeout = ACTIVE_TIMEOUT_MS;
}
else if (!rv && info.si_pid) {
done_count++;
if (!(ml = _get_command(info.si_pid))) {
log_helper("command for pid %d result %d not found",
info.si_pid, info.si_status);
continue;
}
log_helper("command for pid %d result %d done", info.si_pid, info.si_status);
ml->msg.type = HELPER_COMMAND_RESULT;
ml->msg.result = info.si_status;
send_result(&ml->msg, out_fd);
list_del(&ml->list);
free(ml);
continue;
}
else {
log_helper("helper waitid rv %d errno %d fork_count %d done_count %d",
rv, errno, fork_count, done_count);
}
break;
}
}
}

View File

@@ -63,10 +63,6 @@ enum {
LD_OP_QUERY_LOCK,
LD_OP_REFRESH_LV,
LD_OP_VG_STATUS,
LD_OP_FENCE,
LD_OP_FENCE_RESULT,
LD_OP_SETLOCKARGS_BEFORE,
LD_OP_SETLOCKARGS_FINAL,
};
/* resource types */
@@ -123,7 +119,6 @@ struct client {
#define LD_AF_ADOPT_ONLY 0x00200000 /* adopt orphan or fail */
#define LD_AF_NODELAY 0x00400000
#define LD_AF_REPAIR 0x00800000
#define LD_AF_NO_TIMEOUT 0x01000000
/*
* Number of times to repeat a lock request after
@@ -137,32 +132,6 @@ struct pvs {
int num;
};
#define RUN_COMMAND_LEN 1024
#define MAX_AV_COUNT 32
#define ONE_ARG_LEN 256
/* helper_msg types */
#define HELPER_COMMAND 0x1
#define HELPER_COMMAND_RESULT 0x2
struct helper_msg {
uint8_t type;
uint8_t act;
uint16_t unused1;
uint32_t msg_id;
int pid;
int result;
char ls_name[MAX_NAME+1];
uint8_t unused2;
uint16_t unused3;
char command[RUN_COMMAND_LEN];
};
struct helper_msg_list {
struct helper_msg msg;
struct list_head list;
};
#define OWNER_NAME_SIZE 64
#define OWNER_STATE_SIZE 32
@@ -178,13 +147,9 @@ struct action {
struct list_head list;
uint32_t client_id;
uint32_t flags; /* LD_AF_ */
uint32_t msg_id;
uint32_t version;
uint32_t host_id;
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_ */
@@ -201,7 +166,7 @@ struct action {
char lv_uuid[MAX_NAME+1];
char vg_args[MAX_ARGS+1];
char lv_args[MAX_ARGS+1];
char other_args[MAX_ARGS+1];
char prev_lv_args[MAX_ARGS+1];
struct owner owner;
struct pvs pvs; /* PV list for idm */
};
@@ -222,7 +187,6 @@ struct resource {
unsigned int use_vb : 1;
struct list_head locks;
struct list_head actions;
struct list_head fence_wait_actions;
char lv_args[MAX_ARGS+1];
char lm_data[]; /* lock manager specific data */
};
@@ -245,10 +209,8 @@ struct lockspace {
char vg_args[MAX_ARGS+1]; /* lock manager specific args */
int8_t lm_type; /* lock manager: LM_DLM, LM_SANLOCK */
void *lm_data;
uint32_t lock_args_flags;
uint32_t host_id;
uint64_t generation;
uint64_t ourkey;
uint64_t free_lock_offset; /* for sanlock, start search for free lock here */
struct pvs pvs; /* for idm: PV list */
@@ -263,14 +225,13 @@ struct lockspace {
unsigned int thread_done : 1;
unsigned int sanlock_gl_enabled: 1;
unsigned int sanlock_gl_dup: 1;
unsigned int free_vg: 1;
unsigned int kill_vg: 1;
unsigned int fence_pr: 1;
unsigned int no_timeout: 1;
unsigned int drop_vg: 1;
struct list_head actions; /* new client actions */
struct list_head resources; /* resource/lock state for gl/vg/lv */
struct list_head dispose; /* resources to free */
struct list_head fence_history; /* internally created actions for fencing */
};
/* val_blk version */
@@ -429,9 +390,7 @@ void log_level(int level, const char *fmt, ...) __attribute__((format(printf, 2
struct lockspace *alloc_lockspace(void);
int lockspaces_empty(void);
int last_string_from_args(char *args_in, char *last);
void helper_main(int in_fd, int out_fd, int log_stderr);
int lockd_lockargs_get_user_flags(const char *str, uint32_t *flags);
int lockd_lockargs_get_version(char *str, unsigned int *major, unsigned int *minor, unsigned int *patch);
int version_from_args(char *args, unsigned int *major, unsigned int *minor, unsigned int *patch);
static inline const char *mode_str(int x)
{
@@ -600,7 +559,7 @@ static inline int lm_refresh_lv_check_dlm(struct action *act)
#ifdef LOCKDSANLOCK_SUPPORT
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb, char *other_args);
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb);
int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char *lv_name, char *vg_args, char *lv_args, char *prev_args);
int lm_free_lv_sanlock(struct lockspace *ls, struct resource *r);
int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args);
@@ -625,9 +584,6 @@ int lm_data_size_sanlock(void);
int lm_is_running_sanlock(void);
int lm_find_free_lock_sanlock(struct lockspace *ls, uint64_t lv_size_bytes);
int lm_vg_status_sanlock(struct lockspace *ls, struct action *act);
void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner);
int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act);
int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act);
static inline int lm_support_sanlock(void)
{
@@ -636,7 +592,7 @@ static inline int lm_support_sanlock(void)
#else
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb, char *other_args)
static inline int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb)
{
return -1;
}
@@ -750,20 +706,6 @@ static inline int lm_support_sanlock(void)
return 0;
}
static inline void lm_set_host_dead_sanlock(struct lockspace *ls, struct owner *owner)
{
}
static inline int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act)
{
return 0;
}
static inline int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act)
{
return -1;
}
#endif /* sanlock support */
#ifdef LOCKDIDM_SUPPORT

View File

@@ -28,8 +28,6 @@
#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>
@@ -177,32 +175,30 @@ int lm_data_size_sanlock(void)
}
/*
* If a new variant of the lock_args string cannot be
* handled by the previous version of lvmlockd, then the
* new variant should contain a larger major number.
* lock_args format
*
* VG_LOCK_ARGS_V1 format:
* 1.0.0:lvname
* vg_lock_args format for sanlock is
* vg_version_string:undefined:lock_lv_name
*
* VG_LOCK_ARGS_V2 format:
* 2.0.0:lvname:notimeout:persist
* 2.0.0:lvname:notimeout
* 2.0.0:lvname:persist
* lv_lock_args format for sanlock is
* lv_version_string:undefined:offset
*
* version_string is MAJOR.MINOR.PATCH
* undefined may contain ":"
*
* If a new version of the lock_args string cannot be
* handled by an old version of lvmlockd, then the
* new lock_args string should contain a larger major number.
*/
#define VG_LOCK_ARGS_MAJOR 2
#define VG_LOCK_ARGS_MAJOR 1
#define VG_LOCK_ARGS_MINOR 0
#define VG_LOCK_ARGS_PATCH 0
#define VG_LOCK_ARGS_V1 "1.0.0"
#define VG_LOCK_ARGS_V2 "2.0.0"
#define LV_LOCK_ARGS_MAJOR 1
#define LV_LOCK_ARGS_MINOR 0
#define LV_LOCK_ARGS_PATCH 0
#define LV_LOCK_ARGS_V1 "1.0.0"
/*
* offset 0 is lockspace
* offset align_size * 1 is unused
@@ -245,31 +241,9 @@ static void strcpy_name_len(char *buf, const char *str, size_t len)
memccpy(buf, str, 0, len);
}
/*
* copy out lvname from lock_args string:
* 1.0.0:lvname
* 2.0.0:lvname
* 2.0.0:lvname:other
*/
static int lockd_lockargs_get_locklv(char *vg_args, char *lock_lv_name)
static int lock_lv_name_from_args(char *vg_args, char *lock_lv_name)
{
char args[MAX_ARGS+1] = {0};
char *p, *name;
strncpy(args, vg_args, MAX_ARGS);
if (!(p = strchr(args, ':')))
return -1;
name = p+1;
if (!*name)
return -1;
if ((p = strchr(name, ':')))
*p = '\0';
strncpy(lock_lv_name, name, MAX_ARGS);
return 0;
return last_string_from_args(vg_args, lock_lv_name);
}
static int lock_lv_offset_from_args(char *lv_args, uint64_t *lock_lv_offset)
@@ -295,7 +269,7 @@ static int check_args_version(char *args, unsigned int our_major)
unsigned int major = 0;
int rv;
rv = lockd_lockargs_get_version(args, &major, NULL, NULL);
rv = version_from_args(args, &major, NULL, NULL);
if (rv < 0) {
log_error("check_args_version %s error %d", args, rv);
return rv;
@@ -359,13 +333,13 @@ out:
}
#if LOCKDSANLOCK_SUPPORT >= 410
static int read_info_file(char *vg_name, uint32_t *host_id, uint64_t *generation, int *sector_size, int *align_size, int *no_timeout)
static int read_info_file(struct lockspace *ls, uint32_t *host_id, uint64_t *generation, int *sector_size, int *align_size)
{
char line[MAX_LINE];
char path[PATH_MAX] = { 0 };
FILE *fp;
if (dm_snprintf(path, sizeof(path), "/var/lib/lvm/lvmlockd_info_%s", vg_name) < 0)
if (dm_snprintf(path, sizeof(path), "/var/lib/lvm/lvmlockd_info_%s", ls->vg_name) < 0)
return -1;
if (!(fp = fopen(path, "r"))) {
@@ -388,14 +362,11 @@ static int read_info_file(char *vg_name, uint32_t *host_id, uint64_t *generation
} else if (!strncmp(line, "align_size ", 11)) {
if (sscanf(line, "align_size %d", align_size) != 1)
goto fail;
} else if (!strncmp(line, "no_timeout ", 11)) {
if (sscanf(line, "no_timeout %d", no_timeout) != 1)
goto fail;
}
}
_fclose(fp, path);
log_debug("info file: read %u %llu %d %d %d", *host_id, (unsigned long long)*generation, *sector_size, *align_size, *no_timeout);
log_debug("info file: read %u %llu %d %d", *host_id, (unsigned long long)*generation, *sector_size, *align_size);
return 0;
fail:
@@ -405,13 +376,14 @@ fail:
}
#endif
static int write_info_file(char *vg_name, uint32_t host_id, uint64_t generation, int sector_size, int align_size, int no_timeout)
static int write_info_file(struct lockspace *ls)
{
struct lm_sanlock *lms = (struct lm_sanlock *)ls->lm_data;
char path[PATH_MAX] = { 0 };
FILE *fp;
time_t t = time(NULL);
if (dm_snprintf(path, sizeof(path), "/var/lib/lvm/lvmlockd_info_%s", vg_name) < 0)
if (dm_snprintf(path, sizeof(path), "/var/lib/lvm/lvmlockd_info_%s", ls->vg_name) < 0)
return -1;
if (!(fp = fopen(path, "w"))) {
@@ -419,18 +391,17 @@ static int write_info_file(char *vg_name, uint32_t host_id, uint64_t generation,
return -1;
}
fprintf(fp, "# vg %s created %s", vg_name, ctime(&t));
fprintf(fp, "host_id %u\n", host_id);
fprintf(fp, "generation %llu\n", (unsigned long long)generation);
fprintf(fp, "sector_size %d\n", sector_size);
fprintf(fp, "align_size %d\n", align_size);
fprintf(fp, "no_timeout %d\n", no_timeout);
fprintf(fp, "# vg %s %s created %s", ls->vg_name, ls->vg_uuid, ctime(&t));
fprintf(fp, "host_id %u\n", ls->host_id);
fprintf(fp, "generation %llu\n", (unsigned long long)ls->generation);
fprintf(fp, "sector_size %d\n", lms->sector_size);
fprintf(fp, "align_size %d\n", lms->align_size);
if (fflush(fp))
log_warn("Failed to write/flush %s", path);
_fclose(fp, path);
log_debug("info file: wrote %u %llu %d %d %d", host_id, (unsigned long long)generation, sector_size, align_size, no_timeout);
log_debug("info file: wrote %u %llu %d %d", ls->host_id, (unsigned long long)ls->generation, lms->sector_size, lms->align_size);
return 0;
}
@@ -620,7 +591,7 @@ static int _lease_corrupt_error(int rv)
sanlock encoded this in the lockspace/resource structs on disk. */
static int read_lockspace_info(char *path, uint32_t host_id, int *sector_size, int *align_size, int *align_mb,
uint32_t *ss_size_flags, uint32_t *rs_size_flags, int *no_timeout, struct sanlk_host *hs)
uint32_t *ss_flags, uint32_t *rs_flags, struct sanlk_host *hs)
{
struct sanlk_lockspace ss;
uint32_t io_timeout = 0;
@@ -652,43 +623,40 @@ static int read_lockspace_info(char *path, uint32_t host_id, int *sector_size, i
*sector_size = 4096;
*align_mb = 8;
*align_size = 8 * ONE_MB;
*ss_size_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M;
*rs_size_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M;
*ss_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M;
*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M;
} else if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN4M)) {
*sector_size = 4096;
*align_mb = 4;
*align_size = 4 * ONE_MB;
*ss_size_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN4M;
*rs_size_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN4M;
*ss_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN4M;
*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN4M;
} else if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN2M)) {
*sector_size = 4096;
*align_mb = 2;
*align_size = 2 * ONE_MB;
*ss_size_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN2M;
*rs_size_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN2M;
*ss_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN2M;
*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN2M;
} else if ((ss.flags & SANLK_LSF_SECTOR4K) && (ss.flags & SANLK_LSF_ALIGN1M)) {
*sector_size = 4096;
*align_mb = 1;
*align_size = ONE_MB;
*ss_size_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN1M;
*rs_size_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN1M;
*ss_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN1M;
*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN1M;
} else if ((ss.flags & SANLK_LSF_SECTOR512) && (ss.flags & SANLK_LSF_ALIGN1M)) {
*sector_size = 512;
*align_mb = 1;
*align_size = ONE_MB;
*ss_size_flags = SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M;
*rs_size_flags = SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M;
*ss_flags = SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M;
*rs_flags = SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M;
}
if (ss.flags & SANLK_LSF_NO_TIMEOUT)
*no_timeout = 1;
log_debug("read_lockspace_info %s %u found sector_size %d align_size %d no_timeout %d",
path, host_id, *sector_size, *align_size, *no_timeout);
log_debug("read_lockspace_info %s %u found sector_size %d align_size %d",
path, host_id, *sector_size, *align_size);
return 0;
}
@@ -702,52 +670,43 @@ static int read_lockspace_info(char *path, uint32_t host_id, int *sector_size, i
#define MAX_VERSION 16
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb, char *other_args)
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb)
{
struct sanlk_lockspace ss;
struct sanlk_resourced rd;
struct sanlk_disk disk;
char lock_lv_name[MAX_ARGS+1];
char lock_args_version[MAX_VERSION+1];
const char *gl_name = NULL;
uint32_t lock_args_flags = 0;
uint32_t rs_flags;
uint32_t daemon_version;
uint32_t daemon_proto;
uint64_t offset;
uint64_t dev_size;
int no_timeout;
int persist;
int sector_size = 0;
int align_size = 0;
int align_mb = 0;
int i, rv;
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));
memset(lock_args_version, 0, sizeof(lock_args_version));
if (!vg_args || !vg_args[0] || !strcmp(vg_args, "none")) {
log_error("S %s init_vg_san vg_args missing", ls_name);
return -EARGS;
}
snprintf(lock_args_version, MAX_VERSION, "%u.%u.%u",
VG_LOCK_ARGS_MAJOR, VG_LOCK_ARGS_MINOR, VG_LOCK_ARGS_PATCH);
/* see comment above about input vg_args being only lock_lv_name */
dm_strncpy(lock_lv_name, vg_args, sizeof(lock_lv_name));
if (strlen(lock_lv_name) + strlen(lock_args_version) + 2 > MAX_ARGS)
return -EARGS;
if ((rv = build_dm_path(disk.path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
return rv;
@@ -756,7 +715,7 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
if (daemon_test) {
if (!gl_lsname_sanlock[0])
strncpy(gl_lsname_sanlock, ls_name, MAX_NAME);
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", VG_LOCK_ARGS_V1, lock_lv_name);
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
if (rv >= MAX_ARGS)
log_debug("init_vg_san vg_args may be too long %d %s", rv, vg_args);
return 0;
@@ -828,9 +787,6 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
return -EARGS;
}
if (no_timeout)
ss.flags |= SANLK_LSF_NO_TIMEOUT;
rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
if (rv < 0) {
log_error("S %s init_vg_san write_lockspace error %d %s",
@@ -885,6 +841,15 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
return rv;
}
if (!strcmp(gl_name, R_NAME_GL))
dm_strncpy(gl_lsname_sanlock, ls_name, sizeof(gl_lsname_sanlock));
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", lock_args_version, lock_lv_name);
if (rv >= MAX_ARGS)
log_debug("init_vg_san vg_args may be too long %d %s", rv, vg_args);
log_debug("S %s init_vg_san done vg_args %s", ls_name, vg_args);
/*
* Go through all lv resource slots and initialize them with the
* correct lockspace name but a special resource name that indicates
@@ -923,25 +888,6 @@ int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_ar
offset += align_size;
}
if (no_timeout && persist)
rv = snprintf(vg_args, MAX_ARGS, "%s:%s:notimeout:persist", VG_LOCK_ARGS_V2, lock_lv_name);
else if (no_timeout)
rv = snprintf(vg_args, MAX_ARGS, "%s:%s:notimeout", VG_LOCK_ARGS_V2, lock_lv_name);
else if (persist)
rv = snprintf(vg_args, MAX_ARGS, "%s:%s:persist", VG_LOCK_ARGS_V2, lock_lv_name);
else
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", VG_LOCK_ARGS_V1, lock_lv_name);
if (rv >= MAX_ARGS) {
log_error("S %s init_vg_san vg_args string too long %d %s", ls_name, rv, vg_args);
return -EINVAL;
}
if (!strcmp(gl_name, R_NAME_GL))
dm_strncpy(gl_lsname_sanlock, ls_name, sizeof(gl_lsname_sanlock));
log_debug("S %s init_vg_san done vg_args %s", ls_name, vg_args);
return 0;
}
@@ -959,12 +905,12 @@ int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char
struct lm_sanlock *lms;
struct sanlk_resourced rd;
char lock_lv_name[MAX_ARGS+1];
char lock_args_version[MAX_VERSION+1];
uint64_t offset;
uint64_t prev_offset = 0;
int sector_size = 0;
int align_size = 0;
int align_mb;
int no_timeout = 0;
uint32_t ss_flags;
uint32_t rs_flags = 0;
uint32_t tries = 1;
@@ -972,20 +918,24 @@ int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char
memset(&rd, 0, sizeof(rd));
memset(lock_lv_name, 0, sizeof(lock_lv_name));
memset(lock_args_version, 0, sizeof(lock_args_version));
memset(disk_path, 0, sizeof(disk_path));
snprintf(lock_args_version, MAX_VERSION, "%u.%u.%u",
LV_LOCK_ARGS_MAJOR, LV_LOCK_ARGS_MINOR, LV_LOCK_ARGS_PATCH);
if (daemon_test) {
align_size = 1024 * 1024;
snprintf(lv_args, MAX_ARGS, "%s:%llu",
LV_LOCK_ARGS_V1,
lock_args_version,
(unsigned long long)((align_size * LV_LOCK_BEGIN) + (align_size * daemon_test_lv_count)));
daemon_test_lv_count++;
return 0;
}
rv = lockd_lockargs_get_locklv(vg_args, lock_lv_name);
rv = lock_lv_name_from_args(vg_args, lock_lv_name);
if (rv < 0) {
log_error("S %s init_lv_san lockd_lockargs_get_locklv error %d %s",
log_error("S %s init_lv_san lock_lv_name_from_args error %d %s",
ls_name, rv, vg_args);
return rv;
}
@@ -1007,7 +957,7 @@ int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char
/* using host_id 1 to get sizes since we don't need host-specific info */
rv = read_lockspace_info(disk_path, 1, &sector_size, &align_size, &align_mb, &ss_flags, &rs_flags, &no_timeout, NULL);
rv = read_lockspace_info(disk_path, 1, &sector_size, &align_size, &align_mb, &ss_flags, &rs_flags, NULL);
if (rv < 0) {
log_error("S %s init_lv_san read_lockspace_info error %d %s",
ls_name, rv, disk_path);
@@ -1075,7 +1025,7 @@ int lm_init_lv_sanlock(struct lockspace *ls, char *ls_name, char *vg_name, char
rv = sanlock_write_resource(&rd.rs, 0, 0, 0);
if (!rv) {
snprintf(lv_args, MAX_ARGS, "%s:%llu",
LV_LOCK_ARGS_V1, (unsigned long long)offset);
lock_args_version, (unsigned long long)offset);
} else {
log_error("S %s init_lv_san write error %d offset %llu",
ls_name, rv, (unsigned long long)rv);
@@ -1115,9 +1065,9 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
return -EINVAL;
}
rv = lockd_lockargs_get_locklv(vg_args, lock_lv_name);
rv = lock_lv_name_from_args(vg_args, lock_lv_name);
if (rv < 0) {
log_error("S %s init_lv_san lockd_lockargs_get_locklv error %d %s",
log_error("S %s init_lv_san lock_lv_name_from_args error %d %s",
ls_name, rv, vg_args);
return rv;
}
@@ -1637,7 +1587,6 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation
int sector_size = 0;
int align_size = 0;
int align_mb = 0;
int no_timeout = 0;
int retries = 0;
int gl_found;
int ret, rv;
@@ -1663,9 +1612,9 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation
goto fail;
}
rv = lockd_lockargs_get_locklv(ls->vg_args, lock_lv_name);
rv = lock_lv_name_from_args(ls->vg_args, lock_lv_name);
if (rv < 0) {
log_error("S %s prepare_lockspace_san lockd_lockargs_get_locklv error %d %s",
log_error("S %s prepare_lockspace_san lock_lv_name_from_args error %d %s",
ls->name, rv, ls->vg_args);
ret = -EARGS;
goto fail;
@@ -1762,16 +1711,15 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation
#endif
sector_size = 0;
align_size = 0;
no_timeout = 0;
rv = read_lockspace_info(disk_path, lms->ss.host_id, &sector_size, &align_size, &align_mb, &ss_flags, &rs_flags, &no_timeout, &hs);
rv = read_lockspace_info(disk_path, lms->ss.host_id, &sector_size, &align_size, &align_mb, &ss_flags, &rs_flags, &hs);
#if LOCKDSANLOCK_SUPPORT >= 410
if ((rv == -ELOCKREPAIR) && repair && !retries) {
uint64_t generation = 0;
uint32_t host_id = 0;
rv = read_info_file(ls->vg_name, &host_id, &generation, &sector_size, &align_size, &no_timeout);
rv = read_info_file(ls, &host_id, &generation, &sector_size, &align_size);
if (rv < 0) {
log_error("S %s prepare_lockspace_san cannot repair lockspace no info file", lsname);
ret = -EINVAL;
@@ -1802,9 +1750,6 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation
ret = -EINVAL;
}
if (no_timeout)
lms->ss.flags |= SANLK_LSF_NO_TIMEOUT;
log_debug("S %s prepare_lockspace_san repair host %u lease", lsname, host_id);
rv = sanlock_init_lockspace_host(&lms->ss, NULL, generation, 0, 0, 0);
@@ -1954,7 +1899,7 @@ int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok,
free(hs);
write_info_file(ls->vg_name, ls->host_id, ls->generation, lms->sector_size, lms->align_size, ls->no_timeout);
write_info_file(ls);
/*
* Don't let the lockspace be cleanly released if orphan locks
@@ -2258,7 +2203,6 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
rv == SANLK_ACQUIRE_OWNED ||
rv == SANLK_ACQUIRE_OTHER ||
rv == SANLK_ACQUIRE_OWNED_RETRY ||
rv == SANLK_ACQUIRE_OWNED_NO_TIMEOUT ||
rv == -EAGAIN) {
/*
@@ -2287,9 +2231,6 @@ int lm_lock_sanlock(struct lockspace *ls, struct resource *r, int ld_mode,
if (rv == SANLK_ACQUIRE_OWNED_RETRY)
*retry = 0;
if (rv == SANLK_ACQUIRE_OWNED_NO_TIMEOUT)
*retry = 0;
if (owner && owner_host.host_id) {
const char *host_state;
@@ -2480,7 +2421,6 @@ int lm_convert_sanlock(struct lockspace *ls, struct resource *r,
case SANLK_ACQUIRE_IDLIVE:
case SANLK_ACQUIRE_OWNED:
case SANLK_ACQUIRE_OWNED_RETRY:
case SANLK_ACQUIRE_OWNED_NO_TIMEOUT:
case SANLK_ACQUIRE_OTHER:
case SANLK_AIO_TIMEOUT:
/* expected errors from known/normal cases like lock contention or io timeouts */
@@ -2789,181 +2729,3 @@ 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;
struct sanlk_host host = { 0 };
int rv;
log_debug("S %s set_host_dead_sanlock host_id %u gen %u", ls->name, owner->host_id, owner->generation);
host.host_id = owner->host_id;
host.generation = owner->generation;
rv = sanlock_set_host(&lms->ss, SANLK_SET_HOST_DEAD_EXT, 0, 0, &host);
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);
}
int lm_setlockargs_supported_sanlock(struct lockspace *ls, struct action *act)
{
uint32_t daemon_version;
uint32_t daemon_proto;
uint32_t lock_args_flags = 0;
uint32_t ver_major, ver_minor;
int rv;
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;
}
if (!(lock_args_flags & LOCKARGS_NOTIMEOUT) && !(lock_args_flags & LOCKARGS_PERSIST))
return 1;
rv = sanlock_version(0, &daemon_version, &daemon_proto);
if (rv < 0) {
log_error("S %s setlockargs failed to connect to sanlock daemon", ls->name);
return 0;
}
log_debug("S %s setlockargs sanlock version 0x%x lock_args_flags 0x%x", ls->name, daemon_version, lock_args_flags);
ver_major = (daemon_version & 0xFF000000) >> 24;
ver_minor = (daemon_version & 0x00FF0000) >> 16;
/* sanlock 4.2.0 added support for LOCKARGS_NOTIMEOUT or LOCKARGS_PERSIST. */
if (ver_major < 4)
return 0;
if ((ver_major == 4) && (ver_minor < 2))
return 0;
return 1;
}
int lm_setlockargs_vg_sanlock(char *ls_name, char *vg_name, struct action *act)
{
struct sanlk_lockspace ss = {0};
char lock_lv_name[MAX_ARGS+1] = {0};
char disk_path[SANLK_PATH_LEN] = {0};
uint32_t ss_size_flags = 0;
uint32_t rs_size_flags = 0;
uint32_t lock_args_flags = 0;
int sector_size = 0;
int align_size = 0;
int align_mb = 0;
int no_timeout;
int persist;
int rv;
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;
}
rv = lockd_lockargs_get_locklv(act->vg_args, lock_lv_name);
if (rv < 0) {
log_error("S %s setlockargs lockd_lockargs_get_locklv error %d %s",
ls_name, rv, act->vg_args);
return rv;
}
if ((rv = build_dm_path(disk_path, SANLK_PATH_LEN, vg_name, lock_lv_name)))
return rv;
/* get the sector and align flags from host_id 1 in the current lockspace */
rv = read_lockspace_info(disk_path, 1, &sector_size, &align_size, &align_mb, &ss_size_flags, &rs_size_flags, &no_timeout, NULL);
if (rv < 0) {
log_error("S %s setlockargs read_lockspace_info error %d %s", ls_name, rv, disk_path);
return rv;
}
/* initialize lockspace */
no_timeout = (lock_args_flags & LOCKARGS_NOTIMEOUT) ? 1 :0;
persist = (lock_args_flags & LOCKARGS_PERSIST) ? 1 : 0;
strcpy_name_len(ss.name, ls_name, SANLK_NAME_LEN);
memcpy(ss.host_id_disk.path, disk_path, SANLK_PATH_LEN);
ss.host_id_disk.offset = 0;
ss.flags = ss_size_flags;
if (no_timeout)
ss.flags |= SANLK_LSF_NO_TIMEOUT;
log_debug("S %s setlockargs write_lockspace no_timeout %d flags 0x%x", ls_name, no_timeout, ss.flags);
rv = sanlock_write_lockspace(&ss, 0, 0, sanlock_io_timeout);
if (rv < 0) {
log_error("S %s setlockargs write_lockspace error %d %s", ls_name, rv, ss.host_id_disk.path);
return rv;
}
update_info_file(vg_name, no_timeout);
if (no_timeout && persist)
rv = snprintf(act->vg_args, MAX_ARGS, "%s:%s:notimeout:persist", VG_LOCK_ARGS_V2, lock_lv_name);
else if (no_timeout)
rv = snprintf(act->vg_args, MAX_ARGS, "%s:%s:notimeout", VG_LOCK_ARGS_V2, lock_lv_name);
else if (persist)
rv = snprintf(act->vg_args, MAX_ARGS, "%s:%s:persist", VG_LOCK_ARGS_V2, lock_lv_name);
else
rv = snprintf(act->vg_args, MAX_ARGS, "%s:%s", VG_LOCK_ARGS_V1, lock_lv_name);
log_debug("S %s setlockargs new args %s", ls_name, act->vg_args);
if (rv >= MAX_ARGS) {
log_error("S %s setlockargs vg_args string too long %d %s", ls_name, rv, act->vg_args);
return -EINVAL;
}
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,7 +72,6 @@ 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).
@@ -81,34 +80,27 @@ 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 LVs using [lvs(8)](https://man7.org/linux/man-pages/man8/lvs.8.html) or
List PVs 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 [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).
See [vgcreate(8)](https://man7.org/linux/man-pages/man8/vgcreate.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 hexadecimal.\n"
"The local persistent reservation key in hexidecimal.\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

@@ -30,7 +30,6 @@
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include <scsi/sg.h>
@@ -175,70 +174,29 @@ static int parse_prkey(const char *ptr, uint64_t *prkey)
return 1;
}
/*
* If there was previously a different VG with the same name (and unknown vgid),
* remove the key file that it used.
*/
void persist_key_file_remove_name(struct cmd_context *cmd, const char *vg_name)
{
DIR *dir;
struct dirent *de;
char path[PATH_MAX] = { 0 };
char name[PATH_MAX] = { 0 };
int namelen;
if (dm_snprintf(name, sizeof(name), "persist_key_%s", vg_name) < 0)
return;
namelen = strlen(name);
if (!(dir = opendir("/var/lib/lvm")))
return;
while ((de = readdir(dir))) {
if (de->d_name[0] == '.')
continue;
if (!strncmp(de->d_name, name, namelen)) {
if (dm_snprintf(path, sizeof(path), "/var/lib/lvm/%s", de->d_name) < 0)
continue;
if (unlink(path))
log_sys_debug("unlink", path);
}
}
(void) closedir(dir);
}
static void create_persist_key_path(struct volume_group *vg, const char *vg_name, char *path)
{
char vgid[ID_LEN + 1] __attribute__((aligned(8)));
vgid[ID_LEN] = 0;
memcpy(vgid, &vg->id.uuid, ID_LEN);
(void) dm_snprintf(path, PATH_MAX, "/var/lib/lvm/persist_key_%s_%s", vg_name, vgid);
}
void persist_key_file_remove(struct cmd_context *cmd, struct volume_group *vg)
void persist_key_file_remove(struct cmd_context *cmd, const char *vg_name)
{
char path[PATH_MAX] = { 0 };
create_persist_key_path(vg, vg->name, path);
if (dm_snprintf(path, PATH_MAX-1, "/var/lib/lvm/persist_key_%s", vg_name) < 0)
return;
if (unlink(path))
log_sys_debug("unlink", path);
}
void persist_key_file_rename(struct volume_group *vg, const char *old_name, const char *new_name)
void persist_key_file_rename(const char *old_name, const char *new_name)
{
char old_path[PATH_MAX] = { 0 };
char new_path[PATH_MAX] = { 0 };
struct stat info;
create_persist_key_path(vg, old_name, old_path);
create_persist_key_path(vg, new_name, new_path);
if (dm_snprintf(old_path, PATH_MAX-1, "/var/lib/lvm/persist_key_%s", old_name) < 0)
return;
if (stat(old_path, &info))
return;
if (dm_snprintf(new_path, PATH_MAX-1, "/var/lib/lvm/persist_key_%s", new_name) < 0)
return;
if (rename(old_path, new_path) < 0)
log_warn("WARNING: Failed to rename %s", old_path);
}
@@ -248,7 +206,8 @@ static int key_file_exists(struct cmd_context *cmd, struct volume_group *vg)
char path[PATH_MAX] = { 0 };
struct stat info;
create_persist_key_path(vg, vg->name, path);
if (dm_snprintf(path, PATH_MAX-1, "/var/lib/lvm/persist_key_%s", vg->name) < 0)
return 0;
if (!stat(path, &info))
return 1;
@@ -269,7 +228,8 @@ static int read_key_file(struct cmd_context *cmd, struct volume_group *vg,
uint32_t found_gen = 0;
FILE *fp;
create_persist_key_path(vg, vg->name, path);
if (dm_snprintf(path, PATH_MAX-1, "/var/lib/lvm/persist_key_%s", vg->name) < 0)
return 0;
if (!(fp = fopen(path, "r"))) {
log_debug("key_file: cannot open %s", path);
@@ -330,12 +290,13 @@ static int read_key_file(struct cmd_context *cmd, struct volume_group *vg,
return 1;
}
static int write_key_file(struct cmd_context *cmd, struct volume_group *vg, uint64_t key)
static int write_key_file(struct cmd_context *cmd, const char *vg_name, uint64_t key)
{
char path[PATH_MAX] = { 0 };
FILE *fp;
create_persist_key_path(vg, vg->name, path);
if (dm_snprintf(path, PATH_MAX-1, "/var/lib/lvm/persist_key_%s", vg_name) < 0)
return 0;
if (!(fp = fopen(path, "w"))) {
log_debug("Failed to create key file");
@@ -813,7 +774,7 @@ int vg_is_registered(struct cmd_context *cmd, struct volume_group *vg, uint64_t
}
}
int persist_is_started(struct cmd_context *cmd, struct volume_group *vg, int may_fail, uint64_t *our_key_ret)
int persist_is_started(struct cmd_context *cmd, struct volume_group *vg, int may_fail)
{
struct pv_list *pvl;
struct device *dev;
@@ -826,9 +787,6 @@ int persist_is_started(struct cmd_context *cmd, struct volume_group *vg, int may
if (!vg_is_registered(cmd, vg, &our_key_val, &partial))
goto out;
if (our_key_ret)
*our_key_ret = our_key_val;
if (partial) {
log_debug("PR is started: partial");
goto out;
@@ -898,7 +856,7 @@ static int get_our_key(struct cmd_context *cmd, struct volume_group *vg,
if (last_host_id != local_host_id) {
log_debug("last key from file: wrong host_id %d vs local %d", last_host_id, local_host_id);
persist_key_file_remove(cmd, vg);
persist_key_file_remove(cmd, vg->name);
goto read_keys;
}
@@ -1005,7 +963,7 @@ static int get_our_key_sanlock_start(struct cmd_context *cmd, struct volume_grou
if (last_host_id != local_host_id) {
log_debug("last key from file: wrong host_id %d vs local %d", last_host_id, local_host_id);
persist_key_file_remove(cmd, vg);
persist_key_file_remove(cmd, vg->name);
goto read_keys;
}
@@ -1056,7 +1014,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 actually returns the previous generation
* the PR key. The sanlock lockstart atually 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 +1054,7 @@ int persist_key_update(struct cmd_context *cmd, struct volume_group *vg, uint32_
/*
* When using an explicit pr_key setting, there's
* no sanlock generation number that needs updating.
* not sanlock generation number that needs updating.
*/
if (local_key)
return 1;
@@ -1522,7 +1480,7 @@ int persist_check(struct cmd_context *cmd, struct volume_group *vg,
if (!read_key_file(cmd, vg, NULL, &file_key, NULL, NULL) || (file_key != our_key_val)) {
log_print_unless_silent("updating incorrect key file value 0x%llx to 0x%llx",
(unsigned long long)file_key, (unsigned long long)our_key_val);
if (!write_key_file(cmd, vg, our_key_val))
if (!write_key_file(cmd, vg->name, our_key_val))
log_warn("WARNING: Failed to update key file.");
}
@@ -1570,78 +1528,23 @@ static int _run_stop(struct cmd_context *cmd, struct volume_group *vg, struct dm
}
/*
* For vgremove, separate persist_stop into before and after parts:
* - before cannot happen after normal vgremove, because the list
* 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
* of PVs is no longer available.
* - after cannot happen before normal vgremove, because removing the
* - run 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_vgremove_before(struct cmd_context *cmd, struct volume_group *vg, struct dm_list *devs, char **key)
int persist_stop_prepare(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)
@@ -1655,15 +1558,34 @@ int persist_stop(struct cmd_context *cmd, struct volume_group *vg)
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 (!_run_stop(cmd, vg, &devs, our_key_buf, 0))
if (!(*key = dm_pool_strdup(cmd->mem, our_key_buf)))
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)
{
@@ -1797,117 +1719,6 @@ static int _persist_extend_shared(struct cmd_context *cmd, struct volume_group *
return error ? 0 : 1;
}
int persist_upgrade_stop(struct cmd_context *cmd, struct volume_group *vg, uint64_t our_key_val)
{
DM_LIST_INIT(devs);
char our_key_buf[PR_KEY_BUF_SIZE] = { 0 };
if (!pv_list_to_dev_list(cmd->mem, &vg->pvs, &devs))
return_0;
if (dm_snprintf(our_key_buf, PR_KEY_BUF_SIZE-1, "0x%llx", (unsigned long long)our_key_val) < 0)
return_0;
if (!_run_stop(cmd, vg, &devs, our_key_buf, 0))
return_0;
return 1;
}
/*
* Host currently holds a normal sh access PR on shared VG,
* and wants to switch to an ex access PR on that VG
* (to prevent other hosts from using it while it's making
* changes.)
*/
int persist_upgrade_ex(struct cmd_context *cmd, struct volume_group *vg, uint64_t *our_key_held)
{
DM_LIST_INIT(devs);
struct device_list *devl;
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 };
char new_key_buf[PR_KEY_BUF_SIZE] = { 0 };
uint64_t our_key_val = 0;
uint64_t new_key_val = 0;
const char *devname;
const char **argv;
int pv_count;
int args;
int status;
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;
if (!pv_list_to_dev_list(cmd->mem, &vg->pvs, &devs))
return_0;
log_debug("persist_upgrade_ex stop PR %s", our_key_buf);
if (!_run_stop(cmd, vg, &devs, our_key_buf, 0))
return_0;
if (local_key) {
new_key_val = our_key_val;
memcpy(new_key_buf, our_key_buf, PR_KEY_BUF_SIZE);
} else if (local_host_id) {
if (dm_snprintf(new_key_buf, PR_KEY_BUF_SIZE-1, "0x100000000000%04x", local_host_id) != 18) {
log_error("Failed to format key string for host_id %d", local_host_id);
return 0;
}
if (!parse_prkey(new_key_buf, &new_key_val)) {
log_error("Failed to parse generated key %s", new_key_buf);
return 0;
}
}
pv_count = dm_list_size(&devs);
log_debug("persist_upgrade_ex start PR on %d devs with local key %llx", pv_count, (unsigned long long)new_key_val);
args = 9 + pv_count*2;
if (vg->pr & VG_PR_PTPL)
args += 1;
if (!(argv = dm_pool_alloc(cmd->mem, args * sizeof(char *))))
return_0;
args = 0;
argv[0] = LVMPERSIST_PATH;
argv[++args] = "start";
argv[++args] = "--ourkey";
argv[++args] = new_key_buf;
argv[++args] = "--access";
argv[++args] = "ex";
argv[++args] = "--vg";
argv[++args] = vg->name;
if (vg->pr & VG_PR_PTPL)
argv[++args] = "--ptpl";
dm_list_iterate_items(devl, &devs) {
if (!(devname = dm_pool_strdup(cmd->mem, dev_name(devl->dev))))
return_0;
argv[++args] = "--device";
argv[++args] = devname;
}
argv[++args] = NULL;
if (!exec_cmd(cmd, argv, &status, 1)) {
log_error("persistent reservation exclusive start failed: lvmpersist command error.");
log_error("(Use vgchange --persist stop to stop PR on other hosts.");
return 0;
}
*our_key_held = new_key_val;
return 1;
}
/*
* Start PR on devices that are being used for vgcreate.
* This is somewhat awkward because it happens early in
@@ -1931,7 +1742,7 @@ int persist_vgcreate_begin(struct cmd_context *cmd, char *vg_name, char *local_k
int args;
int status;
persist_key_file_remove_name(cmd, vg_name);
persist_key_file_remove(cmd, vg_name);
if (local_key) {
if (!parse_prkey(local_key, &our_key_val)) {
@@ -1999,8 +1810,7 @@ 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,
uint64_t *our_key_ret)
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags)
{
DM_LIST_INIT(devs);
struct device_list *devl;
@@ -2067,7 +1877,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 with key %s", our_key_buf_stop);
log_warn("WARNING: failed to stop PR");
log_debug("start PR on %d devs with local key %llx", pv_count, (unsigned long long)our_key_val);
@@ -2105,12 +1915,9 @@ int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, ui
}
/* key file is an optimization, not an error condition */
if (!write_key_file(cmd, vg, our_key_val))
if (!write_key_file(cmd, vg->name, our_key_val))
stack;
if (our_key_ret)
*our_key_ret = our_key_val;
return 1;
}
@@ -2495,7 +2302,7 @@ int persist_start(struct cmd_context *cmd, struct volume_group *vg,
}
/* key file is an optimization, not an error condition */
if (!write_key_file(cmd, vg, our_key_val))
if (!write_key_file(cmd, vg->name, our_key_val))
stack;
return 1;

View File

@@ -48,9 +48,8 @@ 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_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_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_remove(struct cmd_context *cmd, struct volume_group *vg,
char *local_key, int local_host_id, const char *remkey);
@@ -62,19 +61,14 @@ 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,
uint64_t *our_key_ret);
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags);
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);
int persist_is_started(struct cmd_context *cmd, struct volume_group *vg, int may_fail, uint64_t *our_key);
int persist_is_started(struct cmd_context *cmd, struct volume_group *vg, int may_fail);
int persist_key_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t prev_gen);
void persist_key_file_remove_name(struct cmd_context *cmd, const char *vg_name);
void persist_key_file_remove(struct cmd_context *cmd, struct volume_group *vg);
void persist_key_file_rename(struct volume_group *vg, const char *old_name, const char *new_name);
void persist_key_file_remove(struct cmd_context *cmd, const char *vg_name);
void persist_key_file_rename(const char *old_name, const char *new_name);
int dev_read_reservation_nvme(struct cmd_context *cmd, struct device *dev, uint64_t *holder_ret, int *prtype_ret);

View File

@@ -117,62 +117,6 @@ void lvmlockd_disconnect(void)
_lvmlockd_connected = 0;
}
#define MAX_LOCKARGS 8
/* parse lock_args string for values that may appear in command line --setlockargs */
int lockd_lockargs_get_user_flags(const char *str, uint32_t *flags)
{
char buf[PATH_MAX];
char *argv[MAX_LOCKARGS];
int argc;
int i;
if (!str)
return 0;
dm_strncpy(buf, str, sizeof(buf));
split_line(buf, &argc, argv, MAX_LOCKARGS, ',');
for (i = 0; i < argc; i++) {
if (!strcmp(argv[i], "persist"))
*flags |= LOCKARGS_PERSIST;
else if (!strcmp(argv[i], "nopersist"))
*flags |= LOCKARGS_NOPERSIST;
else if (!strcmp(argv[i], "timeout"))
*flags |= LOCKARGS_TIMEOUT;
else if (!strcmp(argv[i], "notimeout"))
*flags |= LOCKARGS_NOTIMEOUT;
else {
log_error("Unknown lockargs option value: %s", argv[i]);
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;
}
/* Translate the result strings from lvmlockd to bit flags. */
static void _flags_str_to_lockd_flags(const char *flags_str, uint32_t *lockd_flags)
{
@@ -225,7 +169,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, uint64_t *our_generation)
int *result, uint32_t *lockd_flags, struct owner *owner)
{
int reply_result;
const char *str;
@@ -262,9 +206,6 @@ 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;
}
@@ -479,8 +420,7 @@ static int _lockd_request(struct cmd_context *cmd,
const struct lvmlockd_pvs *lock_pvs,
int *result,
uint32_t *lockd_flags,
struct owner *owner,
uint64_t *our_generation)
struct owner *owner)
{
const char *cmd_name = get_cmd_name();
daemon_reply reply;
@@ -517,7 +457,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, our_generation))
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner))
goto fail;
/*
@@ -537,7 +477,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, our_generation))
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner))
goto fail;
/*
@@ -555,7 +495,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, our_generation))
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner))
goto fail;
log_debug("lockd %s %s result %d %x",
@@ -826,7 +766,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, NULL)) {
if (!_lockd_result(cmd, "find_free_lock", reply, &result, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -881,7 +821,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, NULL)) {
if (!_lockd_result(cmd, "init_vg", reply, &result, NULL, NULL)) {
ret = 0;
result = -ELOCKD;
} else {
@@ -952,7 +892,7 @@ static int _init_vg_idm(struct cmd_context *cmd, struct volume_group *vg)
return _init_vg(cmd, vg, "idm");
}
static int _init_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg, int lv_lock_count, const char *set_args)
static int _init_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg, int lv_lock_count)
{
daemon_reply reply;
const char *reply_str;
@@ -968,9 +908,9 @@ static int _init_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg, in
int ret;
if (!_use_lvmlockd)
return_0;
return 0;
if (!_lvmlockd_connected)
return_0;
return 0;
/*
* We need the sector size to know what size to create the LV,
@@ -1074,12 +1014,11 @@ static int _init_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg, in
"vg_name = %s", vg->name,
"vg_lock_type = %s", "sanlock",
"vg_lock_args = %s", vg->sanlock_lv->name,
"set_lock_args = %s", set_args ?: "none",
"align_mb = " FMTd64, (int64_t) align_size,
"opts = %s", opts ?: "none",
NULL);
if (!_lockd_result(cmd, "init_vg", reply, &result, NULL, NULL, NULL)) {
if (!_lockd_result(cmd, "init_vg", reply, &result, NULL, NULL)) {
ret = 0;
result = -ELOCKD;
} else {
@@ -1181,7 +1120,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, NULL)) {
if (!_lockd_result(cmd, "free_vg", reply, &result, &lockd_flags, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1242,7 +1181,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, NULL)) {
if (!_lockd_result(cmd, "busy_vg", reply, &result, &lockd_flags, NULL)) {
ret = 1;
goto out;
}
@@ -1305,7 +1244,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, NULL)) {
if (!_lockd_result(cmd, "free_vg", reply, &result, &lockd_flags, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1362,7 +1301,7 @@ static int _free_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg)
/* vgcreate */
int lockd_init_vg(struct cmd_context *cmd, struct volume_group *vg,
const char *lock_type, int lv_lock_count, const char *set_args)
const char *lock_type, int lv_lock_count)
{
switch (get_lock_type_from_string(lock_type)) {
case LOCK_TYPE_NONE:
@@ -1372,7 +1311,7 @@ int lockd_init_vg(struct cmd_context *cmd, struct volume_group *vg,
case LOCK_TYPE_DLM:
return _init_vg_dlm(cmd, vg);
case LOCK_TYPE_SANLOCK:
return _init_vg_sanlock(cmd, vg, lv_lock_count, set_args);
return _init_vg_sanlock(cmd, vg, lv_lock_count);
case LOCK_TYPE_IDM:
return _init_vg_idm(cmd, vg);
default:
@@ -1471,7 +1410,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);
persist_key_file_remove(cmd, vg->name);
break;
case LOCK_TYPE_DLM:
_free_vg_dlm(cmd, vg);
@@ -1498,7 +1437,7 @@ void lockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg)
* lock the vg, read/use/write the vg, unlock the vg.
*/
int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, uint64_t our_key, int *exists)
int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists)
{
char uuid[64] __attribute__((aligned(8)));
const char *opts = NULL;
@@ -1576,7 +1515,6 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, uint64_t ou
"vg_uuid = %s", uuid[0] ? uuid : "none",
"version = " FMTd64, (int64_t) vg->seqno,
"host_id = " FMTd64, (int64_t) host_id,
"our_key = " FMTd64, (int64_t) our_key,
"opts = %s", opts ?: "none",
NULL);
_lockd_free_pv_list(&lock_pvs);
@@ -1590,12 +1528,11 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, uint64_t ou
"vg_uuid = %s", uuid[0] ? uuid : "none",
"version = " FMTd64, (int64_t) vg->seqno,
"host_id = " FMTd64, (int64_t) host_id,
"our_key = " FMTd64, (int64_t) our_key,
"opts = %s", opts ?: "none",
NULL);
}
if (!_lockd_result(cmd, "start_vg", reply, &result, &lockd_flags, NULL, NULL)) {
if (!_lockd_result(cmd, "start_vg", reply, &result, &lockd_flags, NULL)) {
ret = 0;
result = -ELOCKD;
} else {
@@ -1685,7 +1622,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, NULL)) {
if (!_lockd_result(cmd, "stop_vg", reply, &result, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1731,7 +1668,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, NULL)) {
if (!_lockd_result(cmd, "start_wait", reply, &result, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1850,7 +1787,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)) {
NULL, &result, &lockd_flags, &owner)) {
/* No result from lvmlockd, it is probably not running. */
log_error("Global lock failed: check that lvmlockd is running.");
return 0;
@@ -2114,7 +2051,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)) {
NULL, &result, &lockd_flags, &owner)) {
/* No result from lvmlockd, it is probably not running. */
/* We don't care if an unlock fails. */
@@ -2351,7 +2288,6 @@ 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;
@@ -2466,7 +2402,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, &our_generation)) {
NULL, &result, &lockd_flags, &owner)) {
/*
* No result from lvmlockd, it is probably not running.
* Decide if it is ok to continue without a lock in
@@ -2679,7 +2615,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;
}
@@ -2724,7 +2660,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, NULL)) {
if (!_lockd_result(vg->cmd, "vg_update", reply, &result, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -2738,7 +2674,6 @@ 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;
@@ -2756,7 +2691,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, &our_generation)) {
if (!_lockd_result(vg->cmd, "vg_status", reply, &result, NULL, &owner)) {
log_debug("lockd_vg_status %s no result", vg->name);
goto out;
}
@@ -2766,16 +2701,6 @@ 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);
@@ -2809,7 +2734,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, NULL)) {
if (!_lockd_result(cmd, "query_lock_lv", reply, &result, 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;
@@ -2882,7 +2807,6 @@ 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;
@@ -2981,7 +2905,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, NULL)) {
&lock_pvs, &result, &lockd_flags, 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);
@@ -2992,7 +2916,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, &our_generation)) {
NULL, &result, &lockd_flags, &owner)) {
/* No result from lvmlockd, it is probably not running. */
log_error("Locking failed for LV %s/%s", vg->name, lv_name);
return 0;
@@ -3922,7 +3846,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, NULL)) {
if (!_lockd_result(cmd, "init_lv", reply, &result, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -3997,7 +3921,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, NULL)) {
if (!_lockd_result(cmd, "free_lv", reply, &result, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -4262,7 +4186,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, NULL)) {
if (!_lockd_result(cmd, "rename_vg_before", reply, &result, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -4307,7 +4231,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
* Depending on the problem that caused the rename to
* fail, it may make sense to not restart the VG here.
*/
if (!lockd_start_vg(cmd, vg, 0, NULL))
if (!lockd_start_vg(cmd, vg, NULL))
log_error("Failed to restart VG %s lockspace.", vg->name);
return 1;
}
@@ -4327,7 +4251,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, NULL)) {
if (!_lockd_result(cmd, "rename_vg_final", reply, &result, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -4347,7 +4271,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
}
}
if (!lockd_start_vg(cmd, vg, 0, NULL))
if (!lockd_start_vg(cmd, vg, NULL))
log_error("Failed to start VG %s lockspace.", vg->name);
return 1;
@@ -4368,7 +4292,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, NULL)) {
if (!_lockd_result(cmd, "running_lm", reply, &result, NULL, NULL)) {
log_error("Failed to get result from lvmlockd");
goto out;
}
@@ -4489,7 +4413,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, NULL)) {
if (!_lockd_result(cmd, "refresh_lv", reply, &result, NULL, NULL)) {
/* No result from lvmlockd, it is probably not running. */
log_error("LV refresh failed for LV %s", path);
return 0;
@@ -4563,171 +4487,3 @@ void lockd_lockopt_get_flags(const char *str, uint32_t *flags)
log_warn("Ignoring unknown lockopt value: %s", argv[i]);
}
}
int lockd_setlockargs(struct cmd_context *cmd, struct volume_group *vg, const char *set_args, uint64_t *our_key_held)
{
daemon_reply reply;
const char *reply_str;
const char *vg_lock_args = NULL;
uint32_t lockd_flags = 0;
uint32_t lock_args_flags = 0;
int result;
int ret;
if (!_use_lvmlockd) {
log_error("lvmlockd is not in use.");
return 0;
}
if (!_lvmlockd_connected) {
log_error("lvmlockd is not connected.");
return 0;
}
if (!vg->lock_type || strcmp(vg->lock_type, "sanlock")) {
log_error("setlockargs is only supported for lock type sanlock.");
return 0;
}
if (!set_args)
return_0;
if (!lockd_lockargs_get_user_flags(set_args, &lock_args_flags))
return_0;
if ((lock_args_flags & LOCKARGS_PERSIST) && !(vg->pr & VG_PR_REQUIRE)) {
log_error("lockargs \"persist\" requires persistent reservation setting \"require\".");
return 0;
}
/*
* Check if other PR keys are registered, which would
* cause the persist_upgrade_ex below to fail.
*/
if (vg->pr & (VG_PR_REQUIRE | VG_PR_AUTOSTART)) {
struct pv_list *pvl;
struct device *dev;
int key_count;
dm_list_iterate_items(pvl, &vg->pvs) {
if (!(dev = pvl->pv->dev))
continue;
if (dm_list_empty(&dev->aliases))
continue;
if (!dev_find_key(cmd, dev, 0, 0, NULL, 0, NULL, 1, &key_count, NULL)) {
/* Shouldn't happen if persist_is_started already passed. */
log_error("No PR key found on %s.", dev_name(dev));
return 0;
}
if (key_count != 1) {
log_error("Found %d PR keys on %s, stop PR and lockspace on other hosts.", key_count, dev_name(dev));
log_error("(See vgchange --lockstop --persist stop.)");
return 0;
}
}
}
/*
* setlockargs_before checks that sanlock version supports
* the new set_lock_args, checks that no LV locks are held,
* checks we are the only host in the lockspace, and stops
* the lockspace.
*/
log_debug("lockd setlockargs_vg_before %s", vg->name);
reply = _lockd_send("setlockargs_vg_before",
"pid = " FMTd64, (int64_t) getpid(),
"vg_name = %s", vg->name,
"vg_lock_type = %s", vg->lock_type,
"vg_lock_args = %s", vg->lock_args,
"set_lock_args = %s", set_args,
NULL);
if (!_lockd_result(cmd, "setlockargs_vg_before", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 0;
goto out;
}
if (result == -EBUSY) {
log_error("Lockspace for \"%s\" not stopped on other hosts", vg->name);
ret = 0;
goto out;
} else if (result < 0) {
log_error("Lockspace setlockargs error %d for \"%s\"", result, vg->name);
ret = 0;
goto out;
}
daemon_reply_destroy(reply);
/*
* When the VG has the ability to use PR, change the
* current PR to an exclusive mode (WE), using a key
* with our host_id and gen 0. The exclusive PR protects
* the VG from other hosts while the locking parameters
* are being changed (since locking can't be used while
* the locking is being changed.) The lockspace is stopped
* while it's being changed. At the end of the vgchange
* setlockargs command, persist_ugprade_stop() releases
* the exclusive PR. After this, any host can do a normal
* start of PR/locking using the new lockargs.
*/
if (vg->pr & (VG_PR_REQUIRE | VG_PR_AUTOSTART)) {
if (!persist_upgrade_ex(cmd, vg, our_key_held)) {
log_error("Failed to upgrade to exclusive PR.");
log_error("Restart PR and locking to retry setlockargs.");
return 0;
}
}
/*
* setlockargs_final reformats sanlock leases on the lvmlock LV.
* The host generation numbers will all be reset back to 0, and
* the PR keys containing the gen will start over from gen 1.
* lvmlockd returns a new lock_args string that this command
* writes in VG metadata.
*/
retry_final:
log_debug("lockd setlockargs_vg_final %s", vg->name);
reply = _lockd_send("setlockargs_vg_final",
"pid = " FMTd64, (int64_t) getpid(),
"vg_name = %s", vg->name,
"vg_lock_type = %s", vg->lock_type,
"vg_lock_args = %s", vg->lock_args,
"set_lock_args = %s", set_args,
NULL);
if (!_lockd_result(cmd, "setlockargs_vg_final", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 0;
goto out;
}
if (result == -EAGAIN) {
daemon_reply_destroy(reply);
sleep(1);
goto retry_final;
}
if (!(reply_str = daemon_reply_str(reply, "vg_lock_args", NULL))) {
log_error("VG %s setlockargs failed: result %d new lock_args not returned", vg->name, result);
ret = 0;
goto out;
}
if (!(vg_lock_args = dm_pool_strdup(cmd->mem, reply_str))) {
ret = 0;
goto out;
}
log_debug("lockd setlockargs_vg %s result %d new lock_args %s", vg->name, result, vg_lock_args);
vg->lock_args = vg_lock_args;
ret = 1;
out:
daemon_reply_destroy(reply);
return ret;
}

View File

@@ -14,7 +14,6 @@
#include "libdaemon/client/config-util.h"
#include "libdaemon/client/daemon-client.h"
#include "lib/metadata/metadata-exported.h" /* is_lockd_type() */
#include "daemons/lvmlockd/lvmlockd-client.h"
#define LOCKD_SANLOCK_LV_NAME "lvmlock"
@@ -67,7 +66,6 @@
#ifdef LVMLOCKD_SUPPORT
void lockd_lockopt_get_flags(const char *str, uint32_t *flags);
int lockd_lockargs_get_user_flags(const char *str, uint32_t *flags);
struct lvresize_params;
struct lvcreate_params;
@@ -84,8 +82,7 @@ void lvmlockd_disconnect(void);
/* vgcreate/vgremove use init/free */
int lockd_init_vg(struct cmd_context *cmd, struct volume_group *vg,
const char *lock_type, int lv_lock_count, const char *set_args);
int lockd_init_vg(struct cmd_context *cmd, struct volume_group *vg, const char *lock_type, int lv_lock_count);
int lockd_free_vg_before(struct cmd_context *cmd, struct volume_group *vg, int changing, int yes);
void lockd_free_vg_final(struct cmd_context *cmd, struct volume_group *vg);
@@ -96,7 +93,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
/* start and stop the lockspace for a vg */
int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, uint64_t our_key, int *exists);
int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists);
int lockd_stop_vg(struct cmd_context *cmd, struct volume_group *vg);
int lockd_start_wait(struct cmd_context *cmd);
int lockd_vg_is_started(struct cmd_context *cmd, struct volume_group *vg, uint32_t *cur_gen);
@@ -145,19 +142,12 @@ void lockd_lvcreate_done(struct cmd_context *cmd, struct volume_group *vg, struc
int lockd_lvremove_lock(struct cmd_context *cmd, struct logical_volume *lv, struct logical_volume **lv_other, int *other_unlock);
void lockd_lvremove_done(struct cmd_context *cmd, struct logical_volume *lv, struct logical_volume *lv_other, int other_unlock);
int lockd_setlockargs(struct cmd_context *cmd, struct volume_group *vg, const char *set_args, uint64_t *our_key_held);
#else /* LVMLOCKD_SUPPORT */
static inline void lockd_lockopt_get_flags(const char *str, uint32_t *flags)
{
}
static inline int lockd_lockargs_get_user_flags(const char *str, uint32_t *flags)
{
return 0;
}
static inline void lvmlockd_set_socket(const char *sock)
{
}
@@ -183,8 +173,7 @@ static inline int lvmlockd_use(void)
return 0;
}
static inline int lockd_init_vg(struct cmd_context *cmd, struct volume_group *vg,
const char *lock_type, int lv_lock_count, const char *set_args)
static inline int lockd_init_vg(struct cmd_context *cmd, struct volume_group *vg, const char *lock_type, int lv_lock_count)
{
return 1;
}
@@ -356,11 +345,6 @@ static inline int lockd_vg_is_busy(struct cmd_context *cmd, struct volume_group
return 0;
}
static inline int lockd_setlockargs(struct cmd_context *cmd, struct volume_group *vg, const char *set_args, uint64_t *our_key_held)
{
return 0;
}
#endif /* LVMLOCKD_SUPPORT */
#endif /* _LVMLOCKD_H */

View File

@@ -2230,6 +2230,16 @@ static int _validate_lock_args_chars(const char *lock_args)
return r;
}
static int _validate_vg_lock_args(struct volume_group *vg)
{
if (!vg->lock_args || !_validate_lock_args_chars(vg->lock_args)) {
log_error(INTERNAL_ERROR "VG %s has invalid lock_args chars", vg->name);
return 0;
}
return 1;
}
/*
* For lock_type sanlock, LV lock_args are <version>:<info>
* For lock_type dlm, LV lock_args are not used, and lock_args is
@@ -2596,6 +2606,8 @@ int vg_validate(struct volume_group *vg)
r = 0;
}
if (!_validate_vg_lock_args(vg))
r = 0;
} else {
if (vg->lock_args) {
log_error(INTERNAL_ERROR "VG %s has lock_args %s without lock_type",
@@ -5138,7 +5150,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const
}
if ((vg->pr & VG_PR_REQUIRE) && (writing || activating) && !cmd->disable_pr_required) {
if (!persist_is_started(cmd, vg, 0, NULL)) {
if (!persist_is_started(cmd, vg, 0)) {
failure |= FAILED_PR_REQUIRED;
goto_bad;
}

View File

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

View File

@@ -452,50 +452,50 @@ 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_compression
.br
.O_deduplication
.br
.O_deltag
.br
.O_detachprofile
.br
.O_discards
.br
.O_errorwhenfull
.br
.O_integritysettings
.O_minrecoveryrate
.br
.O_maxrecoveryrate
.br
.O_metadataprofile
.br
.O_minrecoveryrate
.br
.O_setautoactivation
.br
.O_vdosettings
.br
.O_integritysettings
.br
.O_writebehind
.br
.O_writemostly
@@ -508,11 +508,11 @@ required, after which the others are optional.
]
.br
[
.O_monitor
.O_poll
]
.br
[
.O_poll
.O_monitor
]
.br
[ COMMON_OPTIONS ]
@@ -583,11 +583,11 @@ Activate or deactivate an LV.
\fIVG\fP|\fILV\fP|\fITag\fP|\fISelect\fP\ .\|.\|.\&
.RS
[
.O_ignoreactivationskip
.O_partial
]
.br
[
.O_partial
.O_ignoreactivationskip
]
.br
[
@@ -595,7 +595,7 @@ Activate or deactivate an LV.
]
.br
[
.O_ignorelockingfailure
.O_poll
]
.br
[
@@ -603,17 +603,17 @@ Activate or deactivate an LV.
]
.br
[
.O_poll
]
.br
[
.O_readonly
.O_ignorelockingfailure
]
.br
[
.O_sysinit
]
.br
[
.O_readonly
]
.br
[ COMMON_OPTIONS ]
.RE
.
@@ -636,11 +636,11 @@ Reactivate an LV using the latest metadata.
]
.br
[
.O_monitor
.O_poll
]
.br
[
.O_poll
.O_monitor
]
.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_minor
.O_persistent
.O_minor
\fILV\fP
.RS
[
.O_activate
]
.br
[
.O_major
]
.br
[
.O_monitor
.O_activate
]
.br
[
.O_poll
]
.br
[
.O_monitor
]
.br
[ COMMON_OPTIONS ]
.RE
.P

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -20,44 +20,33 @@ lvmlockd \(em LVM locking daemon
.
.SH DESCRIPTION
.
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.
.
LVM commands use lvmlockd to coordinate access to shared storage.
.P
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:
When LVM is used on devices shared by multiple hosts, locks will:
.PD 0
.IP \[bu] 2
per-VG locks protect changes to the VG metadata.
coordinate reading and writing of LVM metadata
.IP \[bu]
LV locks limit LV activation to one host at a time.
validate caching of LVM metadata
.IP \[bu]
A Global lock protects unused PVs and the VG namespace.
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.
.PD
.
.SH OPTIONS
.
lvmlockd daemon command line options:
.P
.
.TP
.BR -h | --help
Show this help information.
@@ -119,287 +108,193 @@ Override the default sanlock I/O timeout.
.BR -A | --adopt " " 0 | 1
Enable (1) or disable (0) lock adoption.
.
.SH SETUP
.SH USAGE
.
The following steps provide a quick overview of how to use shared VGs.
More details can be found under SETUP DETAILS.
.P
.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
.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
.B $ vgcreate --shared
.I VG
.I devices
.P
Include vgcreate options to use Persistent Reservations (sanlock only):
.br
.B --setpersist y --setlockargs persist,notimeout
.P
Start Persistent Reservations (if they are used):
.br
.B $ vgchange --persist start
.I VG
.P
Start the lockspace for the shared VG on all hosts:
.br
.B $ vgchange --lockstart
.I VG
.P
.I Usage
.P
Begin using the VG, e.g. creating LVs.
.P
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
.SS Initial set up
.
.SH SETUP DETAILS
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):
.P
.B Identifying devices
.EX
use_lvmlockd = 1
.EE
.
.TP 8
.B sanlock
Assign each host a unique host_id in the range 1-2000 by setting
.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
.I #DEFAULT_SYS_DIR#/lvmlocal.conf
local/host_id
.
.SS 3. start lvmlockd
.
Start the lvmlockd daemon.
.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.
Use systemctl, a cluster resource agent, or run directly, e.g.
.P
.B Config files
.EX
systemctl start lvmlockd
.EE
.
.SS 4. start lock manager
.
.TP 8
.B sanlock
Start the sanlock and wdmd daemons.
.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
Use systemctl or run directly, e.g.
.sp
.EX
systemctl start wdmd sanlock
.EE
.
.TP
.B dlm
Start the dlm and corosync daemons.
.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".
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>
.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.
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
.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.
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.
.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.
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
.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
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
.
.SH TOPICS
.
.SS Displaying shared VGs
.P
The
.B vgs
command shows the letter
.B s
in the last (sixth) attr position for a shared VG:
.SS Protecting VGs on shared devices
.
.nf
The following terms are used to describe the different ways of accessing
VGs on shared devices.
.
.P
$ vgs
VG #PV #LV #SN Attr VSize VFree
vgfoo 1 0 0 wz--ns 992.00m 736.00m
.fi
.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.
.
.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
.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)).
.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.
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.
.
.SS Creating the first sanlock VG
.
When use_lvmlockd is first enabled in lvm.conf,
When use_lvmlockd is first enabled in
.BR lvm.conf (5),
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,
@@ -432,12 +327,27 @@ from concurrent use by another vgcreate on another host.
.P
See below for more information about managing the sanlock global lock.
.
.SS Removing a shared VG
.SS Using shared VGs
.
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.)
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.)
.
.SS Starting and stopping VGs
.
@@ -456,6 +366,32 @@ 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 \&.\|.\|.
@@ -464,6 +400,21 @@ 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
.
@@ -713,7 +664,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
@@ -917,11 +868,14 @@ vgmerge
.
.SS lvmlockd changes from clvmd
.
(See above for converting an existing clvm VG to a shared VG.)
.P
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):
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):
.
.IP \[bu] 2
.BR lvm.conf (5)
@@ -991,6 +945,9 @@ unable to passively check the remote active or lock state of an LV.
.
.nh
.na
.BR lvm (8),
.BR lvmlockctl (8),
.BR sanlock (8),
.BR dlm_controld (8)
.BR lvchange (8),
.BR lvgs (8),
.BR vgs (8),
.BR lvm.conf (5)

View File

@@ -258,7 +258,7 @@ Display the settings.
.P
.SS VG PR commands
.P
vgchange --persist is used to perform PR operations on the VG's devices.
vgchange --persist is used to perfom 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_fs
]
.br
[
.O_fsmode
]
.br
[
.O_noudevsync
]
.br
@@ -213,6 +205,14 @@ the options section.
.O_reportformat
]
.br
[
.O_fs
]
.br
[
.O_fsmode
]
.br
[ COMMON_OPTIONS ]
.RE
.P

View File

@@ -293,6 +293,10 @@ Resize an LV by a specified size.
]
.br
[
.O_poolmetadatasize
]
.br
[
.O_fs
]
.br
@@ -300,10 +304,6 @@ 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_all
.O_history
]
.br
[
.O_history
.O_all
]
.br
[
@@ -245,11 +245,39 @@ lvs produces formatted output about LVs.
]
.br
[
.O_select
]
.br
[
.O_sort
]
.br
[
.O_select
.O_segments
]
.br
[
.O_foreign
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_shared
]
.br
[
.O_units
]
.br
[
@@ -265,7 +293,7 @@ lvs produces formatted output about LVs.
]
.br
[
.O_foreign
.O_logonly
]
.br
[
@@ -273,14 +301,6 @@ lvs produces formatted output about LVs.
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_logonly
]
.br
[
.O_nameprefixes
]
.br
@@ -293,38 +313,18 @@ 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_uuid
.in +2n
.O_allocatable
.in +2n
.O_uuid
.br
.O_addtag
.br
@@ -189,9 +189,9 @@ Change properties of specified PVs.
.B pvchange
.RS
(
.O_uuid
.in +2n
.O_allocatable
.in +2n
.O_uuid
.br
.O_addtag
.br

View File

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

View File

@@ -276,10 +276,6 @@ pe_start value.
]
.br
[
.O_bootloaderareasize
]
.br
[
.O_dataalignment
]
.br
@@ -288,11 +284,15 @@ pe_start value.
]
.br
[
.O_bootloaderareasize
]
.br
[
.O_labelsector
]
.br
[
.O_metadataignore
.O_pvmetadatacopies
]
.br
[
@@ -300,11 +300,15 @@ pe_start value.
]
.br
[
.O_metadataignore
]
.br
[
.O_norestorefile
]
.br
[
.O_pvmetadatacopies
.O_setphysicalvolumesize
]
.br
[
@@ -315,10 +319,6 @@ 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_sort
.O_select
]
.br
[
.O_select
.O_sort
]
.br
[
@@ -394,11 +394,11 @@ Display output in columns like pvs.
]
.br
[
.O_headings
.O_logonly
]
.br
[
.O_logonly
.O_headings
]
.br
[

View File

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

View File

@@ -233,11 +233,11 @@ pvs produces formatted output about PVs.
.B pvs
.RS
[
.O_all
.O_allpvs
]
.br
[
.O_allpvs
.O_all
]
.br
[
@@ -245,11 +245,39 @@ pvs produces formatted output about PVs.
]
.br
[
.O_select
]
.br
[
.O_sort
]
.br
[
.O_select
.O_segments
]
.br
[
.O_foreign
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_shared
]
.br
[
.O_units
]
.br
[
@@ -265,7 +293,7 @@ pvs produces formatted output about PVs.
]
.br
[
.O_foreign
.O_logonly
]
.br
[
@@ -273,14 +301,6 @@ pvs produces formatted output about PVs.
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_logonly
]
.br
[
.O_nameprefixes
]
.br
@@ -293,38 +313,18 @@ 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,10 +315,6 @@ Display PV information.
.B pvscan
.RS
[
.O_allpvs
]
.br
[
.O_exported
]
.br
@@ -335,6 +331,10 @@ Display PV information.
]
.br
[
.O_allpvs
]
.br
[
.O_ignorelockingfailure
]
.br
@@ -363,6 +363,10 @@ Record that a PV is online or offline.
]
.br
[
.O_reportformat
]
.br
[
.O_minor
]
.br
@@ -370,10 +374,6 @@ 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_autoactivation
.O_ignorelockingfailure
]
.br
[
.O_ignorelockingfailure
.O_reportformat
]
.br
[
@@ -410,7 +410,7 @@ Record that a PV is online and autoactivate the VG if complete.
]
.br
[
.O_reportformat
.O_autoactivation
]
.br
[ COMMON_OPTIONS ]
@@ -430,7 +430,7 @@ Record that a PV is online and list the VG using the PV.
\fIPV\fP
.RS
[
.O_autoactivation
.O_ignorelockingfailure
]
.br
[
@@ -438,7 +438,7 @@ Record that a PV is online and list the VG using the PV.
]
.br
[
.O_ignorelockingfailure
.O_vgonline
]
.br
[
@@ -446,7 +446,7 @@ Record that a PV is online and list the VG using the PV.
]
.br
[
.O_vgonline
.O_autoactivation
]
.br
[ COMMON_OPTIONS ]
@@ -464,11 +464,11 @@ Record that a PV is online and list LVs using the PV.
\fIPV\fP
.RS
[
.O_checkcomplete
.O_ignorelockingfailure
]
.br
[
.O_ignorelockingfailure
.O_checkcomplete
]
.br
[

View File

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

View File

@@ -403,27 +403,27 @@ required, after which the others are optional.
.in +2n
.O_maxphysicalvolumes
.br
.O_physicalextentsize
.br
.O_uuid
.br
.O_physicalextentsize
.br
.O_resizeable
.br
.O_addtag
.br
.O_deltag
.br
.O_alloc
.br
.O_deltag
.O_pvmetadatacopies
.br
.O_vgmetadatacopies
.br
.O_detachprofile
.br
.O_metadataprofile
.br
.O_pvmetadatacopies
.br
.O_setautoactivation
.br
.O_vgmetadatacopies
)
.in
[
@@ -431,11 +431,15 @@ required, after which the others are optional.
]
.br
[
.O_select
]
.br
[
.O_force
]
.br
[
.O_select
.O_poll
]
.br
[
@@ -447,10 +451,6 @@ required, after which the others are optional.
]
.br
[
.O_poll
]
.br
[
.O_reportformat
]
.br
@@ -473,18 +473,26 @@ Start or stop monitoring LVs from dmeventd.
]
.br
[
.O_force
]
.br
[
.O_select
]
.br
[
.O_force
]
.br
[
.O_sysinit
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_poll
]
.br
[
.O_ignoremonitoring
]
.br
@@ -493,17 +501,9 @@ 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_force
.O_select
]
.br
[
.O_select
.O_force
]
.br
[
@@ -561,14 +561,6 @@ Activate or deactivate LVs.
.O_activate
.RS
[
.O_autobackup
]
.br
[
.O_force
]
.br
[
.O_ignoreactivationskip
]
.br
@@ -577,39 +569,23 @@ Activate or deactivate LVs.
]
.br
[
.O_autobackup
]
.br
[
.O_select
]
.br
[
.O_force
]
.br
[
.O_activationmode
]
.br
[
.O_autoactivation
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_ignoremonitoring
]
.br
[
.O_monitor
]
.br
[
.O_noudevsync
]
.br
[
\fB--persist\fP \fIString\fP
]
.br
[
.O_poll
.O_sysinit
]
.br
[
@@ -617,11 +593,35 @@ Activate or deactivate LVs.
]
.br
[
.O_reportformat
.O_ignorelockingfailure
]
.br
[
.O_sysinit
.O_monitor
]
.br
[
.O_poll
]
.br
[
.O_autoactivation
]
.br
[
.O_persist
]
.br
[
.O_ignoremonitoring
]
.br
[
.O_noudevsync
]
.br
[
.O_reportformat
]
.br
[ COMMON_OPTIONS ]
@@ -643,18 +643,26 @@ Reactivate LVs using the latest metadata.
]
.br
[
.O_force
]
.br
[
.O_select
]
.br
[
.O_force
]
.br
[
.O_sysinit
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_poll
]
.br
[
.O_ignoremonitoring
]
.br
@@ -663,17 +671,9 @@ 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
[
\fB--persist\fP \fIString\fP
.O_persist
]
.br
[
@@ -723,7 +723,7 @@ Set or clear flags to control persistent reservation behavior.
]
.br
[
\fB--persist\fP \fBstart\fP
.O_persist
]
.br
[ COMMON_OPTIONS ]
@@ -740,21 +740,21 @@ Perform persistent reservation commands on devices.
\fIVG\fP|\fITag\fP|\fISelect\fP
.RS
[
.O_force
]
.br
[
.O_select
]
.br
[
.O_majoritypvs
.O_force
]
.br
[
.O_removekey
]
.br
[
.O_majoritypvs
]
.br
[ COMMON_OPTIONS ]
.RE
.
@@ -772,7 +772,7 @@ Start the lockspace of a shared VG in lvmlockd.
]
.br
[
\fB--persist\fP \fBstart\fP
.O_persist
]
.br
[ COMMON_OPTIONS ]
@@ -794,7 +794,7 @@ Stop the lockspace of a shared VG in lvmlockd.
]
.br
[
\fB--persist\fP \fBstop\fP
.O_persist
]
.br
[ COMMON_OPTIONS ]
@@ -1254,14 +1254,12 @@ for individual LVs.
.TP
.O_setpersist
Set or clear flags to control persistent reservation behavior.
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.
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.
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.
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_bootloaderareasize
]
.br
[
.O_labelsector
]
.br
[
.O_metadatasize
.O_bootloaderareasize
]
.br
[
@@ -177,6 +173,10 @@ convert VGs from the LVM1 format to LVM2.
]
.br
[
.O_metadatasize
]
.br
[
.O_reportformat
]
.br

View File

@@ -134,10 +134,6 @@
.de O_nolocking
.OPS nolocking
..
.de O_persist
.OPA persist
\fIString\fP
..
.de O_physicalextentsize
.OPA s physicalextentsize
\fISize\fP[m|\:UNIT]
@@ -164,10 +160,6 @@
.OPA setautoactivation
\fBy\fP|\fBn\fP
..
.de O_setpersist
.OPA setpersist
\fIString\fP
..
.de O_shared
.OPS shared
..
@@ -243,26 +235,26 @@ device.
]
.br
[
.O_force
]
.br
[
.O_maxlogicalvolumes
]
.br
[
.O_metadatatype
]
.br
[
.O_maxphysicalvolumes
]
.br
[
.O_metadatatype
]
.br
[
.O_physicalextentsize
]
.br
[
.O_force
]
.br
[
.O_zero
]
.br
@@ -275,11 +267,7 @@ device.
]
.br
[
.O_dataalignment
]
.br
[
.O_dataalignmentoffset
.O_metadataprofile
]
.br
[
@@ -287,35 +275,27 @@ 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_setautoactivation
.O_dataalignment
]
.br
[
.O_setpersist
.O_dataalignmentoffset
]
.br
[
@@ -327,7 +307,11 @@ device.
]
.br
[
.O_vgmetadatacopies
.O_locktype
]
.br
[
.O_setautoactivation
]
.br
[ COMMON_OPTIONS ]
@@ -576,20 +560,6 @@ 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
@@ -642,18 +612,6 @@ 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_activevolumegroups
.O_short
]
.br
[
.O_short
.O_activevolumegroups
]
.br
[ COMMON_OPTIONS ]
@@ -368,11 +368,11 @@ Display output in columns like vgs.
]
.br
[
.O_sort
.O_select
]
.br
[
.O_select
.O_sort
]
.br
[
@@ -388,11 +388,11 @@ Display output in columns like vgs.
]
.br
[
.O_headings
.O_logonly
]
.br
[
.O_logonly
.O_headings
]
.br
[

View File

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

View File

@@ -188,19 +188,11 @@ will initialize them. In this case pvcreate options can be used, e.g.
]
.br
[
.O_metadatatype
]
.br
[
.O_zero
]
.br
[
.O_dataalignment
]
.br
[
.O_dataalignmentoffset
.O_metadatatype
]
.br
[
@@ -208,10 +200,6 @@ will initialize them. In this case pvcreate options can be used, e.g.
]
.br
[
.O_metadataignore
]
.br
[
.O_metadatasize
]
.br
@@ -220,6 +208,18 @@ will initialize them. In this case pvcreate options can be used, e.g.
]
.br
[
.O_metadataignore
]
.br
[
.O_dataalignment
]
.br
[
.O_dataalignmentoffset
]
.br
[
.O_reportformat
]
.br

View File

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

View File

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

View File

@@ -235,11 +235,35 @@ vgs produces formatted output about VGs.
]
.br
[
.O_select
]
.br
[
.O_sort
]
.br
[
.O_select
.O_foreign
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_shared
]
.br
[
.O_units
]
.br
[
@@ -255,7 +279,7 @@ vgs produces formatted output about VGs.
]
.br
[
.O_foreign
.O_logonly
]
.br
[
@@ -263,14 +287,6 @@ vgs produces formatted output about VGs.
]
.br
[
.O_ignorelockingfailure
]
.br
[
.O_logonly
]
.br
[
.O_nameprefixes
]
.br
@@ -283,14 +299,6 @@ vgs produces formatted output about VGs.
]
.br
[
.O_readonly
]
.br
[
.O_reportformat
]
.br
[
.O_rows
]
.br
@@ -299,18 +307,10 @@ 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_devices() {
check_device_types() {
err=0
FOUND_MPATH=0
FOUND_SCSI=0
@@ -559,31 +559,11 @@ check_devices() {
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() {
@@ -886,7 +866,6 @@ 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
@@ -1222,7 +1201,7 @@ fi
# subsequent string matching of keys fails.
DECDIGITS='^[0-9]+$'
HEXDIGITS='^[0-9a-fA-F]+$'
HEXDIGITS='^[0-9a-zA-Z]+$'
if [[ -n "$OURKEY" && "$OURKEY" == "0x0"* ]]; then
echo "Leading 0s are not permitted in keys."
@@ -1251,7 +1230,7 @@ if [[ -n "$OURKEY" && "$OURKEY" != "0x"* ]]; then
fi
if [[ -n "$OURKEY" && "$OURKEY" == "0x"* ]]; then
if [[ ! "${OURKEY:2}" =~ $HEXDIGITS ]]; then
if [[ ! "$OURKEY" =~ $HEXDIGITS ]]; then
echo "Invalid hex digits in key: $OURKEY"
exit 1
fi
@@ -1270,7 +1249,7 @@ if [[ -n "$REMKEY" && "$REMKEY" != "0x"* ]]; then
fi
if [[ -n "$REMKEY" && "$REMKEY" == "0x"* ]]; then
if [[ ! "${REMKEY:2}" =~ $HEXDIGITS ]]; then
if [[ ! "$REMKEY" =~ $HEXDIGITS ]]; then
echo "Invalid hex digits in key: $REMKEY"
exit 1
fi
@@ -1402,31 +1381,38 @@ 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,11 +19,6 @@ errorexit() {
exit 1
}
logerror() {
echo "$1" >&2
logger "${SCRIPTNAME}: $1"
}
logmsg() {
echo "$1"
logger "${SCRIPTNAME}: $1"
@@ -73,72 +68,6 @@ 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}"
@@ -169,7 +98,7 @@ fsextend() {
fi
fi
fi
if [ "$DO_CRYPTRESIZE" -eq 1 ]; then
logmsg "cryptsetup resize ${DEVPATH}"
if cryptsetup resize "$DEVPATH"; then
@@ -181,12 +110,8 @@ 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" ${MOUNT_OPTIONS:+-o "$MOUNT_OPTIONS"} "$DEVPATH" "$TMPDIR"; then
if mount -t "$FSTYPE" "$DEVPATH" "$TMPDIR"; then
logmsg "mount done"
TMP_MOUNT_DONE=1
else
@@ -245,12 +170,8 @@ 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" ${MOUNT_OPTIONS:+-o "$MOUNT_OPTIONS"} "$DEVPATH" "$MOUNTDIR"; then
if mount -t "$FSTYPE" "$DEVPATH" "$MOUNTDIR"; then
logmsg "remount done"
else
logmsg "remount failed"
@@ -463,9 +384,6 @@ 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-61[123].el9.*) return 1 ;; # Kernel is missing fixing commit!
6.12.0-12[456].el10.*) return 1 ;; # -- '' --
5.14.0-611.el9.*) return 1 ;; # Kernel is missing fixing commit!
6.12.0-124.el10.*) return 1 ;; # -- '' --
esac
}

View File

@@ -89,24 +89,12 @@ 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 "420.00m"
check lv_field $vg/$lv lv_size "400.00m"
lvremove -f $vg/$lv

View File

@@ -40,16 +40,26 @@ 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(adddev_ARG, '\0', "adddev", pv_VAL, 0, 0,
"Add a device to the devices file.\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(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(aligned_ARG, '\0', "aligned", 0, 0, 0,
"Use with --separator to align the output columns.\n")
@@ -98,6 +108,17 @@ 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"
@@ -124,9 +145,6 @@ 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")
@@ -143,40 +161,22 @@ 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(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(cachedevice_ARG, '\0', "cachedevice", pv_VAL, ARG_GROUPABLE, 0,
"The name of a device to use for a cache.\n")
arg(cachesize_ARG, '\0', "cachesize", sizemb_VAL, 0, 0,
"The size of cache to use.\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,6 +194,40 @@ 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"
@@ -208,17 +242,6 @@ 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")
@@ -363,10 +386,6 @@ 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"
@@ -387,6 +406,13 @@ 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")
@@ -429,15 +455,6 @@ 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")
@@ -462,6 +479,15 @@ 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"
@@ -575,6 +601,15 @@ 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"
@@ -588,6 +623,35 @@ 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(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"
@@ -662,14 +726,6 @@ 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"
@@ -693,9 +749,6 @@ 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"
@@ -708,6 +761,14 @@ 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"
@@ -775,66 +836,6 @@ 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"
@@ -853,21 +854,6 @@ 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,6 +876,21 @@ 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")
@@ -976,40 +977,6 @@ 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")
@@ -1020,6 +987,23 @@ 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")
@@ -1035,21 +1019,6 @@ 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")
@@ -1105,6 +1074,9 @@ 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")
@@ -1118,9 +1090,6 @@ 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"
@@ -1158,28 +1127,24 @@ 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(raidwritebehind_ARG, '\0', "raidwritebehind", number_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(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(split_ARG, '\0', "split", 0, 0, 0, NULL)
arg(metadatacopies_ARG, '\0', "metadatacopies", metadatacopies_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"
@@ -1252,6 +1217,11 @@ 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")
@@ -1264,16 +1234,18 @@ 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")
@@ -1416,6 +1388,9 @@ 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")
@@ -1444,24 +1419,11 @@ 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(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(logicalvolume_ARG, 'l', "logicalvolume", 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")
arg(maxlogicalvolumes_ARG, 'l', "maxlogicalvolumes", uint32_VAL, 0, 0,
"Sets the maximum number of LVs allowed in a VG.\n")
/*
* The extents_VAL is overridden in configure_command_option_values()
@@ -1519,15 +1481,9 @@ 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
@@ -1550,6 +1506,32 @@ 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"
@@ -1600,16 +1582,6 @@ 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"
@@ -1694,14 +1666,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"
@@ -1722,14 +1694,6 @@ 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"
@@ -1761,6 +1725,14 @@ 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)
@@ -1788,6 +1760,18 @@ 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"
@@ -1813,6 +1797,9 @@ 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"
@@ -1827,9 +1814,6 @@ 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 String, OO_VGCHANGE
--autoactivation String, --persist start, OO_VGCHANGE
OP: VG|Tag|Select ...
IO: --ignoreskippedcluster
ID: vgchange_activate
@@ -1843,11 +1843,6 @@ OO: --select String, --removekey String, --majoritypvs, --force
ID: vgchange_persist
DESC: Perform persistent reservation commands on devices.
vgchange --setlockargs String VG|Tag|Select
OO: --select String
ID: vgchange_setlockargs
DESC: Set or clear lock_args flags to control lock manager behavior.
vgchange --lockstart
OO: --select String, --persist start
OP: VG|Tag|Select ...
@@ -1861,7 +1856,6 @@ ID: vgchange_lockstop
DESC: Stop the lockspace of a shared VG in lvmlockd.
vgchange --locktype LockType VG
OO: --setlockargs String
ID: vgchange_locktype
DESC: Change the lock type for a shared VG.
@@ -1886,7 +1880,7 @@ OO: --addtag Tag, --alloc Alloc, --autobackup Bool, --clustered Bool, --maxlogic
--metadatasize SizeMB, --pvmetadatacopies MetadataCopiesPV, --vgmetadatacopies MetadataCopiesVG,
--reportformat ReportFmt, --dataalignment SizeKB, --dataalignmentoffset SizeKB,
--shared, --systemid String, --locktype LockType, --setautoactivation Bool,
--setpersist String, --persist start, --setlockargs String
--setpersist String, --persist start
ID: vgcreate_general
---

View File

@@ -387,60 +387,24 @@ 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.
* 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)
*/
/* Validate cmd_names & command_names arrays are properly sorted */
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 > %s).",
cmd_names[i].name, cmd_names[i + 1].name);
_names_validated = 0;
log_error("File cmds.h has unsorted name entry %s.",
cmd_names[i].name);
return 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 > %s).",
command_names[i].name, command_names[i + 1].name);
_names_validated = 0;
log_error("File commands.h has unsorted name entry %s.",
command_names[i].name);
return 0;
}
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;
_names_validated = 1;
}
#endif
if ((name = bsearch(name, command_names[0].name, LVM_COMMAND_COUNT,
@@ -1280,15 +1244,8 @@ 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;
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;
return strcmp((*optname1)->long_opt + 2, (*optname2)->long_opt + 2);
}
/* Create list of option names for printing alphabetically. */
@@ -1316,44 +1273,6 @@ 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;
@@ -1553,8 +1472,6 @@ 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

@@ -90,7 +90,6 @@ static const struct command_function _command_functions[CMD_COUNT] = {
{ vgchange_systemid_CMD, vgchange_systemid_cmd },
{ vgchange_setpersist_CMD, vgchange_setpersist_cmd },
{ vgchange_persist_CMD, vgchange_persist_cmd },
{ vgchange_setlockargs_CMD, vgchange_setlockargs_cmd },
/* lvdisplay variants */
{ lvdisplay_columns_CMD, lvdisplay_columns_cmd },

View File

@@ -691,22 +691,7 @@ static void _print_man_usage(char *lvmname, struct command *cmd)
if (_is_lvm_all_opt(opt_enum))
continue;
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);
}
_print_bracket_ds_opt_name(opt_enum);
printf(".br\n");
}

View File

@@ -521,8 +521,7 @@ int vgcreate_params_set_defaults(struct cmd_context *cmd,
*/
int vgcreate_params_set_from_args(struct cmd_context *cmd,
struct vgcreate_params *vp_new,
struct vgcreate_params *vp_def,
struct pvcreate_params *pp)
struct vgcreate_params *vp_def)
{
const char *system_id_arg_str;
const char *lock_type = NULL;
@@ -737,29 +736,6 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd,
vp_new->lock_type = lock_type;
log_debug("Setting lock_type to %s", vp_new->lock_type);
if (arg_is_set(cmd, setlockargs_ARG)) {
const char *set_args;
uint32_t lock_args_flags = 0;
if (!lock_type || strcmp(lock_type, "sanlock")) {
log_error("Using setlockargs requires sanlock lock type for shared VG.");
return 0;
}
if (!(set_args = arg_str_value(cmd, setlockargs_ARG, NULL)))
return_0;
if (!lockd_lockargs_get_user_flags(set_args, &lock_args_flags))
return_0;
if (!pp)
return_0;
if ((lock_args_flags & LOCKARGS_PERSIST) && !(pp->setpersist_flags & (SETPR_Y | SETPR_REQUIRE))) {
log_error("Using --setlockargs persist requires --setpersist y|require.");
return 0;
}
}
return 1;
}

View File

@@ -188,8 +188,7 @@ int vgcreate_params_set_defaults(struct cmd_context *cmd,
struct volume_group *vg);
int vgcreate_params_set_from_args(struct cmd_context *cmd,
struct vgcreate_params *vp_new,
struct vgcreate_params *vp_def,
struct pvcreate_params *pp);
struct vgcreate_params *vp_def);
int lv_change_activate(struct cmd_context *cmd, struct logical_volume *lv,
activation_change_t activate);
int lv_refresh(struct cmd_context *cmd, struct logical_volume *lv);

View File

@@ -175,7 +175,6 @@ int vgchange_lock_start_stop_cmd(struct cmd_context *cmd, int argc, char **argv)
int vgchange_systemid_cmd(struct cmd_context *cmd, int argc, char **argv);
int vgchange_setpersist_cmd(struct cmd_context *cmd, int argc, char **argv);
int vgchange_persist_cmd(struct cmd_context *cmd, int argc, char **argv);
int vgchange_setlockargs_cmd(struct cmd_context *cmd, int argc, char **argv);
const struct opt_name *get_opt_name(int opt);
const struct val_name *get_val_name(int val);

View File

@@ -205,7 +205,6 @@ 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
@@ -234,23 +233,8 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
}
}
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;
}
if (do_activate && !persist_start_include(cmd, vg, (activate == CHANGE_AAY), 0, NULL))
return 0;
/*
* Safe, since we never write out new metadata here. Required for
@@ -300,18 +284,6 @@ 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
@@ -683,7 +655,6 @@ static int _passes_lock_start_filter(struct cmd_context *cmd,
static int _vgchange_lock_start(struct cmd_context *cmd, struct volume_group *vg,
struct vgchange_params *vp)
{
uint64_t our_key = 0;
int auto_opt = 0;
int exists = 0;
int r;
@@ -714,12 +685,12 @@ do_start:
if (!persist_start_include(cmd, vg, 0, auto_opt, NULL))
return 0;
if ((vg->pr & (VG_PR_REQUIRE|VG_PR_AUTOSTART)) && !persist_is_started(cmd, vg, 0, &our_key)) {
if ((vg->pr & (VG_PR_REQUIRE|VG_PR_AUTOSTART)) && !persist_is_started(cmd, vg, 0)) {
log_error("VG %s PR should be started before locking (vgchange --persist start)", vg->name);
return 0;
}
r = lockd_start_vg(cmd, vg, our_key, &exists);
r = lockd_start_vg(cmd, vg, &exists);
if (r)
vp->lock_start_count++;
@@ -1128,37 +1099,10 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
if (noupdate)
cmd->ignore_device_name_mismatch = 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;
}
}
/* 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;
/*
* If the devices file includes PVs stacked on LVs, then
@@ -1340,7 +1284,7 @@ static int _vgchange_locktype(struct cmd_context *cmd, struct volume_group *vg,
vg->system_id = NULL;
if (!lockd_init_vg(cmd, vg, lock_type, lv_lock_count, arg_str_value(cmd, setlockargs_ARG, NULL))) {
if (!lockd_init_vg(cmd, vg, lock_type, lv_lock_count)) {
log_error("Failed to initialize lock args for lock type %s", lock_type);
return 0;
}
@@ -1880,7 +1824,7 @@ static int _vgchange_setpersist_single(struct cmd_context *cmd, const char *vg_n
* enabling/starting PR, otherwise enabling/starting PR will
* cause i/o to begin failing on those other hosts.
*/
if (on && vg_is_shared(vg) && !persist_is_started(cmd, vg, 1, NULL) &&
if (on && vg_is_shared(vg) && !persist_is_started(cmd, vg, 1) &&
lockd_vg_is_started(cmd, vg, NULL) && lockd_vg_is_busy(cmd, vg)) {
log_error("VG lockspace should be stopped on all hosts (vgchange --lockstop) before enabling PR.");
return ECMD_FAILED;
@@ -1950,51 +1894,3 @@ int vgchange_setpersist_cmd(struct cmd_context *cmd, int argc, char **argv)
return ret;
}
static int _vgchange_setlockargs_single(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg,
struct processing_handle *handle)
{
const char *set = arg_str_value(cmd, setlockargs_ARG, NULL);
uint64_t our_key_held = 0;
if (!set)
return_ECMD_FAILED;
/*
* lockd_setlockargs gets exclusive PR (if the VG is using PR),
* stops the lockspace, and sets new vg->lock_args that are
* written below. If lockd_setlockargs got the ex PR, then
* persist_upgrade_stop releases the PR.
*/
if (!lockd_setlockargs(cmd, vg, set, &our_key_held))
return_ECMD_FAILED;
if (!vg_write(vg) || !vg_commit(vg))
return_ECMD_FAILED;
if (our_key_held && !persist_upgrade_stop(cmd, vg, our_key_held))
log_warn("Failed to stop PR.");
persist_key_file_remove(cmd, vg);
log_print_unless_silent("Volume group \"%s\" successfully changed.", vg->name);
return ECMD_PROCESSED;
}
int vgchange_setlockargs_cmd(struct cmd_context *cmd, int argc, char **argv)
{
struct processing_handle *handle;
uint32_t flags = READ_FOR_UPDATE;
int ret;
if (!(handle = init_processing_handle(cmd, NULL))) {
log_error("Failed to initialize processing handle.");
return ECMD_FAILED;
}
ret = process_each_vg(cmd, argc, argv, NULL, NULL, flags, 0, handle, &_vgchange_setlockargs_single);
destroy_processing_handle(cmd, handle);
return ret;
}

View File

@@ -51,7 +51,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
if (!vgcreate_params_set_defaults(cmd, &vp_def, NULL))
return EINVALID_CMD_LINE;
vp_def.vg_name = vg_name;
if (!vgcreate_params_set_from_args(cmd, &vp_new, &vp_def, &pp))
if (!vgcreate_params_set_from_args(cmd, &vp_new, &vp_def))
return EINVALID_CMD_LINE;
if (!vgcreate_params_validate(cmd, &vp_new))
@@ -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_mda_copies(vg, vp_new.vgmetadatacopies) ||
!vg_set_persist(vg, pp.setpersist_flags))
!vg_set_persist(vg, pp.setpersist_flags) ||
!vg_set_mda_copies(vg, vp_new.vgmetadatacopies))
goto_bad;
if (arg_is_set(cmd, setautoactivation_ARG) && !arg_int_value(cmd, setautoactivation_ARG, 1))
@@ -160,7 +160,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
* a local VG. lockd_init_vg() then writes the VG a second time with
* both lock_type and lock_args set.
*/
if (!lockd_init_vg(cmd, vg, vp_new.lock_type, 0, arg_str_value(cmd, setlockargs_ARG, NULL))) {
if (!lockd_init_vg(cmd, vg, vp_new.lock_type, 0)) {
log_error("Failed to initialize lock args for lock type %s",
vp_new.lock_type);
vg_remove_pvs(vg);
@@ -181,15 +181,13 @@ 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, &our_key)) {
!persist_vgcreate_update(cmd, vg, pp.setpersist_flags)) {
log_error("Failed to start PR");
goto out;
}
if (!lockd_start_vg(cmd, vg, our_key, NULL)) {
if (!lockd_start_vg(cmd, vg, NULL)) {
log_error("Failed to start locking");
goto out;
}

View File

@@ -74,9 +74,6 @@ 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;
@@ -85,6 +82,9 @@ 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,8 +92,11 @@ static int _vgremove_single(struct cmd_context *cmd, const char *vg_name,
lockd_free_vg_final(cmd, vg);
if (pr_stop)
persist_vgremove_after(cmd, vg, &pr_devs, pr_key);
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);
}
return ECMD_PROCESSED;
}

View File

@@ -114,7 +114,7 @@ static int _vgrename_single(struct cmd_context *cmd, const char *vg_name,
}
if (vg->pr)
persist_key_file_rename(vg, vg_name, vp->vg_name_new);
persist_key_file_rename(vg_name, vp->vg_name_new);
/* Change the volume group name */
vg_rename(cmd, vg, vp->vg_name_new);

View File

@@ -609,7 +609,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
goto_bad;
}
vp_def.vg_name = vg_name_to;
if (!vgcreate_params_set_from_args(cmd, &vp_new, &vp_def, NULL)) {
if (!vgcreate_params_set_from_args(cmd, &vp_new, &vp_def)) {
r = EINVALID_CMD_LINE;
goto_bad;
}