mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
lvmlockctl: use lvm.conf lvmlockctl_kill_command
which specifies a command to run by lvmlockctl --kill.
This commit is contained in:
parent
e9d10f3711
commit
89a3440fc0
3
configure
vendored
3
configure
vendored
@ -693,6 +693,7 @@ MANGLING
|
|||||||
LVM_RELEASE_DATE
|
LVM_RELEASE_DATE
|
||||||
LVM_RELEASE
|
LVM_RELEASE
|
||||||
LVM_PATH
|
LVM_PATH
|
||||||
|
LVM_DIR
|
||||||
LVM_PATCHLEVEL
|
LVM_PATCHLEVEL
|
||||||
LVM_MINOR
|
LVM_MINOR
|
||||||
LVM_MAJOR
|
LVM_MAJOR
|
||||||
@ -13766,9 +13767,11 @@ SYSCONFDIR="$(eval echo $(eval echo $sysconfdir))"
|
|||||||
|
|
||||||
SBINDIR="$(eval echo $(eval echo $sbindir))"
|
SBINDIR="$(eval echo $(eval echo $sbindir))"
|
||||||
LVM_PATH="$SBINDIR/lvm"
|
LVM_PATH="$SBINDIR/lvm"
|
||||||
|
LVM_DIR="$SBINDIR/"
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
#define LVM_PATH "$LVM_PATH"
|
#define LVM_PATH "$LVM_PATH"
|
||||||
|
#define LVM_DIR "$LVM_DIR"
|
||||||
_ACEOF
|
_ACEOF
|
||||||
|
|
||||||
|
|
||||||
|
@ -1607,7 +1607,9 @@ SYSCONFDIR="$(eval echo $(eval echo $sysconfdir))"
|
|||||||
|
|
||||||
SBINDIR="$(eval echo $(eval echo $sbindir))"
|
SBINDIR="$(eval echo $(eval echo $sbindir))"
|
||||||
LVM_PATH="$SBINDIR/lvm"
|
LVM_PATH="$SBINDIR/lvm"
|
||||||
|
LVM_DIR="$SBINDIR/"
|
||||||
AC_DEFINE_UNQUOTED(LVM_PATH, ["$LVM_PATH"], [Path to lvm binary.])
|
AC_DEFINE_UNQUOTED(LVM_PATH, ["$LVM_PATH"], [Path to lvm binary.])
|
||||||
|
AC_DEFINE_UNQUOTED(LVM_DIR, ["$LVM_DIR"], [Path to lvm binary dir.])
|
||||||
|
|
||||||
LVMCONFIG_PATH="$SBINDIR/lvmconfig"
|
LVMCONFIG_PATH="$SBINDIR/lvmconfig"
|
||||||
AC_DEFINE_UNQUOTED(LVMCONFIG_PATH, ["$LVMCONFIG_PATH"], [Path to lvmconfig binary.])
|
AC_DEFINE_UNQUOTED(LVMCONFIG_PATH, ["$LVMCONFIG_PATH"], [Path to lvmconfig binary.])
|
||||||
|
@ -30,6 +30,7 @@ static int kill_vg = 0;
|
|||||||
static int drop_vg = 0;
|
static int drop_vg = 0;
|
||||||
static int gl_enable = 0;
|
static int gl_enable = 0;
|
||||||
static int gl_disable = 0;
|
static int gl_disable = 0;
|
||||||
|
static int use_stderr = 0;
|
||||||
static int stop_lockspaces = 0;
|
static int stop_lockspaces = 0;
|
||||||
static char *arg_vg_name = NULL;
|
static char *arg_vg_name = NULL;
|
||||||
|
|
||||||
@ -47,6 +48,22 @@ do { \
|
|||||||
printf(fmt "\n", ##args); \
|
printf(fmt "\n", ##args); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define log_sys_emerg(fmt, args...) \
|
||||||
|
do { \
|
||||||
|
if (use_stderr) \
|
||||||
|
fprintf(stderr, fmt "\n", ##args); \
|
||||||
|
else \
|
||||||
|
syslog(LOG_EMERG, fmt, ##args); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define log_sys_warn(fmt, args...) \
|
||||||
|
do { \
|
||||||
|
if (use_stderr) \
|
||||||
|
fprintf(stderr, fmt "\n", ##args); \
|
||||||
|
else \
|
||||||
|
syslog(LOG_WARNING, fmt, ##args); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define MAX_LINE 512
|
#define MAX_LINE 512
|
||||||
|
|
||||||
/* copied from lvmlockd-internal.h */
|
/* copied from lvmlockd-internal.h */
|
||||||
@ -502,51 +519,62 @@ static int do_stop_lockspaces(void)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_kill(void)
|
/* Returns -1 on error, 0 on success. */
|
||||||
|
|
||||||
|
static int _get_kill_command(char *kill_cmd)
|
||||||
{
|
{
|
||||||
daemon_reply reply;
|
char config_cmd[PATH_MAX] = { 0 };
|
||||||
int result;
|
char config_val[1024] = { 0 };
|
||||||
int rv;
|
char line[PATH_MAX] = { 0 };
|
||||||
|
char type[4] = { 0 };
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
syslog(LOG_EMERG, "Lost access to sanlock lease storage in VG %s.", arg_vg_name);
|
snprintf(config_cmd, PATH_MAX, "%s/lvmconfig --typeconfig full global/lvmlockctl_kill_command", LVM_DIR);
|
||||||
/* These two lines explain the manual alternative to the FIXME below. */
|
type[0] = 'r';
|
||||||
syslog(LOG_EMERG, "Immediately deactivate LVs in VG %s.", arg_vg_name);
|
|
||||||
syslog(LOG_EMERG, "Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
|
|
||||||
|
|
||||||
/*
|
if (!(fp = popen(config_cmd, type))) {
|
||||||
* It may not be strictly necessary to notify lvmlockd of the kill, but
|
log_error("failed to run %s", config_cmd);
|
||||||
* lvmlockd can use this information to avoid attempting any new lock
|
return -1;
|
||||||
* requests in the VG (which would fail anyway), and can return an
|
|
||||||
* error indicating that the VG has been killed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
reply = _lvmlockd_send("kill_vg",
|
|
||||||
"cmd = %s", "lvmlockctl",
|
|
||||||
"pid = " FMTd64, (int64_t) getpid(),
|
|
||||||
"vg_name = %s", arg_vg_name,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!_lvmlockd_result(reply, &result)) {
|
|
||||||
log_error("lvmlockd result %d", result);
|
|
||||||
rv = result;
|
|
||||||
} else {
|
|
||||||
rv = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
daemon_reply_destroy(reply);
|
if (!fgets(line, sizeof(line), fp)) {
|
||||||
|
log_error("no output from %s", config_cmd);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
if (sscanf(line, "lvmlockctl_kill_command=\"%256[^\n\"]\"", config_val) != 1) {
|
||||||
* FIXME: here is where we should implement a strong form of
|
log_error("unrecognized config value from %s", config_cmd);
|
||||||
* blkdeactivate, and if it completes successfully, automatically call
|
goto bad;
|
||||||
* do_drop() afterward. (The drop step may not always be necessary
|
}
|
||||||
* if the lvm commands run while shutting things down release all the
|
|
||||||
* leases.)
|
|
||||||
*
|
|
||||||
* run_strong_blkdeactivate();
|
|
||||||
* do_drop();
|
|
||||||
*/
|
|
||||||
|
|
||||||
return rv;
|
if (!config_val[0] || (config_val[0] == ' ')) {
|
||||||
|
log_error("invalid config value from %s", config_cmd);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Found lvmlockctl_kill_command: %s\n", config_val);
|
||||||
|
|
||||||
|
snprintf(kill_cmd, PATH_MAX, "%s %s", config_val, arg_vg_name);
|
||||||
|
|
||||||
|
pclose(fp);
|
||||||
|
return 0;
|
||||||
|
bad:
|
||||||
|
pclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns -1 on error, 0 on success. */
|
||||||
|
|
||||||
|
static int _run_kill_command(char *kill_cmd)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = system(kill_cmd);
|
||||||
|
|
||||||
|
if (!WEXITSTATUS(status))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_drop(void)
|
static int do_drop(void)
|
||||||
@ -555,7 +583,7 @@ static int do_drop(void)
|
|||||||
int result;
|
int result;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
syslog(LOG_WARNING, "Dropping locks for VG %s.", arg_vg_name);
|
log_sys_warn("Dropping locks for VG %s.", arg_vg_name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for misuse by looking for any active LVs in the VG
|
* Check for misuse by looking for any active LVs in the VG
|
||||||
@ -583,6 +611,84 @@ static int do_drop(void)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_kill(void)
|
||||||
|
{
|
||||||
|
char kill_cmd[PATH_MAX] = { 0 };
|
||||||
|
daemon_reply reply;
|
||||||
|
int no_kill_command = 0;
|
||||||
|
int result;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
log_sys_emerg("lvmlockd lost access to locks in VG %s.", arg_vg_name);
|
||||||
|
|
||||||
|
rv = _get_kill_command(kill_cmd);
|
||||||
|
if (rv < 0) {
|
||||||
|
log_sys_emerg("Immediately deactivate LVs in VG %s.", arg_vg_name);
|
||||||
|
log_sys_emerg("Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
|
||||||
|
no_kill_command = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It may not be strictly necessary to notify lvmlockd of the kill, but
|
||||||
|
* lvmlockd can use this information to avoid attempting any new lock
|
||||||
|
* requests in the VG (which would fail anyway), and can return an
|
||||||
|
* error indicating that the VG has been killed.
|
||||||
|
*/
|
||||||
|
_lvmlockd = lvmlockd_open(NULL);
|
||||||
|
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
|
||||||
|
log_error("Cannot connect to lvmlockd for kill_vg.");
|
||||||
|
goto run;
|
||||||
|
}
|
||||||
|
reply = _lvmlockd_send("kill_vg",
|
||||||
|
"cmd = %s", "lvmlockctl",
|
||||||
|
"pid = " FMTd64, (int64_t) getpid(),
|
||||||
|
"vg_name = %s", arg_vg_name,
|
||||||
|
NULL);
|
||||||
|
if (!_lvmlockd_result(reply, &result))
|
||||||
|
log_error("lvmlockd result %d kill_vg", result);
|
||||||
|
daemon_reply_destroy(reply);
|
||||||
|
lvmlockd_close(_lvmlockd);
|
||||||
|
|
||||||
|
run:
|
||||||
|
if (no_kill_command)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
rv = _run_kill_command(kill_cmd);
|
||||||
|
if (rv < 0) {
|
||||||
|
log_sys_emerg("Failed to run VG %s kill command %s", arg_vg_name, kill_cmd);
|
||||||
|
log_sys_emerg("Immediately deactivate LVs in VG %s.", arg_vg_name);
|
||||||
|
log_sys_emerg("Once VG is unused, run lvmlockctl --drop %s.", arg_vg_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_sys_warn("Successful VG %s kill command %s", arg_vg_name, kill_cmd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If kill command was successfully, call do_drop(). (The drop step
|
||||||
|
* may not always be necessary if the lvm commands run while shutting
|
||||||
|
* things down release all the leases.)
|
||||||
|
*/
|
||||||
|
rv = 0;
|
||||||
|
_lvmlockd = lvmlockd_open(NULL);
|
||||||
|
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
|
||||||
|
log_sys_emerg("Failed to connect to lvmlockd to drop locks in VG %s.", arg_vg_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
reply = _lvmlockd_send("drop_vg",
|
||||||
|
"cmd = %s", "lvmlockctl",
|
||||||
|
"pid = " FMTd64, (int64_t) getpid(),
|
||||||
|
"vg_name = %s", arg_vg_name,
|
||||||
|
NULL);
|
||||||
|
if (!_lvmlockd_result(reply, &result)) {
|
||||||
|
log_sys_emerg("Failed to drop locks in VG %s", arg_vg_name);
|
||||||
|
rv = result;
|
||||||
|
}
|
||||||
|
daemon_reply_destroy(reply);
|
||||||
|
lvmlockd_close(_lvmlockd);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
static void print_usage(void)
|
static void print_usage(void)
|
||||||
{
|
{
|
||||||
printf("lvmlockctl options\n");
|
printf("lvmlockctl options\n");
|
||||||
@ -600,7 +706,7 @@ static void print_usage(void)
|
|||||||
printf("--force | -f 0|1>\n");
|
printf("--force | -f 0|1>\n");
|
||||||
printf(" Force option for other commands.\n");
|
printf(" Force option for other commands.\n");
|
||||||
printf("--kill | -k <vgname>\n");
|
printf("--kill | -k <vgname>\n");
|
||||||
printf(" Kill access to the VG when sanlock cannot renew lease.\n");
|
printf(" Kill access to the VG locks are lost (see lvmlockctl_kill_command).\n");
|
||||||
printf("--drop | -r <vgname>\n");
|
printf("--drop | -r <vgname>\n");
|
||||||
printf(" Clear locks for the VG when it is unused after kill (-k).\n");
|
printf(" Clear locks for the VG when it is unused after kill (-k).\n");
|
||||||
printf("--gl-enable | -E <vgname>\n");
|
printf("--gl-enable | -E <vgname>\n");
|
||||||
@ -609,6 +715,8 @@ static void print_usage(void)
|
|||||||
printf(" Tell lvmlockd to disable the global lock in a sanlock VG.\n");
|
printf(" Tell lvmlockd to disable the global lock in a sanlock VG.\n");
|
||||||
printf("--stop-lockspaces | -S\n");
|
printf("--stop-lockspaces | -S\n");
|
||||||
printf(" Stop all lockspaces.\n");
|
printf(" Stop all lockspaces.\n");
|
||||||
|
printf("--stderr | -e\n");
|
||||||
|
printf(" Send kill and drop messages to stderr instead of syslog\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_options(int argc, char *argv[])
|
static int read_options(int argc, char *argv[])
|
||||||
@ -628,6 +736,7 @@ static int read_options(int argc, char *argv[])
|
|||||||
{"gl-enable", required_argument, 0, 'E' },
|
{"gl-enable", required_argument, 0, 'E' },
|
||||||
{"gl-disable", required_argument, 0, 'D' },
|
{"gl-disable", required_argument, 0, 'D' },
|
||||||
{"stop-lockspaces", no_argument, 0, 'S' },
|
{"stop-lockspaces", no_argument, 0, 'S' },
|
||||||
|
{"stderr", no_argument, 0, 'e' },
|
||||||
{0, 0, 0, 0 }
|
{0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -637,7 +746,7 @@ static int read_options(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
c = getopt_long(argc, argv, "hqidE:D:w:k:r:S", long_options, &option_index);
|
c = getopt_long(argc, argv, "hqidE:D:w:k:r:Se", long_options, &option_index);
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -680,6 +789,9 @@ static int read_options(int argc, char *argv[])
|
|||||||
case 'S':
|
case 'S':
|
||||||
stop_lockspaces = 1;
|
stop_lockspaces = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'e':
|
||||||
|
use_stderr = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
print_usage();
|
print_usage();
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -698,8 +810,12 @@ int main(int argc, char **argv)
|
|||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
_lvmlockd = lvmlockd_open(NULL);
|
/* do_kill handles lvmlockd connections itself */
|
||||||
|
if (kill_vg)
|
||||||
|
return do_kill();
|
||||||
|
|
||||||
|
|
||||||
|
_lvmlockd = lvmlockd_open(NULL);
|
||||||
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
|
if (_lvmlockd.socket_fd < 0 || _lvmlockd.error) {
|
||||||
log_error("Cannot connect to lvmlockd.");
|
log_error("Cannot connect to lvmlockd.");
|
||||||
return -1;
|
return -1;
|
||||||
@ -720,11 +836,6 @@ int main(int argc, char **argv)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kill_vg) {
|
|
||||||
rv = do_kill();
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drop_vg) {
|
if (drop_vg) {
|
||||||
rv = do_drop();
|
rv = do_drop();
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -586,6 +586,9 @@
|
|||||||
/* Path to lvm binary. */
|
/* Path to lvm binary. */
|
||||||
#undef LVM_PATH
|
#undef LVM_PATH
|
||||||
|
|
||||||
|
/* Path to lvm binary dir. */
|
||||||
|
#undef LVM_DIR
|
||||||
|
|
||||||
/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
|
/* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
|
||||||
*/
|
*/
|
||||||
#undef MAJOR_IN_MKDEV
|
#undef MAJOR_IN_MKDEV
|
||||||
|
@ -1152,6 +1152,15 @@ cfg(global_sanlock_lv_extend_CFG, "sanlock_lv_extend", global_CFG_SECTION, CFG_D
|
|||||||
"and can cause lvcreate to fail. Applicable only if LVM is compiled\n"
|
"and can cause lvcreate to fail. Applicable only if LVM is compiled\n"
|
||||||
"with lockd support\n")
|
"with lockd support\n")
|
||||||
|
|
||||||
|
cfg(global_lvmlockctl_kill_command_CFG, "lvmlockctl_kill_command", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, "", vsn(2, 3, 12), NULL, 0, NULL,
|
||||||
|
"The command that lvmlockctl --kill should use to force LVs offline.\n"
|
||||||
|
"The lvmlockctl --kill command is run when a shared VG has lost\n"
|
||||||
|
"access to locks (e.g. when sanlock has lost access to storage.)\n"
|
||||||
|
"An empty string means that there will be no automatic attempt by\n"
|
||||||
|
"lvmlockctl --kill to forcibly shut down LVs in the VG, and the user\n"
|
||||||
|
"can manually intervene as described in lvmlockd(8).\n"
|
||||||
|
"The VG name will be appended to the command specified here.\n")
|
||||||
|
|
||||||
cfg(global_thin_check_executable_CFG, "thin_check_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, THIN_CHECK_CMD, vsn(2, 2, 94), "@THIN_CHECK_CMD@", 0, NULL,
|
cfg(global_thin_check_executable_CFG, "thin_check_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, THIN_CHECK_CMD, vsn(2, 2, 94), "@THIN_CHECK_CMD@", 0, NULL,
|
||||||
"The full path to the thin_check command.\n"
|
"The full path to the thin_check command.\n"
|
||||||
"LVM uses this command to check that a thin metadata device is in a\n"
|
"LVM uses this command to check that a thin metadata device is in a\n"
|
||||||
|
@ -65,17 +65,21 @@ and prints it.
|
|||||||
.SS kill
|
.SS kill
|
||||||
|
|
||||||
This is run by sanlock when it loses access to the storage holding leases
|
This is run by sanlock when it loses access to the storage holding leases
|
||||||
for a VG. It currently emits a syslog message stating that the VG must
|
for a VG. It runs the command specified in lvm.conf
|
||||||
be immediately deactivated. In the future it may automatically attempt to
|
lvmlockctl_kill_command to deactivate LVs in the VG. If the specified
|
||||||
forcibly deactivate the VG. For more, see
|
command is successful, locks will be dropped for the VG in lvmlockd
|
||||||
|
(the equivalent of lvmlockctl --drop will be run.) If no command
|
||||||
|
is specified, or the command fails, then the user must intervene
|
||||||
|
to forcefully deactivate LVs in the VG, and if successful, run
|
||||||
|
lvmlockctl --drop. For more, see
|
||||||
.BR lvmlockd (8).
|
.BR lvmlockd (8).
|
||||||
|
|
||||||
.SS drop
|
.SS drop
|
||||||
|
|
||||||
This should only be run after a VG has been successfully deactivated
|
This should only be run after a VG has been successfully deactivated
|
||||||
following an lvmlockctl --kill command. It clears the stale lockspace
|
following an lvmlockctl --kill command. It clears the stale lockspace
|
||||||
from lvmlockd. In the future, this may become automatic along with an
|
from lvmlockd. When lvmlockctl_kill_command is used, the --kill
|
||||||
automatic handling of --kill. For more, see
|
command may run drop automatically. For more, see
|
||||||
.BR lvmlockd (8).
|
.BR lvmlockd (8).
|
||||||
|
|
||||||
.SS gl-enable
|
.SS gl-enable
|
||||||
|
Loading…
Reference in New Issue
Block a user