mirror of
git://sourceware.org/git/lvm2.git
synced 2025-08-19 17:49:28 +03:00
Compare commits
4 Commits
v2_03_26
...
dev-dct-pv
Author | SHA1 | Date | |
---|---|---|---|
5e48b04561 | |||
3e893b9b09 | |||
c06d5fe28e | |||
4f1957ee50 |
44
configure.ac
44
configure.ac
@ -785,39 +785,6 @@ AC_ARG_WITH(default-run-dir,
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_RUN_DIR, ["$DEFAULT_RUN_DIR"],
|
||||
[Default LVM run directory.])
|
||||
|
||||
################################################################################
|
||||
dnl -- Build cluster mirror log daemon
|
||||
AC_MSG_CHECKING(whether to build cluster mirror log daemon)
|
||||
AC_ARG_ENABLE(cmirrord,
|
||||
AS_HELP_STRING([--enable-cmirrord],
|
||||
[enable the cluster mirror log daemon]),
|
||||
CMIRRORD=$enableval, CMIRRORD=no)
|
||||
AC_MSG_RESULT($CMIRRORD)
|
||||
|
||||
BUILD_CMIRRORD=$CMIRRORD
|
||||
|
||||
################################################################################
|
||||
dnl -- cmirrord pidfile
|
||||
if test "$BUILD_CMIRRORD" = yes; then
|
||||
AC_ARG_WITH(cmirrord-pidfile,
|
||||
AS_HELP_STRING([--with-cmirrord-pidfile=PATH],
|
||||
[cmirrord pidfile [PID_DIR/cmirrord.pid]]),
|
||||
CMIRRORD_PIDFILE=$withval,
|
||||
CMIRRORD_PIDFILE="$DEFAULT_PID_DIR/cmirrord.pid")
|
||||
AC_DEFINE_UNQUOTED(CMIRRORD_PIDFILE, ["$CMIRRORD_PIDFILE"],
|
||||
[Path to cmirrord pidfile.])
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Look for corosync libraries if required.
|
||||
if [[ "$BUILD_CMIRRORD" = yes ]]; then
|
||||
pkg_config_init
|
||||
|
||||
if test "$HAVE_CPG" != yes; then
|
||||
PKG_CHECK_MODULES(CPG, libcpg)
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
dnl -- Enable debugging
|
||||
AC_MSG_CHECKING(whether to enable debugging)
|
||||
@ -1672,10 +1639,6 @@ fi
|
||||
AC_MSG_CHECKING(whether to enable editline)
|
||||
AC_MSG_RESULT($EDITLINE)
|
||||
|
||||
if test "$BUILD_CMIRRORD" = yes; then
|
||||
AC_CHECK_FUNCS(atexit,,hard_bailout)
|
||||
fi
|
||||
|
||||
if test "$BUILD_LVMLOCKD" = yes; then
|
||||
AS_IF([test "$HAVE_REALTIME" != yes], [AC_MSG_ERROR([Realtime clock support is mandatory for lvmlockd.])])
|
||||
AC_CHECK_FUNCS(strtoull,,hard_bailout)
|
||||
@ -1851,7 +1814,6 @@ AC_ARG_VAR([UDEV_LIBS], [linker flags for udev])
|
||||
################################################################################
|
||||
AC_SUBST(AWK)
|
||||
AC_SUBST(BLKID_PC)
|
||||
AC_SUBST(BUILD_CMIRRORD)
|
||||
AC_SUBST(BUILD_DMEVENTD)
|
||||
AC_SUBST(BUILD_LVMDBUSD)
|
||||
AC_SUBST(BUILD_LVMPOLLD)
|
||||
@ -1984,7 +1946,6 @@ AC_SUBST(WRITE_INSTALL)
|
||||
AC_SUBST(DMEVENTD_PIDFILE)
|
||||
AC_SUBST(LVMPOLLD_PIDFILE)
|
||||
AC_SUBST(LVMLOCKD_PIDFILE)
|
||||
AC_SUBST(CMIRRORD_PIDFILE)
|
||||
AC_SUBST(interface)
|
||||
AC_SUBST(kerneldir)
|
||||
AC_SUBST(missingkernel)
|
||||
@ -2006,7 +1967,6 @@ Makefile
|
||||
make.tmpl
|
||||
libdm/make.tmpl
|
||||
daemons/Makefile
|
||||
daemons/cmirrord/Makefile
|
||||
daemons/dmeventd/Makefile
|
||||
daemons/dmeventd/libdevmapper-event.pc
|
||||
daemons/dmeventd/plugins/Makefile
|
||||
@ -2040,14 +2000,14 @@ libdm/libdevmapper.pc
|
||||
man/Makefile
|
||||
po/Makefile
|
||||
scripts/lvm2-pvscan.service
|
||||
scripts/lvm-activate-vgs-main.service
|
||||
scripts/lvm-activate-vgs-last.service
|
||||
scripts/blkdeactivate.sh
|
||||
scripts/blk_availability_init_red_hat
|
||||
scripts/blk_availability_systemd_red_hat.service
|
||||
scripts/cmirrord_init_red_hat
|
||||
scripts/com.redhat.lvmdbus1.service
|
||||
scripts/dm_event_systemd_red_hat.service
|
||||
scripts/dm_event_systemd_red_hat.socket
|
||||
scripts/lvm2_cmirrord_systemd_red_hat.service
|
||||
scripts/lvm2_lvmdbusd_systemd_red_hat.service
|
||||
scripts/lvm2_lvmpolld_init_red_hat
|
||||
scripts/lvm2_lvmpolld_systemd_red_hat.service
|
||||
|
@ -183,6 +183,7 @@ struct cmd_context {
|
||||
unsigned enable_hints:1; /* hints are enabled for cmds in general */
|
||||
unsigned use_hints:1; /* if hints are enabled this cmd can use them */
|
||||
unsigned pvscan_recreate_hints:1; /* enable special case hint handling for pvscan --cache */
|
||||
unsigned hints_pvs_online:1; /* hints="pvs_online" */
|
||||
unsigned scan_lvs:1;
|
||||
unsigned wipe_outdated_pvs:1;
|
||||
unsigned enable_devices_list:1; /* command is using --devices option */
|
||||
|
@ -1130,6 +1130,18 @@ cfg(global_event_activation_CFG, "event_activation", global_CFG_SECTION, CFG_DEF
|
||||
"See the --setautoactivation option or the auto_activation_volume_list\n"
|
||||
"setting to configure autoactivation for specific VGs or LVs.\n")
|
||||
|
||||
cfg_array(global_event_activation_options_CFG, "event_activation_options", global_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_COMMENTED, CFG_TYPE_STRING, DEFAULT_EVENT_ACTIVATION_OPTIONS, vsn(2, 3, 14), NULL, 0, NULL,
|
||||
"Set event activation options.\n"
|
||||
"service_to_event: begin with fixed activation services,\n"
|
||||
"then switch to event based activation.\n"
|
||||
"event_only: only use event based activation.\n"
|
||||
"service_only: only use fixed activation services.\n"
|
||||
"(This is equivalent to event_activation=0.)\n"
|
||||
"Autoactivation commands should set --eventactivation service|event\n"
|
||||
"to indicate if they are performing service or event activation.\n"
|
||||
"An autoactivation command may then be skipped according to the\n"
|
||||
"value of this setting.\n")
|
||||
|
||||
cfg(global_use_lvmetad_CFG, "use_lvmetad", global_CFG_SECTION, CFG_DEFAULT_COMMENTED, CFG_TYPE_BOOL, 0, vsn(2, 2, 93), 0, vsn(2, 3, 0), NULL,
|
||||
NULL)
|
||||
|
||||
|
@ -328,4 +328,11 @@
|
||||
|
||||
#define DEFAULT_WWIDS_FILE "/etc/multipath/wwids"
|
||||
|
||||
#define DEFAULT_EVENT_ACTIVATION_OPTION1 "service_to_event"
|
||||
#define DEFAULT_EVENT_ACTIVATION_OPTIONS "#S" DEFAULT_EVENT_ACTIVATION_OPTION1
|
||||
|
||||
#define PVS_ONLINE_DIR DEFAULT_RUN_DIR "/pvs_online"
|
||||
#define VGS_ONLINE_DIR DEFAULT_RUN_DIR "/vgs_online"
|
||||
#define PVS_LOOKUP_DIR DEFAULT_RUN_DIR "/pvs_lookup"
|
||||
|
||||
#endif /* _LVM_DEFAULTS_H */
|
||||
|
@ -1831,7 +1831,7 @@ int setup_devices_file(struct cmd_context *cmd)
|
||||
* Add all system devices to dev-cache, and attempt to
|
||||
* match all devices_file entries to dev-cache entries.
|
||||
*/
|
||||
static int _setup_devices(struct cmd_context *cmd, int no_file_match)
|
||||
int setup_devices(struct cmd_context *cmd)
|
||||
{
|
||||
int file_exists;
|
||||
int lock_mode = 0;
|
||||
@ -1958,13 +1958,6 @@ static int _setup_devices(struct cmd_context *cmd, int no_file_match)
|
||||
*/
|
||||
dev_cache_scan(cmd);
|
||||
|
||||
/*
|
||||
* The caller uses "no_file_match" if it wants to match specific devs
|
||||
* itself, instead of matching everything in device_ids_match.
|
||||
*/
|
||||
if (no_file_match && cmd->enable_devices_file)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Match entries from cmd->use_devices with device structs in dev-cache.
|
||||
*/
|
||||
@ -1973,16 +1966,6 @@ static int _setup_devices(struct cmd_context *cmd, int no_file_match)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int setup_devices(struct cmd_context *cmd)
|
||||
{
|
||||
return _setup_devices(cmd, 0);
|
||||
}
|
||||
|
||||
int setup_devices_no_file_match(struct cmd_context *cmd)
|
||||
{
|
||||
return _setup_devices(cmd, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* The alternative to setup_devices() when the command is interested
|
||||
* in using only one PV.
|
||||
@ -2051,3 +2034,188 @@ int setup_device(struct cmd_context *cmd, const char *devname)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* pvscan --cache is specialized/optimized to look only at command args,
|
||||
* so this just sets up the devices file, then individual devices are
|
||||
* added to dev-cache and matched with device_ids later in pvscan.
|
||||
*/
|
||||
|
||||
int setup_devices_for_pvscan_cache(struct cmd_context *cmd)
|
||||
{
|
||||
if (cmd->enable_devices_list) {
|
||||
if (!_setup_devices_list(cmd))
|
||||
return_0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!setup_devices_file(cmd))
|
||||
return_0;
|
||||
|
||||
if (!cmd->enable_devices_file)
|
||||
return 1;
|
||||
|
||||
if (!devices_file_exists(cmd)) {
|
||||
log_debug("Devices file not found, ignoring.");
|
||||
cmd->enable_devices_file = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!lock_devices_file(cmd, LOCK_SH)) {
|
||||
log_error("Failed to lock the devices file to read.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!device_ids_read(cmd)) {
|
||||
log_error("Failed to read the devices file.");
|
||||
unlock_devices_file(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unlock_devices_file(cmd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Get a device name from a devno. */
|
||||
|
||||
static char *_get_devname_from_devno(struct cmd_context *cmd, dev_t devno)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char devname[PATH_MAX];
|
||||
char namebuf[NAME_LEN];
|
||||
char line[1024];
|
||||
int major = MAJOR(devno);
|
||||
int minor = MINOR(devno);
|
||||
int line_major;
|
||||
int line_minor;
|
||||
uint64_t line_blocks;
|
||||
DIR *dir;
|
||||
struct dirent *dirent;
|
||||
FILE *fp;
|
||||
|
||||
/*
|
||||
* $ ls /sys/dev/block/8:0/device/block/
|
||||
* sda
|
||||
*/
|
||||
if (major_is_scsi_device(cmd->dev_types, major)) {
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/device/block",
|
||||
dm_sysfs_dir(), major, minor) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(dir = opendir(path)))
|
||||
return NULL;
|
||||
|
||||
while ((dirent = readdir(dir))) {
|
||||
if (dirent->d_name[0] == '.')
|
||||
continue;
|
||||
if (dm_snprintf(devname, sizeof(devname), "/dev/%s", dirent->d_name) < 0) {
|
||||
devname[0] = '\0';
|
||||
stack;
|
||||
}
|
||||
break;
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
if (devname[0]) {
|
||||
log_debug("Found %s for %d:%d from sys", devname, major, minor);
|
||||
return _strdup(devname);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* $ cat /sys/dev/block/253:3/dm/name
|
||||
* mpatha
|
||||
*/
|
||||
if (major == cmd->dev_types->device_mapper_major) {
|
||||
if (dm_snprintf(path, sizeof(path), "%sdev/block/%d:%d/dm/name",
|
||||
dm_sysfs_dir(), major, minor) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!get_sysfs_value(path, namebuf, sizeof(namebuf), 0))
|
||||
return NULL;
|
||||
|
||||
if (dm_snprintf(devname, sizeof(devname), "/dev/mapper/%s", namebuf) < 0) {
|
||||
devname[0] = '\0';
|
||||
stack;
|
||||
}
|
||||
|
||||
if (devname[0]) {
|
||||
log_debug("Found %s for %d:%d from sys", devname, major, minor);
|
||||
return _strdup(devname);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* /proc/partitions lists
|
||||
* major minor #blocks name
|
||||
*/
|
||||
|
||||
if (!(fp = fopen("/proc/partitions", "r")))
|
||||
return NULL;
|
||||
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
if (sscanf(line, "%u %u %llu %s", &line_major, &line_minor, (unsigned long long *)&line_blocks, namebuf) != 4)
|
||||
continue;
|
||||
if (line_major != major)
|
||||
continue;
|
||||
if (line_minor != minor)
|
||||
continue;
|
||||
|
||||
if (dm_snprintf(devname, sizeof(devname), "/dev/%s", namebuf) < 0) {
|
||||
devname[0] = '\0';
|
||||
stack;
|
||||
}
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
if (devname[0]) {
|
||||
log_debug("Found %s for %d:%d from proc", devname, major, minor);
|
||||
return _strdup(devname);
|
||||
}
|
||||
|
||||
/*
|
||||
* If necessary, this could continue searching by stat'ing /dev entries.
|
||||
*/
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int setup_devname_in_dev_cache(struct cmd_context *cmd, const char *devname)
|
||||
{
|
||||
struct stat buf;
|
||||
struct device *dev;
|
||||
|
||||
if (stat(devname, &buf) < 0) {
|
||||
log_error("Cannot access device %s.", devname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISBLK(buf.st_mode)) {
|
||||
log_error("Invaild device type %s.", devname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!_insert_dev(devname, buf.st_rdev))
|
||||
return_0;
|
||||
|
||||
if (!(dev = (struct device *) dm_hash_lookup(_cache.names, devname)))
|
||||
return_0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int setup_devno_in_dev_cache(struct cmd_context *cmd, dev_t devno)
|
||||
{
|
||||
const char *devname;
|
||||
|
||||
if (!(devname = _get_devname_from_devno(cmd, devno)))
|
||||
return_0;
|
||||
|
||||
return setup_devname_in_dev_cache(cmd, devname);
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,11 @@ int get_dm_uuid_from_sysfs(char *buf, size_t buf_size, int major, int minor);
|
||||
|
||||
int setup_devices_file(struct cmd_context *cmd);
|
||||
int setup_devices(struct cmd_context *cmd);
|
||||
int setup_devices_no_file_match(struct cmd_context *cmd);
|
||||
int setup_device(struct cmd_context *cmd, const char *devname);
|
||||
|
||||
/* Normal device setup functions are split up for pvscan optimization. */
|
||||
int setup_devices_for_pvscan_cache(struct cmd_context *cmd);
|
||||
int setup_devname_in_dev_cache(struct cmd_context *cmd, const char *devname);
|
||||
int setup_devno_in_dev_cache(struct cmd_context *cmd, dev_t devno);
|
||||
|
||||
#endif
|
||||
|
@ -1533,6 +1533,22 @@ int device_ids_match_dev(struct cmd_context *cmd, struct device *dev)
|
||||
* passes the filter.
|
||||
*/
|
||||
|
||||
void device_ids_match_device_list(struct cmd_context *cmd)
|
||||
{
|
||||
struct dev_use *du;
|
||||
|
||||
dm_list_iterate_items(du, &cmd->use_devices) {
|
||||
if (du->dev)
|
||||
continue;
|
||||
if (!(du->dev = dev_cache_get(cmd, du->devname, NULL))) {
|
||||
log_warn("Device not found for %s.", du->devname);
|
||||
} else {
|
||||
/* Should we set dev->id? Which idtype? Use --deviceidtype? */
|
||||
du->dev->flags |= DEV_MATCHED_USE_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void device_ids_match(struct cmd_context *cmd)
|
||||
{
|
||||
struct dev_iter *iter;
|
||||
@ -1540,16 +1556,7 @@ void device_ids_match(struct cmd_context *cmd)
|
||||
struct device *dev;
|
||||
|
||||
if (cmd->enable_devices_list) {
|
||||
dm_list_iterate_items(du, &cmd->use_devices) {
|
||||
if (du->dev)
|
||||
continue;
|
||||
if (!(du->dev = dev_cache_get(cmd, du->devname, NULL))) {
|
||||
log_warn("Device not found for %s.", du->devname);
|
||||
} else {
|
||||
/* Should we set dev->id? Which idtype? Use --deviceidtype? */
|
||||
du->dev->flags |= DEV_MATCHED_USE_ID;
|
||||
}
|
||||
}
|
||||
device_ids_match_device_list(cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ int device_id_add(struct cmd_context *cmd, struct device *dev, const char *pvid,
|
||||
void device_id_pvremove(struct cmd_context *cmd, struct device *dev);
|
||||
void device_ids_match(struct cmd_context *cmd);
|
||||
int device_ids_match_dev(struct cmd_context *cmd, struct device *dev);
|
||||
void device_ids_match_device_list(struct cmd_context *cmd);
|
||||
void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs, int *device_ids_invalid, int noupdate);
|
||||
int device_ids_version_unchanged(struct cmd_context *cmd);
|
||||
void device_ids_find_renamed_devs(struct cmd_context *cmd, struct dm_list *dev_list, int *search_count, int noupdate);
|
||||
|
@ -150,11 +150,14 @@
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
int online_pvid_file_read(char *path, int *major, int *minor, char *vgname);
|
||||
|
||||
static const char *_hints_file = DEFAULT_RUN_DIR "/hints";
|
||||
static const char *_nohints_file = DEFAULT_RUN_DIR "/nohints";
|
||||
static const char *_newhints_file = DEFAULT_RUN_DIR "/newhints";
|
||||
@ -1279,6 +1282,109 @@ check:
|
||||
free(name);
|
||||
}
|
||||
|
||||
static int _get_hints_from_pvs_online(struct cmd_context *cmd, struct dm_list *hints_out,
|
||||
struct dm_list *devs_in, struct dm_list *devs_out)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char file_vgname[NAME_LEN];
|
||||
struct dm_list hints_list;
|
||||
struct hint file_hint;
|
||||
struct hint *alloc_hint;
|
||||
struct hint *hint, *hint2;
|
||||
struct device_list *devl, *devl2;
|
||||
int file_major, file_minor;
|
||||
int found = 0;
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
char *vgname = NULL;
|
||||
char *pvid;
|
||||
|
||||
dm_list_init(&hints_list);
|
||||
|
||||
if (!(dir = opendir(PVS_ONLINE_DIR)))
|
||||
return 0;
|
||||
|
||||
while ((de = readdir(dir))) {
|
||||
if (de->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
pvid = de->d_name;
|
||||
|
||||
if (strlen(pvid) != ID_LEN) /* 32 */
|
||||
continue;
|
||||
|
||||
memset(path, 0, sizeof(path));
|
||||
snprintf(path, sizeof(path), "%s/%s", PVS_ONLINE_DIR, pvid);
|
||||
|
||||
memset(&file_hint, 0, sizeof(file_hint));
|
||||
memset(file_vgname, 0, sizeof(file_vgname));
|
||||
file_major = 0;
|
||||
file_minor = 0;
|
||||
|
||||
if (!online_pvid_file_read(path, &file_major, &file_minor, file_vgname))
|
||||
continue;
|
||||
|
||||
if (!dm_strncpy(file_hint.pvid, pvid, sizeof(file_hint.pvid)))
|
||||
continue;
|
||||
|
||||
file_hint.devt = makedev(file_major, file_minor);
|
||||
|
||||
if (file_vgname[0] && validate_name(file_vgname)) {
|
||||
if (!dm_strncpy(file_hint.vgname, file_vgname, sizeof(file_hint.vgname)))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(alloc_hint = malloc(sizeof(struct hint))))
|
||||
continue;
|
||||
|
||||
memcpy(alloc_hint, &file_hint, sizeof(struct hint));
|
||||
|
||||
log_debug("add hint %s %d:%d %s from pvs_online", file_hint.pvid, file_major, file_minor, file_vgname);
|
||||
dm_list_add(&hints_list, &alloc_hint->list);
|
||||
found++;
|
||||
}
|
||||
|
||||
if (closedir(dir))
|
||||
stack;
|
||||
|
||||
log_debug("accept hints found %d from pvs_online", found);
|
||||
|
||||
_get_single_vgname_cmd_arg(cmd, &hints_list, &vgname);
|
||||
|
||||
/*
|
||||
* apply_hints equivalent, move devs from devs_in to devs_out if
|
||||
* their devno matches the devno of a hint (and if the hint matches
|
||||
* the vgname when a vgname is present.)
|
||||
*/
|
||||
dm_list_iterate_items_safe(devl, devl2, devs_in) {
|
||||
dm_list_iterate_items_safe(hint, hint2, &hints_list) {
|
||||
if ((MAJOR(devl->dev->dev) == MAJOR(hint->devt)) &&
|
||||
(MINOR(devl->dev->dev) == MINOR(hint->devt))) {
|
||||
|
||||
if (vgname && hint->vgname[0] && strcmp(vgname, hint->vgname))
|
||||
goto next_dev;
|
||||
|
||||
snprintf(hint->name, sizeof(hint->name), "%s", dev_name(devl->dev));
|
||||
hint->chosen = 1;
|
||||
|
||||
dm_list_del(&devl->list);
|
||||
dm_list_add(devs_out, &devl->list);
|
||||
}
|
||||
}
|
||||
next_dev:
|
||||
;
|
||||
}
|
||||
|
||||
log_debug("applied hints using %d other %d vgname %s from pvs_online",
|
||||
dm_list_size(devs_out), dm_list_size(devs_in), vgname ?: "");
|
||||
|
||||
dm_list_splice(hints_out, &hints_list);
|
||||
|
||||
free(vgname);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0: no hints are used.
|
||||
* . newhints is set if this command should create new hints after scan
|
||||
@ -1320,6 +1426,15 @@ int get_hints(struct cmd_context *cmd, struct dm_list *hints_out, int *newhints,
|
||||
if (!cmd->use_hints)
|
||||
return 0;
|
||||
|
||||
/* hints = "pvs_online" */
|
||||
if (cmd->hints_pvs_online) {
|
||||
if (!_get_hints_from_pvs_online(cmd, &hints_list, devs_in, devs_out)) {
|
||||
log_debug("get_hints: pvs_online failed");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if another command created the nohints file to prevent us from
|
||||
* using hints.
|
||||
|
@ -1130,6 +1130,9 @@ int label_scan(struct cmd_context *cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log_debug_devs("Filtering devices to scan done (nodata)");
|
||||
|
||||
cmd->filter_nodata_only = 0;
|
||||
|
||||
dm_list_iterate_items(devl, &all_devs)
|
||||
|
@ -15,9 +15,6 @@ srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = @top_builddir@
|
||||
|
||||
SOURCES = lvm2_activation_generator_systemd_red_hat.c
|
||||
TARGETS = lvm2_activation_generator_systemd_red_hat
|
||||
|
||||
include $(top_builddir)/make.tmpl
|
||||
|
||||
ifeq ("@BUILD_DMEVENTD@", "yes")
|
||||
@ -66,7 +63,7 @@ install_initscripts:
|
||||
@echo " [INSTALL] initscripts"
|
||||
$(Q) $(INSTALL_DIR) $(initdir)
|
||||
ifeq ("@BUILD_DMEVENTD@", "yes")
|
||||
$(Q) $(INSTALL_SCRIPT) lvm2_monitoring_init_red_hat $(initdir)/lvm2-monitor
|
||||
$(Q) $(INSTALL_SCRIPT) lvm2_monitoring_init_red_hat $(initdir)/lvm-monitor
|
||||
endif
|
||||
ifeq ("@BUILD_LVMPOLLD@", "yes")
|
||||
$(Q) $(INSTALL_SCRIPT) lvm2_lvmpolld_init_red_hat $(initdir)/lvm2-lvmpolld
|
||||
@ -78,24 +75,15 @@ ifeq ("@BLKDEACTIVATE@", "yes")
|
||||
$(Q) $(INSTALL_SCRIPT) blk_availability_init_red_hat $(initdir)/blk-availability
|
||||
endif
|
||||
|
||||
CFLAGS_lvm2_activation_generator_systemd_red_hat.o += $(EXTRA_EXEC_CFLAGS)
|
||||
|
||||
lvm2_activation_generator_systemd_red_hat: $(OBJECTS) $(LVMINTERNAL_LIBS)
|
||||
@echo " [CC] $@"
|
||||
$(Q) $(CC) -o $@ $(OBJECTS) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) $(LVMINTERNAL_LIBS) $(LIBS)
|
||||
|
||||
install_systemd_generators:
|
||||
@echo " [INSTALL] systemd_generators"
|
||||
$(Q) $(INSTALL_DIR) $(systemd_generator_dir)
|
||||
$(Q) $(INSTALL_PROGRAM) lvm2_activation_generator_systemd_red_hat $(systemd_generator_dir)/lvm2-activation-generator
|
||||
|
||||
install_systemd_units: install_dbus_service
|
||||
@echo " [INSTALL] systemd_units"
|
||||
$(Q) $(INSTALL_DIR) $(systemd_unit_dir)
|
||||
$(Q) $(INSTALL_DATA) lvm-activate-vgs-main.service $(systemd_unit_dir)/lvm-activate-vgs-main.service
|
||||
$(Q) $(INSTALL_DATA) lvm-activate-vgs-last.service $(systemd_unit_dir)/lvm-activate-vgs-last.service
|
||||
ifeq ("@BUILD_DMEVENTD@", "yes")
|
||||
$(Q) $(INSTALL_DATA) dm_event_systemd_red_hat.socket $(systemd_unit_dir)/dm-event.socket
|
||||
$(Q) $(INSTALL_DATA) dm_event_systemd_red_hat.service $(systemd_unit_dir)/dm-event.service
|
||||
$(Q) $(INSTALL_DATA) lvm2_monitoring_systemd_red_hat.service $(systemd_unit_dir)/lvm2-monitor.service
|
||||
$(Q) $(INSTALL_DATA) lvm2_monitoring_systemd_red_hat.service $(systemd_unit_dir)/lvm-monitor.service
|
||||
endif
|
||||
ifeq ("@BLKDEACTIVATE@", "yes")
|
||||
$(Q) $(INSTALL_DATA) blk_availability_systemd_red_hat.service $(systemd_unit_dir)/blk-availability.service
|
||||
@ -155,7 +143,9 @@ DISTCLEAN_TARGETS += \
|
||||
lvm2_monitoring_init_red_hat \
|
||||
lvm2_monitoring_systemd_red_hat.service \
|
||||
lvm2_pvscan_systemd_red_hat@.service \
|
||||
lvm2_tmpfiles_red_hat.conf
|
||||
lvm2_tmpfiles_red_hat.conf \
|
||||
lvm-activate-vgs-main.service \
|
||||
lvm-activate-vgs-last.service
|
||||
|
||||
# Remove ancient files
|
||||
DISTCLEAN_TARGETS += \
|
||||
|
@ -1,7 +1,7 @@
|
||||
[Unit]
|
||||
Description=Availability of block devices
|
||||
Before=shutdown.target
|
||||
After=lvm2-activation.service iscsi-shutdown.service iscsi.service iscsid.service fcoe.service rbdmap.service
|
||||
After=lvm-activate-vgs-main.service lvm-activate-vgs-last.service iscsi-shutdown.service iscsi.service iscsid.service fcoe.service rbdmap.service
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target
|
||||
|
||||
|
22
scripts/lvm-activate-vgs-last.service.in
Normal file
22
scripts/lvm-activate-vgs-last.service.in
Normal file
@ -0,0 +1,22 @@
|
||||
[Unit]
|
||||
Description=Activate LVM Volume Groups (last)
|
||||
Documentation=man:vgchange(8)
|
||||
Wants=systemd-udev-settle.service
|
||||
After=lvm-activate-vgs-main.service systemd-udev-settle.service multipathd.service cryptsetup.target
|
||||
Before=local-fs-pre.target shutdown.target
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target
|
||||
|
||||
# "--eventactivation service" tells vgchange it is being called
|
||||
# from an activation service, so it will do nothing if
|
||||
# lvm.conf event_activation_options = "event_only".
|
||||
# "--eventactivation on" tells vgchange to enable event-based
|
||||
# pvscan activations by creating /run/lvm/event-activation-on.
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=@SBINDIR@/lvm vgchange -aay --nohints --vgonline --eventactivation service,on
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=sysinit.target
|
19
scripts/lvm-activate-vgs-main.service.in
Normal file
19
scripts/lvm-activate-vgs-main.service.in
Normal file
@ -0,0 +1,19 @@
|
||||
[Unit]
|
||||
Description=Activate LVM Volume Groups
|
||||
Documentation=man:vgchange(8)
|
||||
After=dm-event.socket dm-event.service
|
||||
Before=local-fs-pre.target shutdown.target
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target
|
||||
|
||||
# "--eventactivation service" tells vgchange it is being called
|
||||
# from an activation service, so it will do nothing if
|
||||
# lvm.conf event_activation_options = "event_only".
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=@SBINDIR@/lvm vgchange -aay --nohints --vgonline --eventactivation service
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=sysinit.target
|
@ -1,8 +1,8 @@
|
||||
[Unit]
|
||||
Description=Monitoring of LVM2 mirrors, snapshots etc. using dmeventd or progress polling
|
||||
Description=Monitor LVM Logical Volumes
|
||||
Documentation=man:dmeventd(8) man:lvcreate(8) man:lvchange(8) man:vgchange(8)
|
||||
Requires=dm-event.socket
|
||||
After=dm-event.socket dm-event.service lvm2-activation.service
|
||||
After=dm-event.socket dm-event.service lvm-activate-vgs-last.service
|
||||
Before=local-fs-pre.target shutdown.target
|
||||
DefaultDependencies=no
|
||||
Conflicts=shutdown.target
|
||||
|
@ -23,10 +23,10 @@ if [ $1 = 0 ]; then
|
||||
fi
|
||||
|
||||
%triggerun -- %{name} < 2.02.86-2
|
||||
%{_bindir}/systemd-sysv-convert --save lvm2-monitor >/dev/null 2>&1 || :
|
||||
/bin/systemctl --no-reload enable lvm2-monitor.service > /dev/null 2>&1 || :
|
||||
/sbin/chkconfig --del lvm2-monitor > /dev/null 2>&1 || :
|
||||
/bin/systemctl try-restart lvm2-monitor.service > /dev/null 2>&1 || :
|
||||
%{_bindir}/systemd-sysv-convert --save lvm-monitor >/dev/null 2>&1 || :
|
||||
/bin/systemctl --no-reload enable lvm-monitor.service > /dev/null 2>&1 || :
|
||||
/sbin/chkconfig --del lvm-monitor > /dev/null 2>&1 || :
|
||||
/bin/systemctl try-restart lvm-monitor.service > /dev/null 2>&1 || :
|
||||
# files in the main package
|
||||
|
||||
%files
|
||||
@ -100,9 +100,6 @@ fi
|
||||
%{_mandir}/man8/lvm-config.8.gz
|
||||
%{_mandir}/man8/lvm-dumpconfig.8.gz
|
||||
%{_mandir}/man8/lvm.8.gz
|
||||
%if %{enable_systemd}
|
||||
%{_mandir}/man8/lvm2-activation-generator.8.gz
|
||||
%endif
|
||||
%{_mandir}/man8/lvmconfig.8.gz
|
||||
%{_mandir}/man8/lvmdevices.8.gz
|
||||
%{_mandir}/man8/lvmdiskscan.8.gz
|
||||
@ -187,16 +184,17 @@ fi
|
||||
%dir %{_default_run_dir}
|
||||
%if %{enable_systemd}
|
||||
%{_tmpfilesdir}/%{name}.conf
|
||||
%{_unitdir}/lvm-activate-vgs-main.service
|
||||
%{_unitdir}/lvm-activate-vgs-last.service
|
||||
%{_unitdir}/lvm-monitor.service
|
||||
%{_unitdir}/blk-availability.service
|
||||
%{_unitdir}/lvm2-monitor.service
|
||||
%attr(555, -, -) %{_prefix}/lib/systemd/system-generators/lvm2-activation-generator
|
||||
%if %{have_service lvmpolld}
|
||||
%{_unitdir}/lvm2-lvmpolld.service
|
||||
%{_unitdir}/lvm2-lvmpolld.socket
|
||||
%endif
|
||||
%else
|
||||
%{_sysconfdir}/rc.d/init.d/blk-availability
|
||||
%{_sysconfdir}/rc.d/init.d/lvm2-monitor
|
||||
%{_sysconfdir}/rc.d/init.d/lvm-monitor
|
||||
%if %{have_service lvmpolld}
|
||||
%{_sysconfdir}/rc.d/init.d/lvm2-lvmpolld
|
||||
%endif
|
||||
|
@ -278,6 +278,11 @@ arg(errorwhenfull_ARG, '\0', "errorwhenfull", bool_VAL, 0, 0,
|
||||
"(Also see dm-thin-pool kernel module option no_space_timeout.)\n"
|
||||
"See \\fBlvmthin\\fP(7) for more information.\n")
|
||||
|
||||
arg(eventactivation_ARG, '\0', "eventactivation", string_VAL, 0, 0,
|
||||
"Specify if the command is running autoactivation from an event\n"
|
||||
"or a fixed service. The lvm.conf event_activation_options setting\n"
|
||||
"determines if event or service based activation commands are used.\n")
|
||||
|
||||
arg(force_long_ARG, '\0', "force", 0, ARG_COUNTABLE, 0,
|
||||
"Force metadata restore even with thin pool LVs.\n"
|
||||
"Use with extreme caution. Most changes to thin metadata\n"
|
||||
|
@ -1642,14 +1642,15 @@ DESC: Record that a PV is online or offline.
|
||||
|
||||
pvscan --cache_long --activate ay
|
||||
OO: --ignorelockingfailure, --reportformat ReportFmt,
|
||||
--major Number, --minor Number, --noudevsync
|
||||
--major Number, --minor Number, --noudevsync, --eventactivation String
|
||||
OP: PV|String ...
|
||||
IO: --background
|
||||
ID: pvscan_cache
|
||||
DESC: Record that a PV is online and autoactivate the VG if complete.
|
||||
|
||||
pvscan --cache_long --listvg PV
|
||||
OO: --ignorelockingfailure, --checkcomplete, --vgonline, --udevoutput
|
||||
OO: --ignorelockingfailure, --checkcomplete, --vgonline, --udevoutput,
|
||||
--eventactivation String
|
||||
ID: pvscan_cache
|
||||
DESC: Record that a PV is online and list the VG using the PV.
|
||||
|
||||
@ -1747,7 +1748,8 @@ DESC: Start or stop processing LV conversions.
|
||||
|
||||
vgchange --activate Active
|
||||
OO: --activationmode ActivationMode, --ignoreactivationskip, --partial, --sysinit,
|
||||
--readonly, --ignorelockingfailure, --monitor Bool, --poll Bool, OO_VGCHANGE
|
||||
--readonly, --ignorelockingfailure, --monitor Bool, --poll Bool,
|
||||
--vgonline, --eventactivation String, OO_VGCHANGE
|
||||
OP: VG|Tag|Select ...
|
||||
IO: --ignoreskippedcluster
|
||||
ID: vgchange_activate
|
||||
|
@ -2540,6 +2540,8 @@ static int _get_current_settings(struct cmd_context *cmd)
|
||||
if (!strcmp(hint_mode, "none")) {
|
||||
cmd->enable_hints = 0;
|
||||
cmd->use_hints = 0;
|
||||
} else if (!strcmp(hint_mode, "pvs_online")) {
|
||||
cmd->hints_pvs_online = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
195
tools/pvscan.c
195
tools/pvscan.c
@ -21,6 +21,8 @@
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
int online_pvid_file_read(char *path, int *major, int *minor, char *vgname);
|
||||
|
||||
struct pvscan_params {
|
||||
int new_pvs_found;
|
||||
int pvs_found;
|
||||
@ -46,6 +48,8 @@ static const char *_pvs_online_dir = DEFAULT_RUN_DIR "/pvs_online";
|
||||
static const char *_vgs_online_dir = DEFAULT_RUN_DIR "/vgs_online";
|
||||
static const char *_pvs_lookup_dir = DEFAULT_RUN_DIR "/pvs_lookup";
|
||||
|
||||
static const char *_event_activation_file = DEFAULT_RUN_DIR "/event-activation-on";
|
||||
|
||||
static int _pvscan_display_pv(struct cmd_context *cmd,
|
||||
struct physical_volume *pv,
|
||||
struct pvscan_params *params)
|
||||
@ -179,6 +183,84 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Event based activation
|
||||
* lvm.conf event_activation_options = "event_only"
|
||||
* . all events are used for activation
|
||||
* . no fixed services are used for activation
|
||||
* . lvm.conf event_activation=1 required
|
||||
*
|
||||
* vgchange -aay --eventactivation service
|
||||
* . does nothing
|
||||
* vgchange -aay --eventactivation event
|
||||
* . does activation
|
||||
* pvscan --eventactivation event
|
||||
* . does activation
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* Non-event based activation
|
||||
* lvm.conf event_activation_options = "service_only"
|
||||
* . fixed services are used for activation
|
||||
* . no events are used for activation
|
||||
* . lvm.conf event_activation=0 is equivalent to
|
||||
* event_activation=1 event_activation_options="service_only"
|
||||
*
|
||||
* vgchange -aay --eventactivation service
|
||||
* . does activation
|
||||
* vgchange -aay --eventactivation event
|
||||
* . does nothing
|
||||
* pvscan --eventactivation event
|
||||
* . does nothing
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* Mix of event and non-event based activation
|
||||
* lvm.conf event_activation_options = "service_to_event"
|
||||
* . both services and events are used for activation
|
||||
* . fixed services are used for activation initially,
|
||||
* and last service enables event based activation
|
||||
* by creating the event-activation-on file
|
||||
*
|
||||
* vgchange -aay --eventactivation service
|
||||
* . does activation only if event-activation-on does not exist
|
||||
* vgchange -aay --eventactivation event
|
||||
* . does activation only if event-activation-on exists
|
||||
* vgchange -aay --eventactivation service,on
|
||||
* . does activation only if event-activation-on does not exist
|
||||
* . creates event-activation-on to enable event-based activation
|
||||
* vgchange --eventactivation on|off
|
||||
* . create or remove event-activation-on to enable|disable
|
||||
* event-based activation
|
||||
* pvscan --eventactivation event
|
||||
* . does activation only if event-activation-on exists
|
||||
*
|
||||
*/
|
||||
|
||||
int event_activation_enable(struct cmd_context *cmd)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if (!(fp = fopen(_event_activation_file, "w")))
|
||||
return_0;
|
||||
if (fclose(fp))
|
||||
stack;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int event_activation_is_on(struct cmd_context *cmd)
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if (!stat(_event_activation_file, &buf))
|
||||
return 1;
|
||||
|
||||
if (errno != ENOENT)
|
||||
log_debug("event_activation_is_on errno %d", errno);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Avoid a duplicate pvscan[%d] prefix when logging to the journal.
|
||||
* FIXME: this should probably replace if (udevoutput) with
|
||||
@ -225,7 +307,7 @@ static char *_vgname_in_pvid_file_buf(char *buf)
|
||||
|
||||
#define MAX_PVID_FILE_SIZE 512
|
||||
|
||||
static int _online_pvid_file_read(char *path, int *major, int *minor, char *vgname)
|
||||
int online_pvid_file_read(char *path, int *major, int *minor, char *vgname)
|
||||
{
|
||||
char buf[MAX_PVID_FILE_SIZE] = { 0 };
|
||||
char *name;
|
||||
@ -328,7 +410,7 @@ static void _online_pvid_file_remove_devno(int major, int minor)
|
||||
file_minor = 0;
|
||||
memset(file_vgname, 0, sizeof(file_vgname));
|
||||
|
||||
_online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
||||
online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
||||
|
||||
if ((file_major == major) && (file_minor == minor)) {
|
||||
log_debug("Unlink pv online %s", path);
|
||||
@ -367,7 +449,7 @@ static void _online_files_remove(const char *dirpath)
|
||||
log_sys_debug("closedir", dirpath);
|
||||
}
|
||||
|
||||
static int _online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const char *vgname)
|
||||
int online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const char *vgname, int ignore_existing, int *exists)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char buf[MAX_PVID_FILE_SIZE] = { 0 };
|
||||
@ -407,8 +489,13 @@ static int _online_pvid_file_create(struct cmd_context *cmd, struct device *dev,
|
||||
|
||||
fd = open(path, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0) {
|
||||
if (errno == EEXIST)
|
||||
if (errno == EEXIST) {
|
||||
if (exists)
|
||||
*exists = 1;
|
||||
if (ignore_existing)
|
||||
return 1;
|
||||
goto check_duplicate;
|
||||
}
|
||||
log_error_pvscan(cmd, "Failed to create online file for %s path %s error %d", dev_name(dev), path, errno);
|
||||
return 0;
|
||||
}
|
||||
@ -427,7 +514,6 @@ static int _online_pvid_file_create(struct cmd_context *cmd, struct device *dev,
|
||||
}
|
||||
|
||||
/* We don't care about syncing, these files are not even persistent. */
|
||||
|
||||
if (close(fd))
|
||||
log_sys_debug("close", path);
|
||||
|
||||
@ -447,7 +533,7 @@ check_duplicate:
|
||||
|
||||
memset(file_vgname, 0, sizeof(file_vgname));
|
||||
|
||||
_online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
||||
online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
||||
|
||||
if ((file_major == major) && (file_minor == minor)) {
|
||||
log_debug("Existing online file for %d:%d", major, minor);
|
||||
@ -660,7 +746,7 @@ static int _count_pvid_files_from_lookup_file(struct cmd_context *cmd, struct de
|
||||
return (vgname) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void _online_dir_setup(struct cmd_context *cmd)
|
||||
void online_dir_setup(struct cmd_context *cmd)
|
||||
{
|
||||
struct stat st;
|
||||
int rv;
|
||||
@ -748,7 +834,7 @@ static int _pvscan_aa_single(struct cmd_context *cmd, const char *vg_name,
|
||||
|
||||
log_debug("pvscan autoactivating VG %s.", vg_name);
|
||||
|
||||
if (!vgchange_activate(cmd, vg, CHANGE_AAY)) {
|
||||
if (!vgchange_activate(cmd, vg, CHANGE_AAY, 1)) {
|
||||
log_error_pvscan(cmd, "%s: autoactivation failed.", vg->name);
|
||||
pp->activate_errors++;
|
||||
}
|
||||
@ -756,7 +842,7 @@ static int _pvscan_aa_single(struct cmd_context *cmd, const char *vg_name,
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
static int _online_vg_file_create(struct cmd_context *cmd, const char *vgname)
|
||||
int online_vg_file_create(struct cmd_context *cmd, const char *vgname)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
int fd;
|
||||
@ -847,7 +933,7 @@ static int _get_devs_from_saved_vg(struct cmd_context *cmd, const char *vgname,
|
||||
file_minor = 0;
|
||||
memset(file_vgname, 0, sizeof(file_vgname));
|
||||
|
||||
_online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
||||
online_pvid_file_read(path, &file_major, &file_minor, file_vgname);
|
||||
|
||||
if (file_vgname[0] && strcmp(vgname, file_vgname)) {
|
||||
log_error_pvscan(cmd, "Wrong VG found for %d:%d PVID %s: %s vs %s",
|
||||
@ -857,11 +943,21 @@ static int _get_devs_from_saved_vg(struct cmd_context *cmd, const char *vgname,
|
||||
|
||||
devno = MKDEV(file_major, file_minor);
|
||||
|
||||
if (!setup_devno_in_dev_cache(cmd, devno)) {
|
||||
log_error_pvscan(cmd, "No device set up for %d:%d PVID %s", file_major, file_minor, pvid);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!(dev = dev_cache_get_by_devt(cmd, devno, NULL, NULL))) {
|
||||
log_error_pvscan(cmd, "No device found for %d:%d PVID %s", file_major, file_minor, pvid);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not need to match device_id here, see comment after
|
||||
* get_devs_from_saved_vg about relying on pvid online file.
|
||||
*/
|
||||
|
||||
name1 = dev_name(dev);
|
||||
name2 = pvl->pv->device_hint;
|
||||
|
||||
@ -1026,7 +1122,7 @@ static int _pvscan_aa_quick(struct cmd_context *cmd, struct pvscan_aa_params *pp
|
||||
|
||||
log_debug("pvscan autoactivating VG %s.", vgname);
|
||||
|
||||
if (!vgchange_activate(cmd, vg, CHANGE_AAY)) {
|
||||
if (!vgchange_activate(cmd, vg, CHANGE_AAY, 1)) {
|
||||
log_error_pvscan(cmd, "%s: autoactivation failed.", vg->name);
|
||||
pp->activate_errors++;
|
||||
}
|
||||
@ -1060,7 +1156,7 @@ static int _pvscan_aa(struct cmd_context *cmd, struct pvscan_aa_params *pp,
|
||||
* to run the activation. The first to create the file will do it.
|
||||
*/
|
||||
dm_list_iterate_items_safe(sl, sl2, vgnames) {
|
||||
if (!_online_vg_file_create(cmd, sl->str)) {
|
||||
if (!online_vg_file_create(cmd, sl->str)) {
|
||||
log_print_pvscan(cmd, "VG %s skip autoactivation.", sl->str);
|
||||
str_list_del(vgnames, sl->str);
|
||||
continue;
|
||||
@ -1192,11 +1288,15 @@ static int _get_args_devs(struct cmd_context *cmd, struct dm_list *pvscan_args,
|
||||
/* in common usage, no dev will be found for a devno */
|
||||
|
||||
dm_list_iterate_items(arg, pvscan_args) {
|
||||
if (arg->devname)
|
||||
if (arg->devname) {
|
||||
if (!setup_devname_in_dev_cache(cmd, arg->devname))
|
||||
log_error_pvscan(cmd, "No device set up for name arg %s", arg->devname);
|
||||
arg->dev = dev_cache_get(cmd, arg->devname, NULL);
|
||||
else if (arg->devno)
|
||||
} else if (arg->devno) {
|
||||
if (!setup_devno_in_dev_cache(cmd, arg->devno))
|
||||
log_error_pvscan(cmd, "No device set up for devno arg %d", (int)arg->devno);
|
||||
arg->dev = dev_cache_get_by_devt(cmd, arg->devno, NULL, NULL);
|
||||
else
|
||||
} else
|
||||
return_0;
|
||||
}
|
||||
|
||||
@ -1246,7 +1346,7 @@ static void _set_pv_devices_online(struct cmd_context *cmd, struct volume_group
|
||||
minor = 0;
|
||||
file_vgname[0] = '\0';
|
||||
|
||||
_online_pvid_file_read(path, &major, &minor, file_vgname);
|
||||
online_pvid_file_read(path, &major, &minor, file_vgname);
|
||||
|
||||
if (file_vgname[0] && strcmp(vg->name, file_vgname)) {
|
||||
log_warn("WARNING: VG %s PV %s wrong vgname in online file %s",
|
||||
@ -1412,7 +1512,7 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs
|
||||
* Create file named for pvid to record this PV is online.
|
||||
* The command creates/checks online files only when --cache is used.
|
||||
*/
|
||||
if (do_cache && !_online_pvid_file_create(cmd, dev, vg ? vg->name : NULL)) {
|
||||
if (do_cache && !online_pvid_file_create(cmd, dev, vg ? vg->name : NULL, 0, NULL)) {
|
||||
log_error_pvscan(cmd, "PV %s failed to create online file.", dev_name(dev));
|
||||
release_vg(vg);
|
||||
ret = 0;
|
||||
@ -1497,7 +1597,7 @@ static int _online_devs(struct cmd_context *cmd, int do_all, struct dm_list *pvs
|
||||
} else if (!do_check_complete) {
|
||||
log_print("VG %s", vgname);
|
||||
} else if (vg_complete) {
|
||||
if (do_vgonline && !_online_vg_file_create(cmd, vgname)) {
|
||||
if (do_vgonline && !online_vg_file_create(cmd, vgname)) {
|
||||
log_print("VG %s finished", vgname);
|
||||
} else {
|
||||
/*
|
||||
@ -1672,11 +1772,13 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv,
|
||||
cmd->pvscan_cache_single = 1;
|
||||
|
||||
/*
|
||||
* "no_file_match" means that when the devices file is used,
|
||||
* setup_devices will skip matching devs to devices file entries.
|
||||
* Specific devs must be matched later with device_ids_match_dev().
|
||||
* Special pvscan-specific setup steps to avoid looking
|
||||
* at any devices except for device args.
|
||||
* Read devices file and determine if devices file will be used.
|
||||
* Does not do dev_cache_scan (adds nothing to dev-cache), and
|
||||
* does not do any device id matching.
|
||||
*/
|
||||
if (!setup_devices_no_file_match(cmd)) {
|
||||
if (!setup_devices_for_pvscan_cache(cmd)) {
|
||||
log_error_pvscan(cmd, "Failed to set up devices.");
|
||||
return 0;
|
||||
}
|
||||
@ -1735,17 +1837,21 @@ static int _pvscan_cache_args(struct cmd_context *cmd, int argc, char **argv,
|
||||
log_debug("pvscan_cache_args: filter devs nodata");
|
||||
|
||||
/*
|
||||
* Match dev args with the devices file because
|
||||
* setup_devices_no_file_match() was used above which skipped checking
|
||||
* the devices file. If a match fails here do not exclude it, that
|
||||
* will be done below by passes_filter() which runs filter-deviceid.
|
||||
* The relax_deviceid_filter case needs to be able to work around
|
||||
* Match dev args with the devices file because special/optimized
|
||||
* device setup was used above which does not check the devices file.
|
||||
* If a match fails here do not exclude it, that will be done below by
|
||||
* passes_filter() which runs filter-deviceid. The
|
||||
* relax_deviceid_filter case needs to be able to work around
|
||||
* unmatching devs.
|
||||
*/
|
||||
|
||||
if (cmd->enable_devices_file) {
|
||||
dm_list_iterate_items_safe(devl, devl2, &pvscan_devs)
|
||||
dm_list_iterate_items(devl, &pvscan_devs)
|
||||
device_ids_match_dev(cmd, devl->dev);
|
||||
|
||||
}
|
||||
if (cmd->enable_devices_list)
|
||||
device_ids_match_device_list(cmd);
|
||||
|
||||
if (cmd->enable_devices_file && device_ids_use_devname(cmd)) {
|
||||
relax_deviceid_filter = 1;
|
||||
@ -1857,6 +1963,7 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
struct pvscan_aa_params pp = { 0 };
|
||||
struct dm_list complete_vgnames;
|
||||
const char *ea;
|
||||
int do_activate = arg_is_set(cmd, activate_ARG);
|
||||
int event_activation;
|
||||
int devno_args = 0;
|
||||
@ -1919,7 +2026,7 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
do_all = !argc && !devno_args;
|
||||
|
||||
_online_dir_setup(cmd);
|
||||
online_dir_setup(cmd);
|
||||
|
||||
if (do_all) {
|
||||
if (!_pvscan_cache_all(cmd, argc, argv, &complete_vgnames))
|
||||
@ -1930,6 +2037,36 @@ int pvscan_cache_cmd(struct cmd_context *cmd, int argc, char **argv)
|
||||
log_verbose("Ignoring pvscan --cache because event_activation is disabled.");
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
|
||||
if ((ea = arg_str_value(cmd, eventactivation_ARG, NULL))) {
|
||||
int service_only = 0, event_only = 0, service_to_event = 0;
|
||||
int ea_service = 0, ea_event = 0, ea_on = 0;
|
||||
|
||||
if (!get_event_activation_config_settings(cmd, &service_only, &event_only, &service_to_event))
|
||||
return ECMD_FAILED;
|
||||
if (!get_event_activation_command_options(cmd, ea, &ea_service, &ea_event, &ea_on))
|
||||
return ECMD_FAILED;
|
||||
|
||||
if (ea_event) {
|
||||
if (!event_activation) {
|
||||
log_print("Skip pvscan for event and event_activation=0.");
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
if (service_only) {
|
||||
log_print("Skip pvscan for event and event_activation_options service_only.");
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
if (service_to_event && !event_activation_is_on(cmd)) {
|
||||
log_print("Skip pvscan for event and no event-activation-on.");
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
} else {
|
||||
log_error("Option --eventactivation %s is not used by pvscan.", ea);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_pvscan_cache_args(cmd, argc, argv, &complete_vgnames))
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
@ -5714,3 +5714,90 @@ bad:
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_event_activation_config_settings(struct cmd_context *cmd,
|
||||
int *service_only, int *event_only, int *service_to_event)
|
||||
{
|
||||
const struct dm_config_node *cn;
|
||||
const struct dm_config_value *cv;
|
||||
int eo = 0, so = 0, se = 0;
|
||||
|
||||
if (!(cn = find_config_tree_array(cmd, global_event_activation_options_CFG, NULL)))
|
||||
return 1;
|
||||
|
||||
for (cv = cn->v; cv; cv = cv->next) {
|
||||
if (cv->type != DM_CFG_STRING)
|
||||
continue;
|
||||
if (!strcmp(cv->v.str, "service_only"))
|
||||
so = 1;
|
||||
else if (!strcmp(cv->v.str, "event_only"))
|
||||
eo = 1;
|
||||
else if (!strcmp(cv->v.str, "service_to_event"))
|
||||
se = 1;
|
||||
else if (strlen(cv->v.str) > 0)
|
||||
log_warn("WARNING: ignoring unrecognized event_activation_options value %s.", cv->v.str);
|
||||
}
|
||||
|
||||
if (se && (so || eo)) {
|
||||
log_warn("WARNING: ignoring incompatible event_activation_options, using service_to_event.");
|
||||
*service_to_event = 1;
|
||||
} else if (so && eo) {
|
||||
log_warn("WARNING: ignoring incompatible event_activation_options, using event_only.");
|
||||
*event_only = 1;
|
||||
} else if (se) {
|
||||
*service_to_event = 1;
|
||||
} else if (so) {
|
||||
*service_only = 1;
|
||||
} else if (eo) {
|
||||
*event_only = 1;
|
||||
} else {
|
||||
*service_to_event = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _ea_option_value(const char *val, int *ea_service, int *ea_event, int *ea_on)
|
||||
{
|
||||
if (!strcmp(val, "service"))
|
||||
*ea_service = 1;
|
||||
else if (!strcmp(val, "event"))
|
||||
*ea_event = 1;
|
||||
else if (!strcmp(val, "on"))
|
||||
*ea_on = 1;
|
||||
else {
|
||||
log_error("Unknown --eventactivation value.");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_event_activation_command_options(struct cmd_context *cmd, const char *ea, int *ea_service, int *ea_event, int *ea_on)
|
||||
{
|
||||
char ea_vals[128] = {0};
|
||||
char *val1, *val2;
|
||||
|
||||
strncpy(ea_vals, ea, 127);
|
||||
|
||||
/* Currently only two values can be used together. */
|
||||
|
||||
val1 = ea_vals;
|
||||
|
||||
if ((val2 = strchr(ea_vals, ','))) {
|
||||
*val2 = '\0';
|
||||
val2++;
|
||||
}
|
||||
|
||||
if (val1 && !_ea_option_value(val1, ea_service, ea_event, ea_on))
|
||||
return 0;
|
||||
|
||||
if (val2 && !_ea_option_value(val2, ea_service, ea_event, ea_on))
|
||||
return 0;
|
||||
|
||||
if (*ea_service && *ea_event) {
|
||||
log_error("Invalid --eventactivation options, service and event are incompatible.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -237,4 +237,9 @@ int lvremove_single(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
|
||||
int get_lvt_enum(struct logical_volume *lv);
|
||||
|
||||
int get_event_activation_config_settings(struct cmd_context *cmd,
|
||||
int *service_only, int *event_only, int *service_to_event);
|
||||
int get_event_activation_command_options(struct cmd_context *cmd,
|
||||
const char *ea, int *ea_service, int *ea_event, int *ea_on);
|
||||
|
||||
#endif
|
||||
|
@ -226,9 +226,8 @@ int lvconvert_poll(struct cmd_context *cmd, struct logical_volume *lv, unsigned
|
||||
int mirror_remove_missing(struct cmd_context *cmd,
|
||||
struct logical_volume *lv, int force);
|
||||
|
||||
|
||||
int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
|
||||
activation_change_t activate);
|
||||
activation_change_t activate, int vg_complete_to_activate);
|
||||
|
||||
int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg);
|
||||
|
||||
@ -295,6 +294,11 @@ int lvconvert_cachevol_attach_single(struct cmd_context *cmd,
|
||||
struct logical_volume *lv,
|
||||
struct processing_handle *handle);
|
||||
|
||||
int online_pvid_file_create(struct cmd_context *cmd, struct device *dev, const char *vgname, int ignore_existing, int *exists);
|
||||
void online_vg_file_remove(const char *vgname);
|
||||
int online_vg_file_create(struct cmd_context *cmd, const char *vgname);
|
||||
void online_dir_setup(struct cmd_context *cmd);
|
||||
int event_activation_enable(struct cmd_context *cmd);
|
||||
int event_activation_is_on(struct cmd_context *cmd);
|
||||
|
||||
#endif
|
||||
|
184
tools/vgchange.c
184
tools/vgchange.c
@ -19,6 +19,7 @@
|
||||
struct vgchange_params {
|
||||
int lock_start_count;
|
||||
unsigned int lock_start_sanlock : 1;
|
||||
unsigned int vg_complete_to_activate : 1;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -194,11 +195,47 @@ int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _online_pvid_file_create_all(struct cmd_context *cmd)
|
||||
{
|
||||
struct lvmcache_info *info;
|
||||
struct dev_iter *iter;
|
||||
struct device *dev;
|
||||
const char *vgname;
|
||||
int exists;
|
||||
int exist_count = 0;
|
||||
int create_count = 0;
|
||||
|
||||
if (!(iter = dev_iter_create(NULL, 0)))
|
||||
return 0;
|
||||
while ((dev = dev_iter_get(cmd, iter))) {
|
||||
if (dev->pvid[0] &&
|
||||
(info = lvmcache_info_from_pvid(dev->pvid, dev, 0))) {
|
||||
vgname = lvmcache_vgname_from_info(info);
|
||||
if (vgname && !is_orphan_vg(vgname)) {
|
||||
/*
|
||||
* Ignore exsting pvid file because a pvscan may be creating
|
||||
* the same file as the same time we are, which is expected.
|
||||
*/
|
||||
exists = 0;
|
||||
online_pvid_file_create(cmd, dev, vgname, 1, &exists);
|
||||
if (exists)
|
||||
exist_count++;
|
||||
else
|
||||
create_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
dev_iter_destroy(iter);
|
||||
log_debug("PV online files created %d exist %d", create_count, exist_count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
|
||||
activation_change_t activate)
|
||||
activation_change_t activate, int vg_complete_to_activate)
|
||||
{
|
||||
int lv_open, active, monitored = 0, r = 1;
|
||||
const struct lv_list *lvl;
|
||||
struct pv_list *pvl;
|
||||
int do_activate = is_change_activating(activate);
|
||||
|
||||
/*
|
||||
@ -219,6 +256,20 @@ int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (arg_is_set(cmd, vgonline_ARG) && !online_vg_file_create(cmd, vg->name)) {
|
||||
log_print("VG %s already online", vg->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (do_activate && vg_complete_to_activate) {
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!pvl->pv->dev) {
|
||||
log_print("VG %s is incomplete.", vg->name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Safe, since we never write out new metadata here. Required for
|
||||
* partial activation to work.
|
||||
@ -647,6 +698,7 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name,
|
||||
struct volume_group *vg,
|
||||
struct processing_handle *handle)
|
||||
{
|
||||
struct vgchange_params *vp = (struct vgchange_params *)handle->custom_handle;
|
||||
int ret = ECMD_PROCESSED;
|
||||
unsigned i;
|
||||
activation_change_t activate;
|
||||
@ -699,9 +751,12 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name,
|
||||
log_print_unless_silent("Volume group \"%s\" successfully changed", vg->name);
|
||||
}
|
||||
|
||||
if (arg_is_set(cmd, vgonline_ARG))
|
||||
online_dir_setup(cmd);
|
||||
|
||||
if (arg_is_set(cmd, activate_ARG)) {
|
||||
activate = (activation_change_t) arg_uint_value(cmd, activate_ARG, 0);
|
||||
if (!vgchange_activate(cmd, vg, activate))
|
||||
if (!vgchange_activate(cmd, vg, activate, vp->vg_complete_to_activate))
|
||||
return_ECMD_FAILED;
|
||||
} else if (arg_is_set(cmd, refresh_ARG)) {
|
||||
/* refreshes the visible LVs (which starts polling) */
|
||||
@ -722,8 +777,113 @@ static int _vgchange_single(struct cmd_context *cmd, const char *vg_name,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _check_event_activation(struct cmd_context *cmd, struct vgchange_params *vp, int *skip_command, int *enable_events)
|
||||
{
|
||||
const char *ea;
|
||||
int service_only = 0, event_only = 0, service_to_event = 0;
|
||||
int ea_service = 0, ea_event = 0, ea_on = 0;
|
||||
int on_file_exists;
|
||||
int event_activation;
|
||||
|
||||
if (!(ea = arg_str_value(cmd, eventactivation_ARG, NULL))) {
|
||||
log_error("No eventactivation value.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* lvm.conf event_activation_options */
|
||||
if (!get_event_activation_config_settings(cmd, &service_only, &event_only, &service_to_event))
|
||||
return_0;
|
||||
|
||||
/* --eventactivation values */
|
||||
if (!get_event_activation_command_options(cmd, ea, &ea_service, &ea_event, &ea_on))
|
||||
return_0;
|
||||
|
||||
event_activation = find_config_tree_bool(cmd, global_event_activation_CFG, NULL);
|
||||
|
||||
/*
|
||||
* The combination of lvm.conf event_activation/event_activation_options
|
||||
* and the --eventactivation service|event value determines if this
|
||||
* command should do anything or be skipped, along with the existence of
|
||||
* the /run/lvm/event-activation-on file in case of service_to_event.
|
||||
*/
|
||||
if (!event_activation) {
|
||||
if (ea_event) {
|
||||
log_print("Skip vgchange for event and event_activation=0.");
|
||||
*skip_command = 1;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (event_only && ea_service) {
|
||||
log_print("Skip vgchange for service and event_activation_options event_only.");
|
||||
*skip_command = 1;
|
||||
return 1;
|
||||
}
|
||||
if (service_only && ea_event) {
|
||||
log_print("Skip vgchange for event and event_activation_options service_only.");
|
||||
*skip_command = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
on_file_exists = event_activation_is_on(cmd);
|
||||
|
||||
if (service_to_event && ea_service && on_file_exists) {
|
||||
log_print("Skip vgchange for service and event-activation-on.");
|
||||
*skip_command = 1;
|
||||
return 1;
|
||||
}
|
||||
if (service_to_event && ea_event && !on_file_exists) {
|
||||
log_print("Skip vgchange for event and no event-activation-on.");
|
||||
*skip_command = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch from service activation to event activation when:
|
||||
* lvm.conf event_activation=1,
|
||||
* event_activation_options=service_to_event,
|
||||
* and --eventactivation service,on.
|
||||
*
|
||||
* When enabling event-based activation, first create the
|
||||
* /run/lvm/event-activation-on file to tell other commands
|
||||
* to begin responding to PV events and doing activation
|
||||
* for newly completed VGs. It also needs to create online
|
||||
* files for existing PVs because some VGs may be incomplete
|
||||
* at this point, and future pvscan commands need to
|
||||
* find online files for PVs that have already appeared.
|
||||
* The label scan provides info to know which PVs are
|
||||
* present and should have pvid online files created.
|
||||
*
|
||||
* process_each_vg() usually begins with lock_global() and
|
||||
* lvmcache_label_scan(), and then processes each VG.
|
||||
* In this case, lock_global/lvmcache_label_scan are done
|
||||
* before calling process_each_vg. This allows a special
|
||||
* step to be inserted between the label scan and processing
|
||||
* vgs. That step creates the pvid online files, which
|
||||
* requires label scan info. The lock_global and
|
||||
* lvmcache_label_scan will be skipped by process_each_vg
|
||||
* since they are already done here.
|
||||
*/
|
||||
if (event_activation && service_to_event && ea_service && ea_on) {
|
||||
if (!event_activation_enable(cmd))
|
||||
log_warn("WARNING: Failed to create event-activation-on.");
|
||||
*enable_events = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* lvm.conf service_to_event, and vgchange -aay --eventactivation service,
|
||||
* then only activate LVs if the VG is complete.
|
||||
* A later event will complete the VG and activate it.
|
||||
*/
|
||||
if (event_activation && service_to_event && ea_service)
|
||||
vp->vg_complete_to_activate = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vgchange(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
struct vgchange_params vp = { 0 };
|
||||
struct processing_handle *handle;
|
||||
uint32_t flags = 0;
|
||||
int ret;
|
||||
@ -837,6 +997,24 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
|
||||
cmd->lockd_vg_enforce_sh = 1;
|
||||
}
|
||||
|
||||
if (arg_is_set(cmd, eventactivation_ARG)) {
|
||||
int skip_command = 0, enable_events = 0;
|
||||
if (!_check_event_activation(cmd, &vp, &skip_command, &enable_events))
|
||||
return ECMD_FAILED;
|
||||
if (skip_command)
|
||||
return ECMD_PROCESSED;
|
||||
if (enable_events) {
|
||||
if (!event_activation_enable(cmd))
|
||||
log_warn("WARNING: Failed to create event-activation-on.");
|
||||
/* The process_each_vg lock_global/lvmcache_label_scan will be skipped. */
|
||||
if (!lock_global(cmd, "sh"))
|
||||
return ECMD_FAILED;
|
||||
lvmcache_label_scan(cmd);
|
||||
_online_pvid_file_create_all(cmd);
|
||||
flags |= PROCESS_SKIP_SCAN;
|
||||
}
|
||||
}
|
||||
|
||||
if (update)
|
||||
flags |= READ_FOR_UPDATE;
|
||||
else if (arg_is_set(cmd, activate_ARG))
|
||||
@ -847,6 +1025,8 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
handle->custom_handle = &vp;
|
||||
|
||||
ret = process_each_vg(cmd, argc, argv, NULL, NULL, flags, 0, handle, &_vgchange_single);
|
||||
|
||||
destroy_processing_handle(cmd, handle);
|
||||
|
@ -121,6 +121,6 @@ LABEL="direct_pvscan"
|
||||
# MD | | X | X* | |
|
||||
# loop | | X | X* | |
|
||||
# other | X | | X | | X
|
||||
RUN+="(LVM_EXEC)/lvm pvscan --background --cache --activate ay --major $major --minor $minor", ENV{LVM_SCANNED}="1"
|
||||
RUN+="(LVM_EXEC)/lvm pvscan --cache -aay --eventactivation event --major $major --minor $minor", ENV{LVM_SCANNED}="1"
|
||||
|
||||
LABEL="lvm_end"
|
||||
|
@ -78,9 +78,19 @@ ENV{SYSTEMD_READY}="1"
|
||||
#
|
||||
# TODO: adjust the output of vgchange -aay so that
|
||||
# it's better suited to appearing in the journal.
|
||||
#
|
||||
# "--eventactivation event" used with pvscan or vgchange
|
||||
# tells the command that it is being run from an event.
|
||||
# The command does nothing if lvm.conf event_activation=0.
|
||||
# The command does nothing if lvm.conf event_activation=1,
|
||||
# and lvm.conf event_activation_options="service_only".
|
||||
# The command goes ahead if event_activation_options="event_only",
|
||||
# or if event_activation_options="service_to_event" and the
|
||||
# event-activation-on file exists.
|
||||
#
|
||||
|
||||
IMPORT{program}="(LVM_EXEC)/lvm pvscan --cache --listvg --checkcomplete --vgonline --udevoutput --journal=output $env{DEVNAME}"
|
||||
ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/usr/bin/systemd-run -r --no-block --property DefaultDependencies=no --unit lvm-activate-$env{LVM_VG_NAME_COMPLETE} lvm vgchange -aay --nohints $env{LVM_VG_NAME_COMPLETE}"
|
||||
IMPORT{program}="(LVM_EXEC)/lvm pvscan --cache --listvg --checkcomplete --vgonline --eventactivation event --udevoutput --journal=output $env{DEVNAME}"
|
||||
ENV{LVM_VG_NAME_COMPLETE}=="?*", RUN+="/usr/bin/systemd-run -r --no-block --property DefaultDependencies=no --unit lvm-activate-$env{LVM_VG_NAME_COMPLETE} lvm vgchange -aay --config devices/hints=pvs_online --eventactivation event $env{LVM_VG_NAME_COMPLETE}"
|
||||
GOTO="lvm_end"
|
||||
|
||||
LABEL="lvm_end"
|
||||
|
Reference in New Issue
Block a user