1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-10-27 11:33:19 +03:00

Compare commits

...

1 Commits

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

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

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

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

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

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

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

Requires sanlock version 4.2.0 or later.
2025-10-03 09:57:10 -05:00
23 changed files with 2173 additions and 225 deletions

View File

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

View File

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

View File

@@ -60,4 +60,11 @@ 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 = version_from_args(vg_args, &major, NULL, NULL);
rv = lockd_lockargs_get_version(vg_args, &major, NULL, NULL);
if (rv < 0) {
log_error("check_args_version %s error %d", vg_args, rv);
return rv;

View File

@@ -0,0 +1,264 @@
/*
* 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,6 +63,10 @@ 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 */
@@ -119,6 +123,7 @@ 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
@@ -132,6 +137,32 @@ 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
@@ -147,9 +178,13 @@ 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_ */
@@ -166,7 +201,7 @@ struct action {
char lv_uuid[MAX_NAME+1];
char vg_args[MAX_ARGS+1];
char lv_args[MAX_ARGS+1];
char prev_lv_args[MAX_ARGS+1];
char other_args[MAX_ARGS+1];
struct owner owner;
struct pvs pvs; /* PV list for idm */
};
@@ -187,6 +222,7 @@ 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 */
};
@@ -209,8 +245,10 @@ 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 */
@@ -225,13 +263,14 @@ 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 drop_vg: 1;
unsigned int fence_pr: 1;
unsigned int no_timeout: 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 */
@@ -390,7 +429,9 @@ 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);
int version_from_args(char *args, unsigned int *major, unsigned int *minor, unsigned int *patch);
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);
static inline const char *mode_str(int x)
{
@@ -559,7 +600,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);
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_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);
@@ -584,6 +625,9 @@ 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)
{
@@ -592,7 +636,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)
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)
{
return -1;
}
@@ -706,6 +750,20 @@ 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,6 +28,8 @@
#define SANLK_ADD_NODELAY 0x00000002
/* FIXME: copied from sanlock header until the sanlock update is more widespread */
#define SANLK_GET_HOST_LOCAL 0x00000001
/* FIXME: copied from sanlock header until the sanlock update is more widespread */
#define SANLK_LSF_NO_TIMEOUT 0x00000004
#include <stddef.h>
#include <poll.h>
@@ -175,30 +177,32 @@ int lm_data_size_sanlock(void)
}
/*
* lock_args format
* 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.
*
* vg_lock_args format for sanlock is
* vg_version_string:undefined:lock_lv_name
* VG_LOCK_ARGS_V1 format:
* 1.0.0:lvname
*
* 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.
* VG_LOCK_ARGS_V2 format:
* 2.0.0:lvname:notimeout:persist
* 2.0.0:lvname:notimeout
* 2.0.0:lvname:persist
*/
#define VG_LOCK_ARGS_MAJOR 1
#define VG_LOCK_ARGS_MAJOR 2
#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
@@ -241,9 +245,31 @@ static void strcpy_name_len(char *buf, const char *str, size_t len)
memccpy(buf, str, 0, len);
}
static int lock_lv_name_from_args(char *vg_args, char *lock_lv_name)
/*
* 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)
{
return last_string_from_args(vg_args, 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;
}
static int lock_lv_offset_from_args(char *lv_args, uint64_t *lock_lv_offset)
@@ -269,7 +295,7 @@ static int check_args_version(char *args, unsigned int our_major)
unsigned int major = 0;
int rv;
rv = version_from_args(args, &major, NULL, NULL);
rv = lockd_lockargs_get_version(args, &major, NULL, NULL);
if (rv < 0) {
log_error("check_args_version %s error %d", args, rv);
return rv;
@@ -333,13 +359,13 @@ out:
}
#if LOCKDSANLOCK_SUPPORT >= 410
static int read_info_file(struct lockspace *ls, uint32_t *host_id, uint64_t *generation, int *sector_size, int *align_size)
static int read_info_file(char *vg_name, uint32_t *host_id, uint64_t *generation, int *sector_size, int *align_size, int *no_timeout)
{
char line[MAX_LINE];
char path[PATH_MAX] = { 0 };
FILE *fp;
if (dm_snprintf(path, sizeof(path), "/var/lib/lvm/lvmlockd_info_%s", ls->vg_name) < 0)
if (dm_snprintf(path, sizeof(path), "/var/lib/lvm/lvmlockd_info_%s", vg_name) < 0)
return -1;
if (!(fp = fopen(path, "r"))) {
@@ -362,11 +388,14 @@ static int read_info_file(struct lockspace *ls, uint32_t *host_id, uint64_t *gen
} 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", *host_id, (unsigned long long)*generation, *sector_size, *align_size);
log_debug("info file: read %u %llu %d %d %d", *host_id, (unsigned long long)*generation, *sector_size, *align_size, *no_timeout);
return 0;
fail:
@@ -376,14 +405,13 @@ fail:
}
#endif
static int write_info_file(struct lockspace *ls)
static int write_info_file(char *vg_name, uint32_t host_id, uint64_t generation, int sector_size, int align_size, int no_timeout)
{
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", ls->vg_name) < 0)
if (dm_snprintf(path, sizeof(path), "/var/lib/lvm/lvmlockd_info_%s", vg_name) < 0)
return -1;
if (!(fp = fopen(path, "w"))) {
@@ -391,17 +419,18 @@ static int write_info_file(struct lockspace *ls)
return -1;
}
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);
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);
if (fflush(fp))
log_warn("Failed to write/flush %s", path);
_fclose(fp, path);
log_debug("info file: wrote %u %llu %d %d", ls->host_id, (unsigned long long)ls->generation, lms->sector_size, lms->align_size);
log_debug("info file: wrote %u %llu %d %d %d", host_id, (unsigned long long)generation, sector_size, align_size, no_timeout);
return 0;
}
@@ -591,7 +620,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_flags, uint32_t *rs_flags, struct sanlk_host *hs)
uint32_t *ss_size_flags, uint32_t *rs_size_flags, int *no_timeout, struct sanlk_host *hs)
{
struct sanlk_lockspace ss;
uint32_t io_timeout = 0;
@@ -623,40 +652,43 @@ 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_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M;
*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN8M;
*ss_size_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN8M;
*rs_size_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_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN4M;
*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN4M;
*ss_size_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN4M;
*rs_size_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_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN2M;
*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN2M;
*ss_size_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN2M;
*rs_size_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_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN1M;
*rs_flags = SANLK_RES_SECTOR4K | SANLK_RES_ALIGN1M;
*ss_size_flags = SANLK_LSF_SECTOR4K | SANLK_LSF_ALIGN1M;
*rs_size_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_flags = SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M;
*rs_flags = SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M;
*ss_size_flags = SANLK_LSF_SECTOR512 | SANLK_LSF_ALIGN1M;
*rs_size_flags = SANLK_RES_SECTOR512 | SANLK_RES_ALIGN1M;
}
log_debug("read_lockspace_info %s %u found sector_size %d align_size %d",
path, host_id, *sector_size, *align_size);
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);
return 0;
}
@@ -670,43 +702,52 @@ 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)
int lm_init_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_args, int opt_align_mb, char *other_args)
{
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;
@@ -715,7 +756,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", lock_args_version, lock_lv_name);
rv = snprintf(vg_args, MAX_ARGS, "%s:%s", VG_LOCK_ARGS_V1, 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;
@@ -787,6 +828,9 @@ 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",
@@ -841,15 +885,6 @@ 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
@@ -888,6 +923,25 @@ 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;
}
@@ -905,12 +959,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;
@@ -918,24 +972,20 @@ 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",
lock_args_version,
LV_LOCK_ARGS_V1,
(unsigned long long)((align_size * LV_LOCK_BEGIN) + (align_size * daemon_test_lv_count)));
daemon_test_lv_count++;
return 0;
}
rv = lock_lv_name_from_args(vg_args, lock_lv_name);
rv = lockd_lockargs_get_locklv(vg_args, lock_lv_name);
if (rv < 0) {
log_error("S %s init_lv_san lock_lv_name_from_args error %d %s",
log_error("S %s init_lv_san lockd_lockargs_get_locklv error %d %s",
ls_name, rv, vg_args);
return rv;
}
@@ -957,7 +1007,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, NULL);
rv = read_lockspace_info(disk_path, 1, &sector_size, &align_size, &align_mb, &ss_flags, &rs_flags, &no_timeout, NULL);
if (rv < 0) {
log_error("S %s init_lv_san read_lockspace_info error %d %s",
ls_name, rv, disk_path);
@@ -1025,7 +1075,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",
lock_args_version, (unsigned long long)offset);
LV_LOCK_ARGS_V1, (unsigned long long)offset);
} else {
log_error("S %s init_lv_san write error %d offset %llu",
ls_name, rv, (unsigned long long)rv);
@@ -1065,9 +1115,9 @@ int lm_rename_vg_sanlock(char *ls_name, char *vg_name, uint32_t flags, char *vg_
return -EINVAL;
}
rv = lock_lv_name_from_args(vg_args, lock_lv_name);
rv = lockd_lockargs_get_locklv(vg_args, lock_lv_name);
if (rv < 0) {
log_error("S %s init_lv_san lock_lv_name_from_args error %d %s",
log_error("S %s init_lv_san lockd_lockargs_get_locklv error %d %s",
ls_name, rv, vg_args);
return rv;
}
@@ -1587,6 +1637,7 @@ 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;
@@ -1612,9 +1663,9 @@ int lm_prepare_lockspace_sanlock(struct lockspace *ls, uint64_t *prev_generation
goto fail;
}
rv = lock_lv_name_from_args(ls->vg_args, lock_lv_name);
rv = lockd_lockargs_get_locklv(ls->vg_args, lock_lv_name);
if (rv < 0) {
log_error("S %s prepare_lockspace_san lock_lv_name_from_args error %d %s",
log_error("S %s prepare_lockspace_san lockd_lockargs_get_locklv error %d %s",
ls->name, rv, ls->vg_args);
ret = -EARGS;
goto fail;
@@ -1711,15 +1762,16 @@ 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, &hs);
rv = read_lockspace_info(disk_path, lms->ss.host_id, &sector_size, &align_size, &align_mb, &ss_flags, &rs_flags, &no_timeout, &hs);
#if LOCKDSANLOCK_SUPPORT >= 410
if ((rv == -ELOCKREPAIR) && repair && !retries) {
uint64_t generation = 0;
uint32_t host_id = 0;
rv = read_info_file(ls, &host_id, &generation, &sector_size, &align_size);
rv = read_info_file(ls->vg_name, &host_id, &generation, &sector_size, &align_size, &no_timeout);
if (rv < 0) {
log_error("S %s prepare_lockspace_san cannot repair lockspace no info file", lsname);
ret = -EINVAL;
@@ -1750,6 +1802,9 @@ 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);
@@ -1899,7 +1954,7 @@ int lm_add_lockspace_sanlock(struct lockspace *ls, int adopt_only, int adopt_ok,
free(hs);
write_info_file(ls);
write_info_file(ls->vg_name, ls->host_id, ls->generation, lms->sector_size, lms->align_size, ls->no_timeout);
/*
* Don't let the lockspace be cleanly released if orphan locks
@@ -2203,6 +2258,7 @@ 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) {
/*
@@ -2231,6 +2287,9 @@ 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;
@@ -2421,6 +2480,7 @@ 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 */
@@ -2729,3 +2789,181 @@ 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

