mirror of
				git://sourceware.org/git/lvm2.git
				synced 2025-11-03 08:23:48 +03:00 
			
		
		
		
	system_id: use for VG ownership
See included lvmsystemid(7) for full description.
This commit is contained in:
		@@ -834,6 +834,19 @@ global {
 | 
			
		||||
    # See cache_check_executable how to obtain binaries.
 | 
			
		||||
    #
 | 
			
		||||
    # cache_dump_executable = "@CACHE_DUMP_CMD@"
 | 
			
		||||
 | 
			
		||||
    # Defines the method lvm will use to find the local system_id.
 | 
			
		||||
    # The options are: none, machineid, uname, lvmlocal, or file.
 | 
			
		||||
    # Unset, or set to an empty string is equivalent to "none".
 | 
			
		||||
    # See lvmsystemid(7) for more information.
 | 
			
		||||
    #
 | 
			
		||||
    # system_id_source = ""
 | 
			
		||||
 | 
			
		||||
    # Specifies the path to a file containing the local system_id.
 | 
			
		||||
    # It is only used when system_id_source = "file".
 | 
			
		||||
    # See lvmsystemid(7) for more information.
 | 
			
		||||
    #
 | 
			
		||||
    # system_id_file = ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
activation {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										33
									
								
								conf/lvmlocal.conf.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								conf/lvmlocal.conf.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
# This is an example local configuration file for the LVM2 system.
 | 
			
		||||
# It contains the default settings that would be used if there was no
 | 
			
		||||
# @DEFAULT_SYS_DIR@/lvmlocal.conf file.
 | 
			
		||||
#
 | 
			
		||||
# Refer to 'man lvm.conf' for further information including the file layout.
 | 
			
		||||
#
 | 
			
		||||
# To put this file in a different directory and override @DEFAULT_SYS_DIR@ set
 | 
			
		||||
# the environment variable LVM_SYSTEM_DIR before running the tools.
 | 
			
		||||
#
 | 
			
		||||
# N.B. Take care that each setting only appears once if uncommenting
 | 
			
		||||
# example settings in this file.
 | 
			
		||||
#
 | 
			
		||||
# The lvmlocal.conf file should contain only the "local { }" section
 | 
			
		||||
# which contains settings that should not be shared or repeated among
 | 
			
		||||
# different hosts.
 | 
			
		||||
#
 | 
			
		||||
# This file should not be copied among hosts.
 | 
			
		||||
 | 
			
		||||
local {
 | 
			
		||||
    # This defines the system_id of the local host.  It is
 | 
			
		||||
    # only used if lvm.conf system_id_source = "lvmlocal".
 | 
			
		||||
    # When used, it should be set to a unique value.
 | 
			
		||||
    # See lvmsystemid(7) for more information.
 | 
			
		||||
    #
 | 
			
		||||
    # system_id = ""
 | 
			
		||||
 | 
			
		||||
    # This defines system_id's other than the local system_id
 | 
			
		||||
    # that the local host is allowed to access.
 | 
			
		||||
    # See lvmsystemid(7) for more information.
 | 
			
		||||
    #
 | 
			
		||||
    # allow_system_id = []
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -55,6 +55,89 @@
 | 
			
		||||
 | 
			
		||||
static const size_t linebuffer_size = 4096;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Copy the input string, removing invalid characters. */
 | 
			
		||||
 | 
			
		||||
char *system_id_from_string(struct cmd_context *cmd, const char *str)
 | 
			
		||||
{
 | 
			
		||||
	char *system_id;
 | 
			
		||||
 | 
			
		||||
	if (!(system_id = dm_pool_zalloc(cmd->mem, strlen(str) + 1)))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	copy_valid_chars(str, system_id);
 | 
			
		||||
 | 
			
		||||
	if (!system_id[0])
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return system_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *_read_system_id_from_file(struct cmd_context *cmd, const char *file)
 | 
			
		||||
{
 | 
			
		||||
	char line[NAME_LEN + 1];
 | 
			
		||||
	FILE *fp;
 | 
			
		||||
 | 
			
		||||
	if (!file || !strlen(file) || !file[0])
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	fp = fopen(file, "r");
 | 
			
		||||
	if (!fp)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	memset(line, 0, sizeof(line));
 | 
			
		||||
 | 
			
		||||
	while (fgets(line, NAME_LEN, fp)) {
 | 
			
		||||
		if (line[0] == '#' || line[0] == '\n')
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		fclose(fp);
 | 
			
		||||
		return system_id_from_string(cmd, line);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *system_id_from_source(struct cmd_context *cmd, const char *source)
 | 
			
		||||
{
 | 
			
		||||
	struct utsname uts;
 | 
			
		||||
	char filebuf[PATH_MAX];
 | 
			
		||||
	const char *file;
 | 
			
		||||
	const char *etc_str;
 | 
			
		||||
	const char *str;
 | 
			
		||||
	char *system_id = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!strcmp(source, "uname")) {
 | 
			
		||||
		if (!uname(&uts) && strncmp(uts.nodename, "localhost", 9))
 | 
			
		||||
			system_id = system_id_from_string(cmd, uts.nodename);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* lvm.conf and lvmlocal.conf are merged into one config tree */
 | 
			
		||||
	if (!strcmp(source, "lvmlocal")) {
 | 
			
		||||
		if ((str = find_config_tree_str(cmd, local_system_id_CFG, NULL)))
 | 
			
		||||
			system_id = system_id_from_string(cmd, str);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!strcmp(source, "machineid")) {
 | 
			
		||||
		memset(filebuf, 0, sizeof(filebuf));
 | 
			
		||||
		etc_str = find_config_tree_str(cmd, global_etc_CFG, NULL);
 | 
			
		||||
		if (dm_snprintf(filebuf, sizeof(filebuf), "%s/machine-id", etc_str) >= 0)
 | 
			
		||||
			system_id = _read_system_id_from_file(cmd, filebuf);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!strcmp(source, "file")) {
 | 
			
		||||
		file = find_config_tree_str(cmd, global_system_id_file_CFG, NULL);
 | 
			
		||||
		system_id = _read_system_id_from_file(cmd, file);
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
out:
 | 
			
		||||
	return system_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _get_env_vars(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	const char *e;
 | 
			
		||||
@@ -572,7 +655,7 @@ static int _init_tags(struct cmd_context *cmd, struct dm_config_tree *cft)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _load_config_file(struct cmd_context *cmd, const char *tag)
 | 
			
		||||
static int _load_config_file(struct cmd_context *cmd, const char *tag, int local)
 | 
			
		||||
{
 | 
			
		||||
	static char config_file[PATH_MAX] = "";
 | 
			
		||||
	const char *filler = "";
 | 
			
		||||
@@ -580,6 +663,10 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
 | 
			
		||||
 | 
			
		||||
	if (*tag)
 | 
			
		||||
		filler = "_";
 | 
			
		||||
	else if (local) {
 | 
			
		||||
		filler = "";
 | 
			
		||||
		tag = "local";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
 | 
			
		||||
			 cmd->system_dir, filler, tag) < 0) {
 | 
			
		||||
@@ -607,7 +694,10 @@ static int _load_config_file(struct cmd_context *cmd, const char *tag)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Find and read first config file */
 | 
			
		||||
/*
 | 
			
		||||
 * Find and read lvm.conf and lvmlocal.conf.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static int _init_lvm_conf(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	/* No config file if LVM_SYSTEM_DIR is empty */
 | 
			
		||||
@@ -619,9 +709,11 @@ static int _init_lvm_conf(struct cmd_context *cmd)
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_load_config_file(cmd, ""))
 | 
			
		||||
	if (!_load_config_file(cmd, "", 0))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
	_load_config_file(cmd, "", 1);
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -632,7 +724,7 @@ static int _init_tag_configs(struct cmd_context *cmd)
 | 
			
		||||
 | 
			
		||||
	/* Tag list may grow while inside this loop */
 | 
			
		||||
	dm_list_iterate_items(sl, &cmd->tags) {
 | 
			
		||||
		if (!_load_config_file(cmd, sl->str))
 | 
			
		||||
		if (!_load_config_file(cmd, sl->str, 0))
 | 
			
		||||
			return_0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -1352,6 +1444,39 @@ static int _init_hostname(struct cmd_context *cmd)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_system_id(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	const char *source;
 | 
			
		||||
	int local_set;
 | 
			
		||||
 | 
			
		||||
	cmd->system_id = NULL;
 | 
			
		||||
 | 
			
		||||
	local_set = !!find_config_tree_str(cmd, local_system_id_CFG, NULL);
 | 
			
		||||
 | 
			
		||||
	source = find_config_tree_str(cmd, global_system_id_source_CFG, NULL);
 | 
			
		||||
	if (!source)
 | 
			
		||||
		source = "none";
 | 
			
		||||
 | 
			
		||||
	/* Defining local system_id but not using it is probably a config mistake. */
 | 
			
		||||
	if (local_set && strcmp(source, "lvmlocal"))
 | 
			
		||||
		log_warn("Local system_id is not used by system_id_source %s.", source);
 | 
			
		||||
 | 
			
		||||
	if (!strcmp(source, "none"))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if ((cmd->system_id = system_id_from_source(cmd, source)))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * The source failed to resolve a system_id.  In this case allow
 | 
			
		||||
	 * VGs with no system_id to be accessed, but not VGs with a system_id.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	log_warn("No system_id found from system_id_source %s.", source);
 | 
			
		||||
	cmd->unknown_system_id = 1;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _init_backup(struct cmd_context *cmd)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t days, min;
 | 
			
		||||
@@ -1580,6 +1705,9 @@ struct cmd_context *create_toolcontext(unsigned is_long_lived,
 | 
			
		||||
	if (!_init_profiles(cmd))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	if (!_init_system_id(cmd))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 | 
			
		||||
	if (!(cmd->dev_types = create_dev_types(cmd->proc_dir,
 | 
			
		||||
						find_config_tree_node(cmd, devices_types_CFG, NULL))))
 | 
			
		||||
		goto_out;
 | 
			
		||||
 
 | 
			
		||||
@@ -71,6 +71,7 @@ struct cmd_context {
 | 
			
		||||
 | 
			
		||||
	struct dm_list formats;	/* Available formats */
 | 
			
		||||
	struct dm_list segtypes;	/* Available segment types */
 | 
			
		||||
	const char *system_id;
 | 
			
		||||
	const char *hostname;
 | 
			
		||||
	const char *kernel_vsn;
 | 
			
		||||
 | 
			
		||||
@@ -95,6 +96,8 @@ struct cmd_context {
 | 
			
		||||
	unsigned threaded:1;		/* Set if running within a thread e.g. clvmd */
 | 
			
		||||
 | 
			
		||||
	unsigned independent_metadata_areas:1;	/* Active formats have MDAs outside PVs */
 | 
			
		||||
	unsigned unknown_system_id:1;
 | 
			
		||||
	unsigned include_foreign_vgs:1;
 | 
			
		||||
 | 
			
		||||
	struct dev_types *dev_types;
 | 
			
		||||
 | 
			
		||||
@@ -160,4 +163,7 @@ int init_lvmcache_orphans(struct cmd_context *cmd);
 | 
			
		||||
 | 
			
		||||
struct format_type *get_format_by_name(struct cmd_context *cmd, const char *format);
 | 
			
		||||
 | 
			
		||||
char *system_id_from_source(struct cmd_context *cmd, const char *system_id_source);
 | 
			
		||||
char *system_id_from_string(struct cmd_context *cmd, const char *system_id_string);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -82,6 +82,7 @@ cfg_section(metadata_CFG_SECTION, "metadata", root_CFG_SECTION, CFG_ADVANCED, vs
 | 
			
		||||
cfg_section(report_CFG_SECTION, "report", root_CFG_SECTION, CFG_ADVANCED | CFG_PROFILABLE, vsn(1, 0, 0), NULL)
 | 
			
		||||
cfg_section(dmeventd_CFG_SECTION, "dmeventd", root_CFG_SECTION, 0, vsn(1, 2, 3), NULL)
 | 
			
		||||
cfg_section(tags_CFG_SECTION, "tags", root_CFG_SECTION, 0, vsn(1, 0, 18), NULL)
 | 
			
		||||
cfg_section(local_CFG_SECTION, "local", root_CFG_SECTION, 0, vsn(2, 2, 117), NULL)
 | 
			
		||||
 | 
			
		||||
cfg(config_checks_CFG, "checks", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 1, vsn(2, 2, 99), "Configuration tree check on each LVM command execution.")
 | 
			
		||||
cfg(config_abort_on_errors_CFG, "abort_on_errors", config_CFG_SECTION, 0, CFG_TYPE_BOOL, 0, vsn(2,2,99), "Abort LVM command execution if configuration is invalid.")
 | 
			
		||||
@@ -164,6 +165,7 @@ cfg(global_format_CFG, "format", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT
 | 
			
		||||
cfg_array(global_format_libraries_CFG, "format_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 0), NULL)
 | 
			
		||||
cfg_array(global_segment_libraries_CFG, "segment_libraries", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL)
 | 
			
		||||
cfg(global_proc_CFG, "proc", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_PROC_DIR, vsn(1, 0, 0), NULL)
 | 
			
		||||
cfg(global_etc_CFG, "etc", global_CFG_SECTION, 0, CFG_TYPE_STRING, DEFAULT_ETC_DIR, vsn(2, 2, 117), NULL)
 | 
			
		||||
cfg(global_locking_type_CFG, "locking_type", global_CFG_SECTION, 0, CFG_TYPE_INT, 1, vsn(1, 0, 0), NULL)
 | 
			
		||||
cfg(global_wait_for_locks_CFG, "wait_for_locks", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_WAIT_FOR_LOCKS, vsn(2, 2, 50), NULL)
 | 
			
		||||
cfg(global_fallback_to_clustered_locking_CFG, "fallback_to_clustered_locking", global_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_FALLBACK_TO_CLUSTERED_LOCKING, vsn(2, 2, 42), NULL)
 | 
			
		||||
@@ -191,6 +193,8 @@ cfg_array(global_cache_check_options_CFG, "cache_check_options", global_CFG_SECT
 | 
			
		||||
cfg(global_cache_dump_executable_CFG, "cache_dump_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, CACHE_DUMP_CMD, vsn(2, 2, 108), NULL)
 | 
			
		||||
cfg(global_cache_repair_executable_CFG, "cache_repair_executable", global_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, CACHE_REPAIR_CMD, vsn(2, 2, 108), NULL)
 | 
			
		||||
cfg_array(global_cache_repair_options_CFG, "cache_repair_options", global_CFG_SECTION, 0, CFG_TYPE_STRING, "#S" DEFAULT_CACHE_REPAIR_OPTIONS, vsn(2, 2, 108), NULL)
 | 
			
		||||
cfg(global_system_id_source_CFG, "system_id_source", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 117), NULL)
 | 
			
		||||
cfg(global_system_id_file_CFG, "system_id_file", global_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 117), NULL)
 | 
			
		||||
 | 
			
		||||
cfg(activation_checks_CFG, "checks", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_ACTIVATION_CHECKS, vsn(2, 2, 86), NULL)
 | 
			
		||||
cfg(activation_udev_sync_CFG, "udev_sync", activation_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_UDEV_SYNC, vsn(2, 2, 51), NULL)
 | 
			
		||||
@@ -277,4 +281,7 @@ cfg(tags_hosttags_CFG, "hosttags", tags_CFG_SECTION, 0, CFG_TYPE_BOOL, DEFAULT_H
 | 
			
		||||
cfg_section(tag_CFG_SUBSECTION, "tag", tags_CFG_SECTION, CFG_NAME_VARIABLE | CFG_DEFAULT_UNDEFINED, vsn(1, 0, 18), NULL)
 | 
			
		||||
cfg(tag_host_list_CFG, "host_list", tag_CFG_SUBSECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(1, 0, 18), NULL)
 | 
			
		||||
 | 
			
		||||
cfg(local_system_id_CFG, "system_id", local_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 117), NULL)
 | 
			
		||||
cfg_array(local_allow_system_id_CFG, "allow_system_id", local_CFG_SECTION, CFG_DEFAULT_UNDEFINED, CFG_TYPE_STRING, NULL, vsn(2, 2, 117), NULL)
 | 
			
		||||
 | 
			
		||||
cfg(CFG_COUNT, NULL, root_CFG_SECTION, 0, CFG_TYPE_INT, 0, vsn(0, 0, 0), NULL)
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_DEV_DIR "/dev"
 | 
			
		||||
#define DEFAULT_PROC_DIR "/proc"
 | 
			
		||||
#define DEFAULT_ETC_DIR "/etc"
 | 
			
		||||
#define DEFAULT_OBTAIN_DEVICE_LIST_FROM_UDEV 1
 | 
			
		||||
#define DEFAULT_EXTERNAL_DEVICE_INFO_SOURCE "none"
 | 
			
		||||
#define DEFAULT_SYSFS_SCAN 1
 | 
			
		||||
 
 | 
			
		||||
@@ -125,6 +125,7 @@ int import_pv(const struct format_type *fmt, struct dm_pool *mem,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@@ -136,6 +137,7 @@ static int _system_id(struct cmd_context *cmd, char *s, const char *prefix)
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute__((unused)),
 | 
			
		||||
	      struct volume_group *vg,
 | 
			
		||||
@@ -156,11 +158,14 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute__((unused
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Preserve existing system_id if it exists */
 | 
			
		||||
#if 0
 | 
			
		||||
	if (vg && *vg->system_id)
 | 
			
		||||
		strncpy((char *)pvd->system_id, vg->system_id, sizeof(pvd->system_id));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* Is VG already exported or being exported? */
 | 
			
		||||
	if (vg && vg_is_exported(vg)) {
 | 
			
		||||
#if 0
 | 
			
		||||
		/* Does system_id need setting? */
 | 
			
		||||
		if (!*vg->system_id ||
 | 
			
		||||
		    strncmp(vg->system_id, EXPORTED_TAG,
 | 
			
		||||
@@ -168,6 +173,7 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute__((unused
 | 
			
		||||
			if (!_system_id(cmd, (char *)pvd->system_id, EXPORTED_TAG))
 | 
			
		||||
				return_0;
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
		if (strlen((char *)pvd->vg_name) + sizeof(EXPORTED_TAG) >
 | 
			
		||||
		    sizeof(pvd->vg_name)) {
 | 
			
		||||
			log_error("Volume group name %s too long to export",
 | 
			
		||||
@@ -177,6 +183,7 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute__((unused
 | 
			
		||||
		strcat((char *)pvd->vg_name, EXPORTED_TAG);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	/* Is VG being imported? */
 | 
			
		||||
	if (vg && !vg_is_exported(vg) && *vg->system_id &&
 | 
			
		||||
	    !strncmp(vg->system_id, EXPORTED_TAG, sizeof(EXPORTED_TAG) - 1)) {
 | 
			
		||||
@@ -194,6 +201,7 @@ int export_pv(struct cmd_context *cmd, struct dm_pool *mem __attribute__((unused
 | 
			
		||||
	    (!*vg->system_id ||
 | 
			
		||||
	     strncmp(vg->system_id, (char *)pvd->system_id, sizeof(pvd->system_id))))
 | 
			
		||||
		    strncpy(vg->system_id, (char *)pvd->system_id, NAME_LEN);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	//pvd->pv_major = MAJOR(pv->dev);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -166,6 +166,7 @@
 | 
			
		||||
#define FAILED_ALLOCATION	0x00000080U
 | 
			
		||||
#define FAILED_EXIST		0x00000100U
 | 
			
		||||
#define FAILED_RECOVERY		0x00000200U
 | 
			
		||||
#define FAILED_SYSTEMID		0x00000400U
 | 
			
		||||
#define SUCCESS			0x00000000U
 | 
			
		||||
 | 
			
		||||
#define VGMETADATACOPIES_ALL UINT32_MAX
 | 
			
		||||
@@ -1177,6 +1178,7 @@ struct vgcreate_params {
 | 
			
		||||
	alloc_policy_t alloc;
 | 
			
		||||
	int clustered; /* FIXME: put this into a 'status' variable instead? */
 | 
			
		||||
	uint32_t vgmetadatacopies;
 | 
			
		||||
	const char *system_id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int validate_major_minor(const struct cmd_context *cmd,
 | 
			
		||||
 
 | 
			
		||||
@@ -4285,6 +4285,122 @@ static struct volume_group *_recover_vg(struct cmd_context *cmd,
 | 
			
		||||
	return (struct volume_group *)vg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int allow_system_id(struct cmd_context *cmd, const char *system_id)
 | 
			
		||||
{
 | 
			
		||||
	const struct dm_config_node *cn;
 | 
			
		||||
	const struct dm_config_value *cv;
 | 
			
		||||
	const char *str;
 | 
			
		||||
 | 
			
		||||
	if (!(cn = find_config_tree_node(cmd, local_allow_system_id_CFG, NULL)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	for (cv = cn->v; cv; cv = cv->next) {
 | 
			
		||||
		if (cv->type == DM_CFG_EMPTY_ARRAY)
 | 
			
		||||
			break;
 | 
			
		||||
		if (cv->type != DM_CFG_STRING) {
 | 
			
		||||
			log_error("Ignoring invalid string in allow_system_id list");
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		str = cv->v.str;
 | 
			
		||||
		if (!*str) {
 | 
			
		||||
			log_error("Ignoring empty string in config file");
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!strcmp(str, system_id))
 | 
			
		||||
			return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _access_vg_clustered(struct cmd_context *cmd, struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	if (vg_is_clustered(vg) && !locking_is_clustered()) {
 | 
			
		||||
		if (!cmd->ignore_clustered_vgs)
 | 
			
		||||
			log_error("Skipping clustered volume group %s", vg->name);
 | 
			
		||||
		else
 | 
			
		||||
			log_verbose("Skipping clustered volume group %s", vg->name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _access_vg_systemid(struct cmd_context *cmd, struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * A VG without a system_id can be accessed by anyone.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!vg->system_id || !vg->system_id[0])
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * We sometimes want to report foreign vgs.
 | 
			
		||||
	 */
 | 
			
		||||
	if (cmd->include_foreign_vgs)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Allow VG access if the local host has active LVs in it.
 | 
			
		||||
	 */
 | 
			
		||||
	if (lvs_in_vg_activated(vg)) {
 | 
			
		||||
		log_error("LVs should not be active in VG %s with foreign system id \"%s\"",
 | 
			
		||||
			  vg->name, vg->system_id);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * A host without a system_id cannot access a VG with a system_id.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!cmd->system_id || cmd->unknown_system_id) {
 | 
			
		||||
		log_warn("Cannot access VG %s with system id \"%s\" with unknown local system id.",
 | 
			
		||||
			 vg->name, vg->system_id);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * A host can access a VG with a matching system_id.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!strcmp(vg->system_id, cmd->system_id))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * A host can access a VG if the VG's system_id is in the allow list.
 | 
			
		||||
	 */
 | 
			
		||||
	if (allow_system_id(cmd, vg->system_id))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Silently ignore foreign VGs.  They will only cause the
 | 
			
		||||
	 * command to fail if they were named as explicit command
 | 
			
		||||
	 * args, in which case the command will fail indicating the
 | 
			
		||||
	 * VG was not found.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * FIXME: move _vg_bad_status_bits() checks in here.
 | 
			
		||||
 */
 | 
			
		||||
static int _access_vg(struct cmd_context *cmd, struct volume_group *vg, uint32_t *failure)
 | 
			
		||||
{
 | 
			
		||||
	if (!is_real_vg(vg->name))
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	if (!_access_vg_clustered(cmd, vg)) {
 | 
			
		||||
		*failure |= FAILED_CLUSTERED;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_access_vg_systemid(cmd, vg)) {
 | 
			
		||||
		*failure |= FAILED_SYSTEMID;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Consolidated locking, reading, and status flag checking.
 | 
			
		||||
 *
 | 
			
		||||
@@ -4344,14 +4460,8 @@ static struct volume_group *_vg_lock_and_read(struct cmd_context *cmd, const cha
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (vg_is_clustered(vg) && !locking_is_clustered()) {
 | 
			
		||||
		if (!cmd->ignore_clustered_vgs)
 | 
			
		||||
			log_error("Skipping clustered volume group %s", vg->name);
 | 
			
		||||
		else
 | 
			
		||||
			log_verbose("Skipping clustered volume group %s", vg->name);
 | 
			
		||||
		failure |= FAILED_CLUSTERED;
 | 
			
		||||
	if (!_access_vg(cmd, vg, &failure))
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* consistent == 0 when VG is not found, but failed == FAILED_NOTFOUND */
 | 
			
		||||
	if (!consistent && !failure) {
 | 
			
		||||
 
 | 
			
		||||
@@ -601,6 +601,22 @@ int vg_set_clustered(struct volume_group *vg, int clustered)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* The input string has already been validated. */
 | 
			
		||||
 | 
			
		||||
int vg_set_system_id(struct volume_group *vg, const char *system_id)
 | 
			
		||||
{
 | 
			
		||||
	if (!system_id) {
 | 
			
		||||
		vg->system_id = NULL;
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!(vg->system_id = dm_pool_strdup(vg->vgmem, system_id))) {
 | 
			
		||||
		log_error("vg_set_system_id no mem");
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *vg_attr_dup(struct dm_pool *mem, const struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	char *repstr;
 | 
			
		||||
 
 | 
			
		||||
@@ -144,6 +144,7 @@ uint32_t vg_seqno(const struct volume_group *vg);
 | 
			
		||||
uint64_t vg_status(const struct volume_group *vg);
 | 
			
		||||
int vg_set_alloc_policy(struct volume_group *vg, alloc_policy_t alloc);
 | 
			
		||||
int vg_set_clustered(struct volume_group *vg, int clustered);
 | 
			
		||||
int vg_set_system_id(struct volume_group *vg, const char *system_id);
 | 
			
		||||
uint64_t vg_size(const struct volume_group *vg);
 | 
			
		||||
uint64_t vg_free(const struct volume_group *vg);
 | 
			
		||||
uint64_t vg_extent_size(const struct volume_group *vg);
 | 
			
		||||
 
 | 
			
		||||
@@ -101,6 +101,41 @@ int validate_name(const char *n)
 | 
			
		||||
	return (_validate_name(n) == NAME_VALID) ? 1 : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copy valid characters from source to destination.
 | 
			
		||||
 * Invalid characters are skipped.  Copying is stopped
 | 
			
		||||
 * when NAME_LEN characters have been copied.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
void copy_valid_chars(const char *src, char *dst)
 | 
			
		||||
{
 | 
			
		||||
	const char *s = src;
 | 
			
		||||
	char *d = dst;
 | 
			
		||||
	int len = 0;
 | 
			
		||||
	int i;
 | 
			
		||||
	char c;
 | 
			
		||||
 | 
			
		||||
	if (!s || !*s)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < strlen(src); i++) {
 | 
			
		||||
		c = *s;
 | 
			
		||||
 | 
			
		||||
		if (!isalnum(c) && c != '.' && c != '_' && c != '-' && c != '+') {
 | 
			
		||||
			s++;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		*d = *s;
 | 
			
		||||
		d++;
 | 
			
		||||
		s++;
 | 
			
		||||
		len++;
 | 
			
		||||
 | 
			
		||||
		if (len == NAME_LEN)
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *_lvname_has_reserved_prefix(const char *lvname)
 | 
			
		||||
{
 | 
			
		||||
	static const char _prefixes[][12] = {
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,8 @@ int validate_name(const char *n);
 | 
			
		||||
name_error_t validate_name_detailed(const char *n);
 | 
			
		||||
int validate_tag(const char *n);
 | 
			
		||||
 | 
			
		||||
void copy_valid_chars(const char *src, char *dst);
 | 
			
		||||
 | 
			
		||||
int apply_lvname_restrictions(const char *name);
 | 
			
		||||
int is_reserved_lvname(const char *name);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -139,7 +139,8 @@ FIELD(VGS, vg, STR, "AllocPol", cmd, 10, vgallocationpolicy, vg_allocation_polic
 | 
			
		||||
FIELD(VGS, vg, BIN, "Clustered", cmd, 10, vgclustered, vg_clustered, "Set if VG is clustered.", 0)
 | 
			
		||||
FIELD(VGS, vg, SIZ, "VSize", cmd, 5, vgsize, vg_size, "Total size of VG in current units.", 0)
 | 
			
		||||
FIELD(VGS, vg, SIZ, "VFree", cmd, 5, vgfree, vg_free, "Total amount of free space in current units.", 0)
 | 
			
		||||
FIELD(VGS, vg, STR, "SYS ID", system_id, 6, string, vg_sysid, "System ID indicating when and where it was created.", 0)
 | 
			
		||||
FIELD(VGS, vg, STR, "SYS ID", system_id, 6, string, vg_sysid, "System ID of the VG indicating its owner.", 0)
 | 
			
		||||
FIELD(VGS, vg, STR, "System ID", system_id, 9, string, vg_systemid, "System ID of the VG indicating its owner.", 0)
 | 
			
		||||
FIELD(VGS, vg, SIZ, "Ext", extent_size, 3, size32, vg_extent_size, "Size of Physical Extents in current units.", 0)
 | 
			
		||||
FIELD(VGS, vg, NUM, "#Ext", extent_count, 4, uint32, vg_extent_count, "Total number of Physical Extents.", 0)
 | 
			
		||||
FIELD(VGS, vg, NUM, "Free", free_count, 4, uint32, vg_free_count, "Total number of unallocated Physical Extents.", 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -362,6 +362,8 @@ GET_VG_NUM_PROPERTY_FN(vg_free, (SECTOR_SIZE * vg_free(vg)))
 | 
			
		||||
#define _vg_free_set prop_not_implemented_set
 | 
			
		||||
GET_VG_STR_PROPERTY_FN(vg_sysid, vg_system_id_dup(vg))
 | 
			
		||||
#define _vg_sysid_set prop_not_implemented_set
 | 
			
		||||
GET_VG_STR_PROPERTY_FN(vg_systemid, vg_system_id_dup(vg))
 | 
			
		||||
#define _vg_systemid_set prop_not_implemented_set
 | 
			
		||||
GET_VG_NUM_PROPERTY_FN(vg_extent_size, (SECTOR_SIZE * vg->extent_size))
 | 
			
		||||
#define _vg_extent_size_set prop_not_implemented_set
 | 
			
		||||
GET_VG_NUM_PROPERTY_FN(vg_extent_count, vg->extent_count)
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ LVMETAD =
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
MAN5=lvm.conf.5
 | 
			
		||||
MAN7=
 | 
			
		||||
MAN7=lvmsystemid.7
 | 
			
		||||
MAN8=lvm-dumpconfig.8 \
 | 
			
		||||
	lvchange.8 lvconvert.8 lvcreate.8 lvdisplay.8 lvextend.8 lvm.8 \
 | 
			
		||||
	lvmchange.8 lvmconf.8 lvmdiskscan.8 lvmdump.8 lvmsadc.8 lvmsar.8 \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										284
									
								
								man/lvmsystemid.7.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								man/lvmsystemid.7.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,284 @@
 | 
			
		||||
.TH "LVMSYSTEMID" "7" "LVM TOOLS #VERSION#" "Red Hat, Inc" "\""
 | 
			
		||||
 | 
			
		||||
.SH NAME
 | 
			
		||||
lvmsystemid \(em LVM system id
 | 
			
		||||
 | 
			
		||||
.SH DESCRIPTION
 | 
			
		||||
 | 
			
		||||
Local VG's may exist on shared storage where they are visible to multiple
 | 
			
		||||
hosts.  These VG's are intended to be used by only a single machine, even
 | 
			
		||||
though they are visible to many.  A system_id identifying a single host
 | 
			
		||||
can be assigned to a VG to indicate the VG's owner.  The VG owner can use
 | 
			
		||||
the VG as usual, and all other hosts will ignore it.  This protects the VG
 | 
			
		||||
from accidental use by other hosts.
 | 
			
		||||
 | 
			
		||||
The system_id is not a dynamic property, and can only be changed in very
 | 
			
		||||
limited circumstances (see vgexport and vgimport).  Even limited changes
 | 
			
		||||
to the VG system_id are not perfectly reflected across hosts.  A more
 | 
			
		||||
coherent view of shared storage requires using an inter-host locking
 | 
			
		||||
system to coordinate access and update caches.
 | 
			
		||||
 | 
			
		||||
The system_id is a string uniquely identifying a host.  It can be manually
 | 
			
		||||
set to a custom value or it can be assigned automatically by lvm using a
 | 
			
		||||
unique identifier already available on the host, e.g. machine-id or uname.
 | 
			
		||||
 | 
			
		||||
In vgcreate, the local system_id is saved in the new VG metadata.  The
 | 
			
		||||
local host owns the new VG, and other hosts will ignore it.
 | 
			
		||||
 | 
			
		||||
A VG without a system_id can be used by any host, and a VG with a
 | 
			
		||||
system_id can only be used by a host with a matching system_id.  A
 | 
			
		||||
"foreign VG" is a VG with a system_id as viewed by a host with a system_id
 | 
			
		||||
that does not match the VG's system_id.  (Or from a host without a
 | 
			
		||||
system_id.)
 | 
			
		||||
 | 
			
		||||
To benefit fully from system_id, all hosts must have system_id set, and
 | 
			
		||||
VGs must have system_id set.  Two hosts should not be assigned the same
 | 
			
		||||
system_id.  Doing so defeats the purpose of the system_id.
 | 
			
		||||
 | 
			
		||||
Valid system_id characters are the same as valid VG name characters.  If a
 | 
			
		||||
system_id contains invalid characters, those characters are omitted and
 | 
			
		||||
remaining characters are used.  If a system_id is longer than the maximum
 | 
			
		||||
name length, the characters up to the maximum length are used.  The
 | 
			
		||||
maximum length of a system_id is 128 characters.
 | 
			
		||||
 | 
			
		||||
.SS Types of VG access
 | 
			
		||||
A "local VG" is meant to be used by a single host.
 | 
			
		||||
.br
 | 
			
		||||
A "shared VG" is meant to be used by multiple hosts.
 | 
			
		||||
.br
 | 
			
		||||
These can be further distinguished as:
 | 
			
		||||
 | 
			
		||||
.B Unrestricted:
 | 
			
		||||
A local VG that has no system_id.  This VG type is unprotected and
 | 
			
		||||
accessible to any host.
 | 
			
		||||
 | 
			
		||||
.B Owned:
 | 
			
		||||
A local VG that has a system_id set, as viewed from the one host with a
 | 
			
		||||
matching system_id (the owner).  This VG type is by definition acessible.
 | 
			
		||||
 | 
			
		||||
.B Foreign:
 | 
			
		||||
A local VG that has a system_id set, as viewed from any host with an
 | 
			
		||||
unmatching system_id (or no system_id).  It is owned by another host.
 | 
			
		||||
This VG type is by definition not accessible.
 | 
			
		||||
 | 
			
		||||
.B Exported:
 | 
			
		||||
A local VG that has been exported with vgexport and has no system_id.
 | 
			
		||||
This VG type can only be accessed by vgimport which will change it to
 | 
			
		||||
owned.
 | 
			
		||||
 | 
			
		||||
.B Clustered:
 | 
			
		||||
A shared VG with the clustered flag set, and no system_id.  This VG type
 | 
			
		||||
is only accessible to hosts using clvmd.
 | 
			
		||||
 | 
			
		||||
.SS system_id_source
 | 
			
		||||
 | 
			
		||||
A host's own system_id can be defined in a number of ways.  lvm.conf
 | 
			
		||||
global/system_id_source defines the method lvm will use to find the local
 | 
			
		||||
system_id:
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B none
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
lvm will not use a system_id.  lvm is allowed to access VGs without a
 | 
			
		||||
system_id, and will create new VGs without a system_id.  An undefined
 | 
			
		||||
system_id_source is equivalent to none.
 | 
			
		||||
 | 
			
		||||
.I lvm.conf
 | 
			
		||||
.nf
 | 
			
		||||
global {
 | 
			
		||||
    system_id_source = "none"
 | 
			
		||||
}
 | 
			
		||||
.fi
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B machineid
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
The content of /etc/machine-id is used as the system_id if available.
 | 
			
		||||
See
 | 
			
		||||
.BR machine-id (5)
 | 
			
		||||
and
 | 
			
		||||
.BR systemd-machine-id-setup (1)
 | 
			
		||||
to check if machine-id is available on the host.
 | 
			
		||||
 | 
			
		||||
.I lvm.conf
 | 
			
		||||
.nf
 | 
			
		||||
global {
 | 
			
		||||
    system_id_source = "machineid"
 | 
			
		||||
}
 | 
			
		||||
.fi
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B uname
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
The string utsname.nodename from
 | 
			
		||||
.BR uname (2)
 | 
			
		||||
is used as the system_id.  A uname beginning with "localhost"
 | 
			
		||||
is ignored and equivalent to none.
 | 
			
		||||
 | 
			
		||||
.I lvm.conf
 | 
			
		||||
.nf
 | 
			
		||||
global {
 | 
			
		||||
    system_id_source = "uname"
 | 
			
		||||
}
 | 
			
		||||
.fi
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B lvmlocal
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
The system_id is defined in lvmlocal.conf local/system_id.
 | 
			
		||||
 | 
			
		||||
.I lvm.conf
 | 
			
		||||
.nf
 | 
			
		||||
global {
 | 
			
		||||
    system_id_source = "lvmlocal"
 | 
			
		||||
}
 | 
			
		||||
.fi
 | 
			
		||||
 | 
			
		||||
.I lvmlocal.conf
 | 
			
		||||
.nf
 | 
			
		||||
local {
 | 
			
		||||
    system_id = "example_name"
 | 
			
		||||
}
 | 
			
		||||
.fi
 | 
			
		||||
 | 
			
		||||
.TP
 | 
			
		||||
.B file
 | 
			
		||||
.br
 | 
			
		||||
 | 
			
		||||
The system_id is defined in a file specified by lvm.conf
 | 
			
		||||
global/system_id_file.
 | 
			
		||||
 | 
			
		||||
.I lvm.conf
 | 
			
		||||
.nf
 | 
			
		||||
global {
 | 
			
		||||
    system_id_source = "file"
 | 
			
		||||
    system_id_file = "/path/to/file"
 | 
			
		||||
}
 | 
			
		||||
.fi
 | 
			
		||||
 | 
			
		||||
.LP
 | 
			
		||||
 | 
			
		||||
Changing system_id_source will often cause the system_id to change, which
 | 
			
		||||
may prevent the host from using VGs that it previously used (see
 | 
			
		||||
allow_system_id below to handle this.)
 | 
			
		||||
 | 
			
		||||
If a system_id_source other than none fails to resolve a system_id, the
 | 
			
		||||
host will be allowed to access VGs with no system_id, but will not be
 | 
			
		||||
allowed to access VGs with a defined system_id.
 | 
			
		||||
 | 
			
		||||
.SS allow_system_id
 | 
			
		||||
 | 
			
		||||
In some cases, it may be useful for a host to access VGs with different
 | 
			
		||||
system_id's, e.g. if a host's system_id changes, and it wants to use VGs
 | 
			
		||||
that it created with its old system_id.  To allow a host to access VGs
 | 
			
		||||
with other system_id's, those other system_id's can be listed in
 | 
			
		||||
lvmlocal.conf local/allow_system_id.
 | 
			
		||||
 | 
			
		||||
.I lvmlocal.conf
 | 
			
		||||
.nf
 | 
			
		||||
local {
 | 
			
		||||
    allow_system_id = [ "my_other_name" ]
 | 
			
		||||
}
 | 
			
		||||
.fi
 | 
			
		||||
 | 
			
		||||
.SS vgcreate
 | 
			
		||||
 | 
			
		||||
In vgcreate, a host sets its own system_id in the VG metadata.
 | 
			
		||||
To override this and set another system_id:
 | 
			
		||||
 | 
			
		||||
.B vgcreate --systemid
 | 
			
		||||
.I SystemID VG Devices
 | 
			
		||||
 | 
			
		||||
Overriding the system_id makes it possible for a host to create a VG that
 | 
			
		||||
it may not be able to use.  Another host with a system_id matching the one
 | 
			
		||||
specified may not recognize the new VG without manually rescanning
 | 
			
		||||
devices.
 | 
			
		||||
 | 
			
		||||
.SS report/display
 | 
			
		||||
 | 
			
		||||
The system_id of a VG is displayed with the "systemid" reporting option.
 | 
			
		||||
 | 
			
		||||
Report/display commands ignore foreign VGs by default.  To report foreign
 | 
			
		||||
VGs, the --foreign option can be used.  This causes all VGs to be read
 | 
			
		||||
from disk.
 | 
			
		||||
 | 
			
		||||
.B vgs --foreign -o+systemid
 | 
			
		||||
 | 
			
		||||
When a host with no system_id sees foreign VGs, it warns about them as
 | 
			
		||||
they are skipped.  The host should be assigned a system_id, after which
 | 
			
		||||
standard reporting commands will silently ignore foreign VGs.
 | 
			
		||||
 | 
			
		||||
.SS vgexport/vgimport
 | 
			
		||||
 | 
			
		||||
vgexport clears the system_id.
 | 
			
		||||
 | 
			
		||||
Other hosts will continue to see a newly exported VG as foreign because of
 | 
			
		||||
local caching (when lvmetad is used).  Manually updating the local lvmetad
 | 
			
		||||
cache with pvscan --cache will allow a host to recognize the newly
 | 
			
		||||
exported VG.
 | 
			
		||||
 | 
			
		||||
vgimport sets the VG system_id to the local system_id as determined by
 | 
			
		||||
lvm.conf system_id_sources.  vgimport automatically scans storage for
 | 
			
		||||
newly exported VGs.
 | 
			
		||||
 | 
			
		||||
After vgimport, the exporting host will continue to see the VG as
 | 
			
		||||
exported, and not owned by the new host.  Manually updating the local
 | 
			
		||||
cache with pvscan --cache will allow a host to recognize the newly
 | 
			
		||||
imported VG as foreign.
 | 
			
		||||
 | 
			
		||||
.SS vgchange
 | 
			
		||||
 | 
			
		||||
If a VG has a system_id, changing it with vgchange requires --force.
 | 
			
		||||
vgchange --systemid is accepted just as with vgcreate.
 | 
			
		||||
 | 
			
		||||
If a host's system_id is changed, the system_id of its own VG's can be
 | 
			
		||||
changed to match.  Using allow_system_id is a way to avoid using force
 | 
			
		||||
with vgchange.
 | 
			
		||||
 | 
			
		||||
To move a VG from one host to another, vgexport and vgimport should be
 | 
			
		||||
used.
 | 
			
		||||
 | 
			
		||||
.SS clustered VGs
 | 
			
		||||
 | 
			
		||||
A "clustered" VG should have no system_id set, allowing multiple hosts to
 | 
			
		||||
use it via clvm.  Changing a VG to clustered will clear the existing
 | 
			
		||||
system_id.  Changing a VG to not clustered will set the system_id to the
 | 
			
		||||
host running the vgchange command.
 | 
			
		||||
 | 
			
		||||
.SS creation_host
 | 
			
		||||
 | 
			
		||||
In vgcreate, the VG metadata field creation_host is set by default to the
 | 
			
		||||
host's uname.  The creation_host cannot be changed, and is not used to
 | 
			
		||||
control access.  When system_id_source is "uname", the system_id and
 | 
			
		||||
creation_host will be the same.
 | 
			
		||||
 | 
			
		||||
.SS orphans
 | 
			
		||||
 | 
			
		||||
Orphan PVs are unused devices; they are not currently used in any VG.
 | 
			
		||||
Because of this, they are not protected by a system_id, and any host can
 | 
			
		||||
use them.  Coodination of changes to orphan PVs is beyond the scope of
 | 
			
		||||
system_id.  The same is true of any block device that is not a PV.
 | 
			
		||||
 | 
			
		||||
The effects of this are especially evident when lvm uses lvmetad caching.
 | 
			
		||||
For example, if multiple hosts see an orphan PV, and one host creates a VG
 | 
			
		||||
using the orphan, the other hosts will continue to report the PV as an
 | 
			
		||||
orphan.  Nothing would automatically prevent the other hosts from using
 | 
			
		||||
the newly allocated PV.  If the other hosts run a command to rescan
 | 
			
		||||
devices, and update lvmetad, they would then recognize the PV has become
 | 
			
		||||
used by another host.  A command that rescans devices could be pvscan
 | 
			
		||||
--cache, or vgs --foreign.
 | 
			
		||||
 | 
			
		||||
.SH SEE ALSO
 | 
			
		||||
.BR vgcreate (8),
 | 
			
		||||
.BR vgchange (8),
 | 
			
		||||
.BR vgimport (8),
 | 
			
		||||
.BR vgexport (8),
 | 
			
		||||
.BR lvm.conf (5),
 | 
			
		||||
.BR machine-id (5),
 | 
			
		||||
.BR uname (2),
 | 
			
		||||
.BR vgs (8)
 | 
			
		||||
 | 
			
		||||
@@ -41,6 +41,7 @@ arg(discards_ARG, '\0', "discards", discards_arg, 0)
 | 
			
		||||
arg(driverloaded_ARG, '\0', "driverloaded", yes_no_arg, 0)
 | 
			
		||||
arg(errorwhenfull_ARG, '\0', "errorwhenfull", yes_no_arg, 0)
 | 
			
		||||
arg(force_long_ARG, '\0', "force", NULL, ARG_COUNTABLE)
 | 
			
		||||
arg(foreign_ARG, '\0', "foreign", NULL, 0)
 | 
			
		||||
arg(ignoreadvanced_ARG, '\0', "ignoreadvanced", NULL, 0)
 | 
			
		||||
arg(ignorelockingfailure_ARG, '\0', "ignorelockingfailure", NULL, 0)
 | 
			
		||||
arg(ignoremonitoring_ARG, '\0', "ignoremonitoring", NULL, 0)
 | 
			
		||||
@@ -99,6 +100,7 @@ arg(splitsnapshot_ARG, '\0', "splitsnapshot", NULL, 0)
 | 
			
		||||
arg(stripes_long_ARG, '\0', "stripes", int_arg, 0)
 | 
			
		||||
arg(syncaction_ARG, '\0', "syncaction", string_arg, 0)	/* FIXME Use custom validation fn */
 | 
			
		||||
arg(sysinit_ARG, '\0', "sysinit", NULL, 0)
 | 
			
		||||
arg(systemid_ARG, '\0', "systemid", string_arg, 0)
 | 
			
		||||
arg(thinpool_ARG, '\0', "thinpool", string_arg, 0)
 | 
			
		||||
arg(trackchanges_ARG, '\0', "trackchanges", NULL, 0)
 | 
			
		||||
arg(trustcache_ARG, '\0', "trustcache", NULL, 0)
 | 
			
		||||
 
 | 
			
		||||
@@ -975,7 +975,7 @@ xx(vgchange,
 | 
			
		||||
   metadataprofile_ARG, monitor_ARG, noudevsync_ARG, metadatacopies_ARG,
 | 
			
		||||
   vgmetadatacopies_ARG, partial_ARG, physicalextentsize_ARG, poll_ARG,
 | 
			
		||||
   refresh_ARG, resizeable_ARG, resizable_ARG, select_ARG, sysinit_ARG,
 | 
			
		||||
   test_ARG, uuid_ARG)
 | 
			
		||||
   systemid_ARG, test_ARG, uuid_ARG)
 | 
			
		||||
 | 
			
		||||
xx(vgck,
 | 
			
		||||
   "Check the consistency of volume group(s)",
 | 
			
		||||
@@ -1037,7 +1037,8 @@ xx(vgcreate,
 | 
			
		||||
   maxphysicalvolumes_ARG, metadataprofile_ARG, metadatatype_ARG,
 | 
			
		||||
   physicalextentsize_ARG, test_ARG, force_ARG, zero_ARG, labelsector_ARG,
 | 
			
		||||
   metadatasize_ARG, pvmetadatacopies_ARG, metadatacopies_ARG,
 | 
			
		||||
   vgmetadatacopies_ARG, dataalignment_ARG, dataalignmentoffset_ARG)
 | 
			
		||||
   vgmetadatacopies_ARG, dataalignment_ARG, dataalignmentoffset_ARG,
 | 
			
		||||
   systemid_ARG)
 | 
			
		||||
 | 
			
		||||
xx(vgdisplay,
 | 
			
		||||
   "Display volume group information",
 | 
			
		||||
@@ -1259,7 +1260,7 @@ xx(vgs,
 | 
			
		||||
   ignoreskippedcluster_ARG, nameprefixes_ARG, noheadings_ARG,
 | 
			
		||||
   nolocking_ARG, nosuffix_ARG, options_ARG, partial_ARG,
 | 
			
		||||
   readonly_ARG, rows_ARG, select_ARG, separator_ARG, sort_ARG,
 | 
			
		||||
   trustcache_ARG, unbuffered_ARG, units_ARG, unquoted_ARG)
 | 
			
		||||
   trustcache_ARG, unbuffered_ARG, units_ARG, unquoted_ARG, foreign_ARG)
 | 
			
		||||
 | 
			
		||||
xx(vgscan,
 | 
			
		||||
   "Search for all volume groups",
 | 
			
		||||
 
 | 
			
		||||
@@ -382,14 +382,6 @@ static int _pvs_in_vg(struct cmd_context *cmd, const char *vg_name,
 | 
			
		||||
		      struct volume_group *vg,
 | 
			
		||||
		      struct processing_handle *handle)
 | 
			
		||||
{
 | 
			
		||||
	int skip;
 | 
			
		||||
 | 
			
		||||
	if (ignore_vg(vg, vg_name, 0, &skip))
 | 
			
		||||
		return_ECMD_FAILED;
 | 
			
		||||
 | 
			
		||||
	if (skip)
 | 
			
		||||
		return ECMD_PROCESSED;
 | 
			
		||||
 | 
			
		||||
	return process_each_pv_in_vg(cmd, vg, handle, &_pvs_single);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -397,14 +389,6 @@ static int _pvsegs_in_vg(struct cmd_context *cmd, const char *vg_name,
 | 
			
		||||
			 struct volume_group *vg,
 | 
			
		||||
			 struct processing_handle *handle)
 | 
			
		||||
{
 | 
			
		||||
	int skip;
 | 
			
		||||
 | 
			
		||||
	if (ignore_vg(vg, vg_name, 0, &skip))
 | 
			
		||||
		return_ECMD_FAILED;
 | 
			
		||||
 | 
			
		||||
	if (skip)
 | 
			
		||||
		return ECMD_PROCESSED;
 | 
			
		||||
 | 
			
		||||
	return process_each_pv_in_vg(cmd, vg, handle, &_pvsegs_single);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -597,6 +581,17 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
 | 
			
		||||
	int lv_info_needed, lv_segment_status_needed;
 | 
			
		||||
	int lock_global = 0;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * When reporting foreign VGs we want to refresh our cached
 | 
			
		||||
	 * copy of them, since other hosts have probably made changes
 | 
			
		||||
	 * to their own VGs.  We also want to override the default
 | 
			
		||||
	 * behavior which skips over foreign VGs.
 | 
			
		||||
	 */
 | 
			
		||||
	if (arg_is_set(cmd, foreign_ARG) && lvmetad_used()) {
 | 
			
		||||
		lvmetad_pvscan_all_devs(cmd, NULL);
 | 
			
		||||
		cmd->include_foreign_vgs = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	aligned = find_config_tree_bool(cmd, report_aligned_CFG, NULL);
 | 
			
		||||
	buffered = find_config_tree_bool(cmd, report_buffered_CFG, NULL);
 | 
			
		||||
	headings = find_config_tree_bool(cmd, report_headings_CFG, NULL);
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <sys/wait.h>
 | 
			
		||||
#include <sys/utsname.h>
 | 
			
		||||
 | 
			
		||||
struct device_id_list {
 | 
			
		||||
	struct dm_list list;
 | 
			
		||||
@@ -175,7 +176,8 @@ const char *skip_dev_dir(struct cmd_context *cmd, const char *vg_name,
 | 
			
		||||
 *
 | 
			
		||||
 * Case c covers the other errors returned when reading the VG.
 | 
			
		||||
 */
 | 
			
		||||
int ignore_vg(struct volume_group *vg, const char *vg_name, int allow_inconsistent, int *skip)
 | 
			
		||||
static int ignore_vg(struct volume_group *vg, const char *vg_name,
 | 
			
		||||
		     struct dm_list *arg_vgnames, int allow_inconsistent, int *skip)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t read_error = vg_read_error(vg);
 | 
			
		||||
	*skip = 0;
 | 
			
		||||
@@ -189,6 +191,25 @@ int ignore_vg(struct volume_group *vg, const char *vg_name, int allow_inconsiste
 | 
			
		||||
		*skip = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Commands that operate on "all vgs" shouldn't be bothered by
 | 
			
		||||
	 * skipping a foreign VG, and the command shouldn't fail when
 | 
			
		||||
	 * one is skipped.  But, if the command explicitly asked to
 | 
			
		||||
	 * operate on a foreign VG and it's skipped, then the command
 | 
			
		||||
	 * would expect to fail.
 | 
			
		||||
	 */
 | 
			
		||||
	if (read_error & FAILED_SYSTEMID) {
 | 
			
		||||
		if (arg_vgnames && str_list_match_item(arg_vgnames, vg->name)) {
 | 
			
		||||
			log_error("Skipping volume group %s with system id %s",
 | 
			
		||||
				  vg->name, vg->system_id);
 | 
			
		||||
			return 1;
 | 
			
		||||
		} else {
 | 
			
		||||
			read_error &= ~FAILED_SYSTEMID; /* Check for other errors */
 | 
			
		||||
			log_verbose("Skipping volume group %s", vg_name);
 | 
			
		||||
			*skip = 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (read_error != SUCCESS) {
 | 
			
		||||
		log_error("Cannot process volume group %s", vg_name);
 | 
			
		||||
		return 1;
 | 
			
		||||
@@ -653,6 +674,7 @@ int vgcreate_params_set_defaults(struct cmd_context *cmd,
 | 
			
		||||
		vp_def->alloc = vg->alloc;
 | 
			
		||||
		vp_def->clustered = vg_is_clustered(vg);
 | 
			
		||||
		vp_def->vgmetadatacopies = vg->mda_copies;
 | 
			
		||||
		vp_def->system_id = vg->system_id ? dm_pool_strdup(cmd->mem, vg->system_id) : NULL;
 | 
			
		||||
	} else {
 | 
			
		||||
		vp_def->vg_name = NULL;
 | 
			
		||||
		extent_size = find_config_tree_int64(cmd,
 | 
			
		||||
@@ -667,6 +689,7 @@ int vgcreate_params_set_defaults(struct cmd_context *cmd,
 | 
			
		||||
		vp_def->alloc = DEFAULT_ALLOC_POLICY;
 | 
			
		||||
		vp_def->clustered = DEFAULT_CLUSTERED;
 | 
			
		||||
		vp_def->vgmetadatacopies = DEFAULT_VGMETADATACOPIES;
 | 
			
		||||
		vp_def->system_id = cmd->system_id ? dm_pool_strdup(cmd->mem, cmd->system_id) : NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
@@ -682,6 +705,8 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd,
 | 
			
		||||
				  struct vgcreate_params *vp_new,
 | 
			
		||||
				  struct vgcreate_params *vp_def)
 | 
			
		||||
{
 | 
			
		||||
	const char *arg_str;
 | 
			
		||||
 | 
			
		||||
	vp_new->vg_name = skip_dev_dir(cmd, vp_def->vg_name, NULL);
 | 
			
		||||
	vp_new->max_lv = arg_uint_value(cmd, maxlogicalvolumes_ARG,
 | 
			
		||||
					vp_def->max_lv);
 | 
			
		||||
@@ -730,6 +755,27 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd,
 | 
			
		||||
		vp_new->vgmetadatacopies = find_config_tree_int(cmd, metadata_vgmetadatacopies_CFG, NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((arg_str = arg_str_value(cmd, systemid_ARG, NULL))) {
 | 
			
		||||
		vp_new->system_id = system_id_from_string(cmd, arg_str);
 | 
			
		||||
	} else {
 | 
			
		||||
		vp_new->system_id = vp_def->system_id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (arg_str) {
 | 
			
		||||
		if (!vp_new->system_id)
 | 
			
		||||
			log_warn("No local system id found, VG will not have a system id.");
 | 
			
		||||
 | 
			
		||||
		if (vp_new->system_id && cmd->system_id &&
 | 
			
		||||
		    strcmp(vp_new->system_id, cmd->system_id)) {
 | 
			
		||||
			log_warn("VG system id \"%s\" will not be accessible to local system id \"%s\"",
 | 
			
		||||
				 vp_new->system_id, cmd->system_id);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* A clustered vg has no system_id. */
 | 
			
		||||
	if (vp_new->clustered)
 | 
			
		||||
		vp_new->system_id = NULL;
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1744,7 +1790,7 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
 | 
			
		||||
		skip = 0;
 | 
			
		||||
 | 
			
		||||
		vg = vg_read(cmd, vg_name, vg_uuid, flags);
 | 
			
		||||
		if (ignore_vg(vg, vg_name, flags & READ_ALLOW_INCONSISTENT, &skip)) {
 | 
			
		||||
		if (ignore_vg(vg, vg_name, arg_vgnames, flags & READ_ALLOW_INCONSISTENT, &skip)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			ret_max = ECMD_FAILED;
 | 
			
		||||
			release_vg(vg);
 | 
			
		||||
@@ -2184,7 +2230,7 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		vg = vg_read(cmd, vg_name, vg_uuid, flags);
 | 
			
		||||
		if (ignore_vg(vg, vg_name, flags & READ_ALLOW_INCONSISTENT, &skip)) {
 | 
			
		||||
		if (ignore_vg(vg, vg_name, arg_vgnames, flags & READ_ALLOW_INCONSISTENT, &skip)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			ret_max = ECMD_FAILED;
 | 
			
		||||
			release_vg(vg);
 | 
			
		||||
@@ -2658,7 +2704,7 @@ static int _process_pvs_in_vgs(struct cmd_context *cmd, uint32_t flags,
 | 
			
		||||
		skip = 0;
 | 
			
		||||
 | 
			
		||||
		vg = vg_read(cmd, vg_name, vg_uuid, flags | READ_WARN_INCONSISTENT);
 | 
			
		||||
		if (ignore_vg(vg, vg_name, flags & READ_ALLOW_INCONSISTENT, &skip)) {
 | 
			
		||||
		if (ignore_vg(vg, vg_name, NULL, flags & READ_ALLOW_INCONSISTENT, &skip)) {
 | 
			
		||||
			stack;
 | 
			
		||||
			ret_max = ECMD_FAILED;
 | 
			
		||||
			release_vg(vg);
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,6 @@
 | 
			
		||||
 | 
			
		||||
int become_daemon(struct cmd_context *cmd, int skip_lvm);
 | 
			
		||||
 | 
			
		||||
int ignore_vg(struct volume_group *vg, const char *vg_name, int allow_inconsistent, int *skip);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The "struct processing_handle" is used as a handle for processing
 | 
			
		||||
 * functions (process_each_* and related).
 | 
			
		||||
 
 | 
			
		||||
@@ -332,6 +332,11 @@ static int _vgchange_clustered(struct cmd_context *cmd,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (clustered)
 | 
			
		||||
		vg->system_id = NULL;
 | 
			
		||||
	else if (cmd->system_id && cmd->system_id[0])
 | 
			
		||||
		vg->system_id = dm_pool_strdup(cmd->mem, cmd->system_id);
 | 
			
		||||
 | 
			
		||||
	if (!vg_set_clustered(vg, clustered))
 | 
			
		||||
		return_0;
 | 
			
		||||
 | 
			
		||||
@@ -471,6 +476,38 @@ static int _vgchange_profile(struct cmd_context *cmd,
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This function will not be called unless the local host is allowed to use the
 | 
			
		||||
 * VG.  Either the VG has no system_id, or the VG and host have matching
 | 
			
		||||
 * system_ids, or the host has the VG's current system_id in its
 | 
			
		||||
 * allow_system_id list.  This function is not allowed to change the system_id
 | 
			
		||||
 * of a foreign VG (VG owned by another host).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static int _vgchange_system_id(struct cmd_context *cmd, struct volume_group *vg)
 | 
			
		||||
{
 | 
			
		||||
	const char *arg_str = arg_str_value(cmd, systemid_ARG, NULL);
 | 
			
		||||
	char *system_id;
 | 
			
		||||
 | 
			
		||||
	if (!arg_str)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	system_id = system_id_from_string(cmd, arg_str);
 | 
			
		||||
 | 
			
		||||
	if (system_id && cmd->system_id && strcmp(system_id, cmd->system_id)) {
 | 
			
		||||
		log_warn("VG \"%s\" system id \"%s\" does not match local system id \"%s\"",
 | 
			
		||||
			 vg->name, system_id, cmd->system_id);
 | 
			
		||||
 | 
			
		||||
		if (yes_no_prompt("Change system id? [y/n]: ") == 'n') {
 | 
			
		||||
			log_error("Volume group \"%s\" not changed.", vg->name);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vg->system_id = system_id;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
 | 
			
		||||
			   struct volume_group *vg,
 | 
			
		||||
			   struct processing_handle *handle __attribute__((unused)))
 | 
			
		||||
@@ -496,6 +533,7 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
 | 
			
		||||
		{ metadataprofile_ARG, &_vgchange_profile },
 | 
			
		||||
		{ profile_ARG, &_vgchange_profile },
 | 
			
		||||
		{ detachprofile_ARG, &_vgchange_profile },
 | 
			
		||||
		{ systemid_ARG, &_vgchange_system_id },
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (vg_is_exported(vg)) {
 | 
			
		||||
@@ -589,13 +627,19 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
 | 
			
		||||
 | 
			
		||||
int vgchange(struct cmd_context *cmd, int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	/* Update commands that can be combined */
 | 
			
		||||
	int noupdate =
 | 
			
		||||
		arg_count(cmd, activate_ARG) ||
 | 
			
		||||
		arg_count(cmd, monitor_ARG) ||
 | 
			
		||||
		arg_count(cmd, poll_ARG) ||
 | 
			
		||||
		arg_count(cmd, refresh_ARG);
 | 
			
		||||
 | 
			
		||||
	int update_partial_safe =
 | 
			
		||||
		arg_count(cmd, deltag_ARG) ||
 | 
			
		||||
		arg_count(cmd, addtag_ARG) ||
 | 
			
		||||
		arg_count(cmd, metadataprofile_ARG) ||
 | 
			
		||||
		arg_count(cmd, profile_ARG) ||
 | 
			
		||||
		arg_count(cmd, detachprofile_ARG);
 | 
			
		||||
 | 
			
		||||
	int update_partial_unsafe =
 | 
			
		||||
		arg_count(cmd, logicalvolume_ARG) ||
 | 
			
		||||
		arg_count(cmd, maxphysicalvolumes_ARG) ||
 | 
			
		||||
@@ -604,18 +648,13 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
 | 
			
		||||
		arg_count(cmd, physicalextentsize_ARG) ||
 | 
			
		||||
		arg_count(cmd, clustered_ARG) ||
 | 
			
		||||
		arg_count(cmd, alloc_ARG) ||
 | 
			
		||||
		arg_count(cmd, vgmetadatacopies_ARG);
 | 
			
		||||
		arg_count(cmd, vgmetadatacopies_ARG) ||
 | 
			
		||||
		arg_count(cmd, systemid_ARG);
 | 
			
		||||
 | 
			
		||||
	int update = update_partial_safe || update_partial_unsafe;
 | 
			
		||||
 | 
			
		||||
	if (!update &&
 | 
			
		||||
	    !arg_count(cmd, activate_ARG) &&
 | 
			
		||||
	    !arg_count(cmd, monitor_ARG) &&
 | 
			
		||||
	    !arg_count(cmd, poll_ARG) &&
 | 
			
		||||
	    !arg_count(cmd, refresh_ARG)) {
 | 
			
		||||
		log_error("Need 1 or more of -a, -c, -l, -p, -s, -x, "
 | 
			
		||||
			  "--refresh, --uuid, --alloc, --addtag, --deltag, "
 | 
			
		||||
			  "--monitor, --poll, --vgmetadatacopies or "
 | 
			
		||||
			  "--metadatacopies");
 | 
			
		||||
	if (!update && !noupdate) {
 | 
			
		||||
		log_error("Need one or more command options.");
 | 
			
		||||
		return EINVALID_CMD_LINE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -71,6 +71,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
 | 
			
		||||
	    !vg_set_max_pv(vg, vp_new.max_pv) ||
 | 
			
		||||
	    !vg_set_alloc_policy(vg, vp_new.alloc) ||
 | 
			
		||||
	    !vg_set_clustered(vg, vp_new.clustered) ||
 | 
			
		||||
	    !vg_set_system_id(vg, vp_new.system_id) ||
 | 
			
		||||
	    !vg_set_mda_copies(vg, vp_new.vgmetadatacopies))
 | 
			
		||||
		goto bad_orphan;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@ static int vgexport_single(struct cmd_context *cmd __attribute__((unused)),
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	vg->status |= EXPORTED_VG;
 | 
			
		||||
	vg->system_id = NULL;
 | 
			
		||||
 | 
			
		||||
	dm_list_iterate_items(pvl, &vg->pvs)
 | 
			
		||||
		pvl->pv->status |= EXPORTED_VG;
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,7 @@ static int vgimport_single(struct cmd_context *cmd __attribute__((unused)),
 | 
			
		||||
		goto_bad;
 | 
			
		||||
 | 
			
		||||
	vg->status &= ~EXPORTED_VG;
 | 
			
		||||
	vg->system_id = cmd->system_id ? dm_pool_strdup(cmd->mem, cmd->system_id) : NULL;
 | 
			
		||||
 | 
			
		||||
	dm_list_iterate_items(pvl, &vg->pvs) {
 | 
			
		||||
		pv = pvl->pv;
 | 
			
		||||
@@ -84,6 +85,17 @@ int vgimport(struct cmd_context *cmd, int argc, char **argv)
 | 
			
		||||
		cmd->handles_missing_pvs = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Rescan devices and update lvmetad.  lvmetad may hold a copy of the
 | 
			
		||||
	 * VG from before it was exported, if it was exported by another host.
 | 
			
		||||
	 * We need to reread it to see that it's been exported before we can
 | 
			
		||||
	 * import it.
 | 
			
		||||
	 */
 | 
			
		||||
	if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, NULL)) {
 | 
			
		||||
		log_error("Failed to scan devices.");
 | 
			
		||||
		return ECMD_FAILED;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return process_each_vg(cmd, argc, argv,
 | 
			
		||||
			       READ_FOR_UPDATE | READ_ALLOW_EXPORTED,
 | 
			
		||||
			       NULL,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user