mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-11-04 12:23:49 +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