@@ -813,7 +813,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)
int persist_is_started(struct cmd_context *cmd, struct volume_group *vg, int may_fail, uint64_t *our_key_ret)
{
struct pv_list *pvl;
struct device *dev;
@@ -826,6 +826,9 @@ 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;
@@ -1093,7 +1096,7 @@ int persist_key_update(struct cmd_context *cmd, struct volume_group *vg, uint32_
/*
* When using an explicit pr_key setting, there's
* not sanlock generation number that needs updating.
* no sanlock generation number that needs updating.
*/
if (local_key)
return 1;
@@ -1794,6 +1797,117 @@ 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
@@ -1817,6 +1931,8 @@ 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);
if (local_key) {
if (!parse_prkey(local_key, &our_key_val)) {
log_error("Failed to parse local key %s", local_key);
@@ -1883,7 +1999,8 @@ int persist_vgcreate_begin(struct cmd_context *cmd, char *vg_name, char *local_k
* access PR (typically WE), and starts PR with the normal sh access
* PR (typically WEAR), allowing other hosts to also use the new VG.
*/
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags)
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags,
uint64_t *our_key_ret)
{
DM_LIST_INIT(devs);
struct device_list *devl;
@@ -1987,9 +2104,13 @@ int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, ui
return 0;
}
/* key file is an optimization, not an error condition */
if (!write_key_file(cmd, vg, our_key_val))
stack;
if (our_key_ret)
*our_key_ret = our_key_val;
return 1;
}

View File

@@ -62,9 +62,13 @@ int persist_start_extend(struct cmd_context *cmd, struct volume_group *vg);
int persist_vgcreate_begin(struct cmd_context *cmd, char *vg_name, char *local_key, int local_host_id,
uint32_t set_flags, struct dm_list *devs);
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags);
int persist_vgcreate_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t set_flags,
uint64_t *our_key_ret);
int persist_is_started(struct cmd_context *cmd, struct volume_group *vg, int may_fail);
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_key_update(struct cmd_context *cmd, struct volume_group *vg, uint32_t prev_gen);

