diff options
Diffstat (limited to 'lib/metadata')
-rw-r--r-- | lib/metadata/metadata-exported.h | 2 | ||||
-rw-r--r-- | lib/metadata/metadata.c | 96 | ||||
-rw-r--r-- | lib/metadata/vg.c | 16 | ||||
-rw-r--r-- | lib/metadata/vg.h | 1 |
4 files changed, 108 insertions, 7 deletions
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index bf6f1c122..7c2dcefb2 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -161,6 +161,7 @@ #define FAILED_CLUSTERED 0x00000040U #define FAILED_ALLOCATION 0x00000080U #define FAILED_EXIST 0x00000100U +#define FAILED_SYSTEMID 0x00000200U #define SUCCESS 0x00000000U #define VGMETADATACOPIES_ALL UINT32_MAX @@ -1145,6 +1146,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, diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 9308cb739..2057ada66 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -4223,6 +4223,94 @@ 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) +{ + if (cmd->skip_systemid_check) + return 1; + + if (vg->system_id && vg->system_id[0] && cmd->unknown_system_id) + goto fail; + + if (vg->system_id && vg->system_id[0] && cmd->system_id && cmd->system_id[0]) { + if (!strcmp(vg->system_id, cmd->system_id)) + return 1; + if (allow_system_id(cmd, vg->system_id)) + return 1; + goto fail; + } + + return 1; + +fail: + if (find_config_tree_bool(cmd, log_silent_other_systemid_CFG, NULL)) + return 0; + log_warn("Cannot access VG %s with system id \"%s\" from local system id \"%s\"", + vg->name, vg->system_id, cmd->system_id ?: "unknown"); + 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. * @@ -4282,14 +4370,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) { diff --git a/lib/metadata/vg.c b/lib/metadata/vg.c index 71b894b8f..57c9acfd9 100644 --- a/lib/metadata/vg.c +++ b/lib/metadata/vg.c @@ -603,6 +603,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; diff --git a/lib/metadata/vg.h b/lib/metadata/vg.h index fffe9a7d5..23d60acdd 100644 --- a/lib/metadata/vg.h +++ b/lib/metadata/vg.h @@ -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); |