View File

@@ -117,6 +117,62 @@ 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)
{
@@ -169,7 +225,7 @@ static char *_owner_str(struct owner *owner)
#define NO_LOCKD_RESULT (-1000)
static int _lockd_result(struct cmd_context *cmd, const char *req_name, daemon_reply reply,
int *result, uint32_t *lockd_flags, struct owner *owner)
int *result, uint32_t *lockd_flags, struct owner *owner, uint64_t *our_generation)
{
int reply_result;
const char *str;
@@ -206,6 +262,9 @@ static int _lockd_result(struct cmd_context *cmd, const char *req_name, daemon_r
owner->name = dm_pool_strdup(cmd->mem, str);
}
if (our_generation)
*our_generation = (uint64_t)daemon_reply_int(reply, "our_generation", 0);
log_debug("lockd %s result: %d", req_name, reply_result);
return 1;
}
@@ -420,7 +479,8 @@ static int _lockd_request(struct cmd_context *cmd,
const struct lvmlockd_pvs *lock_pvs,
int *result,
uint32_t *lockd_flags,
struct owner *owner)
struct owner *owner,
uint64_t *our_generation)
{
const char *cmd_name = get_cmd_name();
daemon_reply reply;
@@ -457,7 +517,7 @@ static int _lockd_request(struct cmd_context *cmd,
"lv_lock_args = %s", lv_lock_args ?: "none",
NULL);
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner))
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner, our_generation))
goto fail;
/*
@@ -477,7 +537,7 @@ static int _lockd_request(struct cmd_context *cmd,
"vg_lock_args = %s", vg_lock_args ?: "none",
NULL);
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner))
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner, our_generation))
goto fail;
/*
@@ -495,7 +555,7 @@ static int _lockd_request(struct cmd_context *cmd,
"vg_lock_type = %s", vg_lock_type ?: "none",
NULL);
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner))
if (!_lockd_result(cmd, req_name, reply, result, lockd_flags, owner, our_generation))
goto fail;
log_debug("lockd %s %s result %d %x",
@@ -766,7 +826,7 @@ static int _handle_sanlock_lv(struct cmd_context *cmd, struct volume_group *vg)
"lv_size_bytes = " FMTd64, (int64_t) lv_size_bytes,
NULL);
if (!_lockd_result(cmd, "find_free_lock", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "find_free_lock", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -821,7 +881,7 @@ static int _init_vg(struct cmd_context *cmd, struct volume_group *vg,
"vg_lock_type = %s", lock_type,
NULL);
if (!_lockd_result(cmd, "init_vg", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "init_vg", reply, &result, NULL, NULL, NULL)) {
ret = 0;
result = -ELOCKD;
} else {
@@ -892,7 +952,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)
static int _init_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg, int lv_lock_count, const char *set_args)
{
daemon_reply reply;
const char *reply_str;
@@ -908,9 +968,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,
@@ -1014,11 +1074,12 @@ 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)) {
if (!_lockd_result(cmd, "init_vg", reply, &result, NULL, NULL, NULL)) {
ret = 0;
result = -ELOCKD;
} else {
@@ -1120,7 +1181,7 @@ static int _free_vg(struct cmd_context *cmd, struct volume_group *vg)
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "free_vg", reply, &result, &lockd_flags, NULL)) {
if (!_lockd_result(cmd, "free_vg", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1181,7 +1242,7 @@ int lockd_vg_is_busy(struct cmd_context *cmd, struct volume_group *vg)
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "busy_vg", reply, &result, &lockd_flags, NULL)) {
if (!_lockd_result(cmd, "busy_vg", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 1;
goto out;
}
@@ -1244,7 +1305,7 @@ static int _free_vg_sanlock(struct cmd_context *cmd, struct volume_group *vg)
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "free_vg", reply, &result, &lockd_flags, NULL)) {
if (!_lockd_result(cmd, "free_vg", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1301,7 +1362,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 *lock_type, int lv_lock_count, const char *set_args)
{
switch (get_lock_type_from_string(lock_type)) {
case LOCK_TYPE_NONE:
@@ -1311,7 +1372,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);
return _init_vg_sanlock(cmd, vg, lv_lock_count, set_args);
case LOCK_TYPE_IDM:
return _init_vg_idm(cmd, vg);
default:
@@ -1437,7 +1498,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, int *exists)
int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, uint64_t our_key, int *exists)
{
char uuid[64] __attribute__((aligned(8)));
const char *opts = NULL;
@@ -1515,6 +1576,7 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists
"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);
@@ -1528,11 +1590,12 @@ int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, int *exists
"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)) {
if (!_lockd_result(cmd, "start_vg", reply, &result, &lockd_flags, NULL, NULL)) {
ret = 0;
result = -ELOCKD;
} else {
@@ -1622,7 +1685,7 @@ int lockd_stop_vg(struct cmd_context *cmd, struct volume_group *vg)
"vg_name = %s", vg->name,
NULL);
if (!_lockd_result(cmd, "stop_vg", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "stop_vg", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1668,7 +1731,7 @@ int lockd_start_wait(struct cmd_context *cmd)
"pid = " FMTd64, (int64_t) getpid(),
NULL);
if (!_lockd_result(cmd, "start_wait", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "start_wait", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -1787,7 +1850,7 @@ int lockd_global_create(struct cmd_context *cmd, const char *def_mode, const cha
req:
if (!_lockd_request(cmd, "lock_gl",
NULL, vg_lock_type, NULL, NULL, NULL, NULL, mode, NULL,
NULL, &result, &lockd_flags, &owner)) {
NULL, &result, &lockd_flags, &owner, NULL)) {
/* No result from lvmlockd, it is probably not running. */
log_error("Global lock failed: check that lvmlockd is running.");
return 0;
@@ -2051,7 +2114,7 @@ int lockd_global(struct cmd_context *cmd, const char *def_mode)
if (!_lockd_request(cmd, "lock_gl",
NULL, NULL, NULL, NULL, NULL, NULL, mode, opts,
NULL, &result, &lockd_flags, &owner)) {
NULL, &result, &lockd_flags, &owner, NULL)) {
/* No result from lvmlockd, it is probably not running. */
/* We don't care if an unlock fails. */
@@ -2288,6 +2351,7 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode,
uint32_t flags, uint32_t *lockd_state)
{
struct owner owner = { 0 };
uint64_t our_generation = 0;
char opt_buf[64] = {};
const char *mode = NULL;
const char *opts = NULL;
@@ -2402,7 +2466,7 @@ int lockd_vg(struct cmd_context *cmd, const char *vg_name, const char *def_mode,
if (!_lockd_request(cmd, "lock_vg",
vg_name, NULL, NULL, NULL, NULL, NULL, mode, opts,
NULL, &result, &lockd_flags, &owner)) {
NULL, &result, &lockd_flags, &owner, &our_generation)) {
/*
* No result from lvmlockd, it is probably not running.
* Decide if it is ok to continue without a lock in
@@ -2615,7 +2679,7 @@ out:
*/
if ((lockd_flags & LD_RF_DUP_GL_LS) && strcmp(mode, "un"))
log_warn("Duplicate sanlock global lock in VG %s", vg_name);
return ret;
}
@@ -2660,7 +2724,7 @@ int lockd_vg_update(struct volume_group *vg)
"version = " FMTd64, (int64_t) vg->seqno,
NULL);
if (!_lockd_result(vg->cmd, "vg_update", reply, &result, NULL, NULL)) {
if (!_lockd_result(vg->cmd, "vg_update", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -2674,6 +2738,7 @@ int lockd_vg_is_started(struct cmd_context *cmd, struct volume_group *vg, uint32
{
daemon_reply reply;
struct owner owner = { 0 };
uint64_t our_generation = 0;
int result;
int ret = 0;
@@ -2691,7 +2756,7 @@ int lockd_vg_is_started(struct cmd_context *cmd, struct volume_group *vg, uint32
"vg_name = %s", vg->name,
NULL);
if (!_lockd_result(vg->cmd, "vg_status", reply, &result, NULL, &owner)) {
if (!_lockd_result(vg->cmd, "vg_status", reply, &result, NULL, &owner, &our_generation)) {
log_debug("lockd_vg_status %s no result", vg->name);
goto out;
}
@@ -2701,6 +2766,16 @@ int lockd_vg_is_started(struct cmd_context *cmd, struct volume_group *vg, uint32
goto out;
}
/*
* The local host generation number is returned
* in both fields, they should always match.
*/
if (our_generation && owner.generation &&
((uint32_t)our_generation != owner.generation)) {
log_warn("WARNING: lvmlockd local host generation mismatch %llu vs %u",
(unsigned long long)our_generation, owner.generation);
}
log_debug("lockd_vg_status %s host_id %u gen %u",
vg->name, owner.host_id, owner.generation);
@@ -2734,7 +2809,7 @@ static int _query_lv(struct cmd_context *cmd, struct volume_group *vg,
"lv_lock_args = %s", lock_args ?: "none",
NULL);
if (!_lockd_result(cmd, "query_lock_lv", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "query_lock_lv", reply, &result, NULL, NULL, NULL)) {
/* No result from lvmlockd, it is probably not running. */
log_error("Lock query failed for LV %s/%s", vg->name, lv_name);
return 0;
@@ -2807,6 +2882,7 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
const char *opts = NULL;
const char *mode = NULL;
uint32_t lockd_flags;
uint64_t our_generation = 0;
int refreshed = 0;
int result;
struct lvmlockd_pvs lock_pvs;
@@ -2905,7 +2981,7 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
if (!_lockd_request(cmd, "lock_lv",
vg->name, vg->lock_type, vg->lock_args,
lv_name, lv_uuid, lock_args, mode, opts,
&lock_pvs, &result, &lockd_flags, NULL)) {
&lock_pvs, &result, &lockd_flags, NULL, NULL)) {
_lockd_free_pv_list(&lock_pvs);
/* No result from lvmlockd, it is probably not running. */
log_error("Locking failed for LV %s/%s", vg->name, lv_name);
@@ -2916,7 +2992,7 @@ int lockd_lv_name(struct cmd_context *cmd, struct volume_group *vg,
if (!_lockd_request(cmd, "lock_lv",
vg->name, vg->lock_type, vg->lock_args,
lv_name, lv_uuid, lock_args, mode, opts,
NULL, &result, &lockd_flags, &owner)) {
NULL, &result, &lockd_flags, &owner, &our_generation)) {
/* No result from lvmlockd, it is probably not running. */
log_error("Locking failed for LV %s/%s", vg->name, lv_name);
return 0;
@@ -3846,7 +3922,7 @@ static int _init_lv_sanlock(struct cmd_context *cmd, struct volume_group *vg,
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "init_lv", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "init_lv", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -3921,7 +3997,7 @@ static int _free_lv(struct cmd_context *cmd, struct volume_group *vg,
"lv_lock_args = %s", lock_args ?: "none",
NULL);
if (!_lockd_result(cmd, "free_lv", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "free_lv", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -4186,7 +4262,7 @@ int lockd_rename_vg_before(struct cmd_context *cmd, struct volume_group *vg)
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "rename_vg_before", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "rename_vg_before", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -4231,7 +4307,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, NULL))
if (!lockd_start_vg(cmd, vg, 0, NULL))
log_error("Failed to restart VG %s lockspace.", vg->name);
return 1;
}
@@ -4251,7 +4327,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
"vg_lock_args = %s", vg->lock_args,
NULL);
if (!_lockd_result(cmd, "rename_vg_final", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "rename_vg_final", reply, &result, NULL, NULL, NULL)) {
ret = 0;
} else {
ret = (result < 0) ? 0 : 1;
@@ -4271,7 +4347,7 @@ int lockd_rename_vg_final(struct cmd_context *cmd, struct volume_group *vg, int
}
}
if (!lockd_start_vg(cmd, vg, NULL))
if (!lockd_start_vg(cmd, vg, 0, NULL))
log_error("Failed to start VG %s lockspace.", vg->name);
return 1;
@@ -4292,7 +4368,7 @@ const char *lockd_running_lock_type(struct cmd_context *cmd, int *found_multiple
"pid = " FMTd64, (int64_t) getpid(),
NULL);
if (!_lockd_result(cmd, "running_lm", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "running_lm", reply, &result, NULL, NULL, NULL)) {
log_error("Failed to get result from lvmlockd");
goto out;
}
@@ -4413,7 +4489,7 @@ int lockd_lv_refresh(struct cmd_context *cmd, struct lvresize_params *lp)
"path = %s", path,
NULL);
if (!_lockd_result(cmd, "refresh_lv", reply, &result, NULL, NULL)) {
if (!_lockd_result(cmd, "refresh_lv", reply, &result, NULL, NULL, NULL)) {
/* No result from lvmlockd, it is probably not running. */
log_error("LV refresh failed for LV %s", path);
return 0;
@@ -4487,3 +4563,171 @@ 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,6 +14,7 @@
#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"
@@ -66,6 +67,7 @@
#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;
@@ -82,7 +84,8 @@ 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);
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_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);
@@ -93,7 +96,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, int *exists);
int lockd_start_vg(struct cmd_context *cmd, struct volume_group *vg, uint64_t our_key, 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);
@@ -142,12 +145,19 @@ 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)
{
}
@@ -173,7 +183,8 @@ 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)
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)
{
return 1;
}
@@ -345,6 +356,11 @@ 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,16 +2230,6 @@ 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
@@ -2606,8 +2596,6 @@ 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",
@@ -5150,7 +5138,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)) {
if (!persist_is_started(cmd, vg, 0, NULL)) {
failure |= FAILED_PR_REQUIRED;
goto_bad;
}

View File

@@ -157,6 +157,15 @@ Create a shared VG from one host (uses the running lock manager):
.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
@@ -170,7 +179,7 @@ Regular shutdown steps:
.br
$ vgchange -an VG
.br
$ vgchange --lockstop VG
$ vgchange --lockstop [--persist stop] VG
.br
$ stop lvmlockd and lock manager
.br
@@ -179,7 +188,7 @@ Regular startup steps:
.br
$ start lvmlockd and lock manager
.br
$ vgchange --lockstart VG
$ vgchange --lockstart [--persist start] VG
.P
.
.SH SETUP DETAILS
@@ -252,6 +261,25 @@ to begin using locks (i.e. creating and joining a lockspace). Starting the
VG may take some time, and until the start completes the VG may not be
modified or activated. When shutting down, the lockspace is stopped with
vgchange --lockstop VG.
.P
.B Persistent Reservations
.br
A shared VG with locktype sanlock can take advantage of Persistent
Reservations (PR) for faster and more reliable recovery. This
requires that all of the shared devices in the VG support PR. Test
if PR is supported by a device with the command:
.br
.B $ lvmpersist devtest --device
.I device
.P
The vgcreate command options when enabling PR recovery with sanlock:
.br
.B $ vgcreate --shared --setpersist y --setlockargs persist,notimeout
.P
When enabled, PR needs to be started for the VG before locking:
.br
.B $ vgchange --persist start
.I VG
.
.SH TOPICS
.
@@ -310,6 +338,53 @@ $ vgs --shared
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

View File

@@ -786,6 +786,20 @@ arg(setautoactivation_ARG, '\0', "setautoactivation", bool_VAL, 0, 0,
"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"

View File

@@ -1843,6 +1843,11 @@ 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 ...
@@ -1856,6 +1861,7 @@ 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.
@@ -1880,7 +1886,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
--setpersist String, --persist start, --setlockargs String
ID: vgcreate_general
---

View File

@@ -90,6 +90,7 @@ 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

@@ -521,7 +521,8 @@ 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 vgcreate_params *vp_def,
struct pvcreate_params *pp)
{
const char *system_id_arg_str;
const char *lock_type = NULL;
@@ -736,6 +737,29 @@ 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,7 +188,8 @@ 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 vgcreate_params *vp_def,
struct pvcreate_params *pp);
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,6 +175,7 @@ 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

@@ -683,6 +683,7 @@ 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;
@@ -713,12 +714,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)) {
if ((vg->pr & (VG_PR_REQUIRE|VG_PR_AUTOSTART)) && !persist_is_started(cmd, vg, 0, &our_key)) {
log_error("VG %s PR should be started before locking (vgchange --persist start)", vg->name);
return 0;
}
r = lockd_start_vg(cmd, vg, &exists);
r = lockd_start_vg(cmd, vg, our_key, &exists);
if (r)
vp->lock_start_count++;
@@ -1339,7 +1340,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)) {
if (!lockd_init_vg(cmd, vg, lock_type, lv_lock_count, arg_str_value(cmd, setlockargs_ARG, NULL))) {
log_error("Failed to initialize lock args for lock type %s", lock_type);
return 0;
}
@@ -1879,7 +1880,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) &&
if (on && vg_is_shared(vg) && !persist_is_started(cmd, vg, 1, NULL) &&
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;
@@ -1949,3 +1950,51 @@ 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

@@ -46,13 +46,12 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
pp.pv_names = argv;
pp.vg_name = vg_name;
pp.preserve_existing = 1; /* Don't create a new PV on top of an existing PV like pvcreate does. */
pp.check_consistent_block_size = 1;
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))
if (!vgcreate_params_set_from_args(cmd, &vp_new, &vp_def, &pp))
return EINVALID_CMD_LINE;
if (!vgcreate_params_validate(cmd, &vp_new))
@@ -161,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)) {
if (!lockd_init_vg(cmd, vg, vp_new.lock_type, 0, arg_str_value(cmd, setlockargs_ARG, NULL))) {
log_error("Failed to initialize lock args for lock type %s",
vp_new.lock_type);
vg_remove_pvs(vg);
@@ -182,13 +181,15 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
* read without locks until the lockspace is done starting.)
*/
if (vg_is_shared(vg)) {
uint64_t our_key = 0;
if (pp.setpersist_flags &&
!persist_vgcreate_update(cmd, vg, pp.setpersist_flags)) {
!persist_vgcreate_update(cmd, vg, pp.setpersist_flags, &our_key)) {
log_error("Failed to start PR");
goto out;
}
if (!lockd_start_vg(cmd, vg, NULL)) {
if (!lockd_start_vg(cmd, vg, our_key, NULL)) {
log_error("Failed to start locking");
goto out;
}

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)) {
if (!vgcreate_params_set_from_args(cmd, &vp_new, &vp_def, NULL)) {
r = EINVALID_CMD_LINE;
goto_bad;
}