* master - lvmcache: rework handling of VGs with duplicate vgnames
@ 2020-04-21 19:51 David Teigland
0 siblings, 0 replies; only message in thread
From: David Teigland @ 2020-04-21 19:51 UTC (permalink / raw)
To: lvm-devel
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=d79afd408446e3eb922d16954ae630a7af995e66
Commit: d79afd408446e3eb922d16954ae630a7af995e66
Parent: cc4051eec051aef8912279a598c2cb491e68b508
Author: David Teigland <teigland@redhat.com>
AuthorDate: Tue Jan 28 11:47:37 2020 -0600
Committer: David Teigland <teigland@redhat.com>
CommitterDate: Tue Apr 21 14:40:34 2020 -0500
lvmcache: rework handling of VGs with duplicate vgnames
The previous method of managing duplicate vgnames prevented
vgreduce from working if a foreign vg with the same name
existed.
---
lib/cache/lvmcache.c | 499 ++++++++++----------
lib/cache/lvmcache.h | 3 +-
lib/commands/toolcontext.c | 2 +-
lib/metadata/metadata.c | 51 ++-
test/shell/duplicate-vgnames.sh | 660 +++++++++++++++++++++++++++
test/shell/duplicate-vgrename.sh | 319 +++++++++++++
test/shell/process-each-duplicate-vgnames.sh | 55 ---
tools/toollib.c | 2 -
8 files changed, 1264 insertions(+), 327 deletions(-)
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index f7af4c28d..bcb893346 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -49,7 +49,7 @@ struct lvmcache_info {
/* One per VG */
struct lvmcache_vginfo {
- struct dm_list list; /* Join these vginfos together */
+ struct dm_list list; /* _vginfos */
struct dm_list infos; /* List head for lvmcache_infos */
struct dm_list outdated_infos; /* vg_read moves info from infos to outdated_infos */
struct dm_list pvsummaries; /* pv_list taken directly from vgsummary */
@@ -58,7 +58,6 @@ struct lvmcache_vginfo {
uint32_t status;
char vgid[ID_LEN + 1];
char _padding[7];
- struct lvmcache_vginfo *next; /* Another VG with same name? */
char *creation_host;
char *system_id;
char *lock_type;
@@ -66,8 +65,16 @@ struct lvmcache_vginfo {
size_t mda_size;
int seqno;
bool scan_summary_mismatch; /* vgsummary from devs had mismatching seqno or checksum */
+ bool has_duplicate_local_vgname; /* this local vg and another local vg have same name */
+ bool has_duplicate_foreign_vgname; /* this foreign vg and another foreign vg have same name */
};
+/*
+ * Each VG found during scan gets a vginfo struct.
+ * Each vginfo is in _vginfos and _vgid_hash, and
+ * _vgname_hash (unless disabled due to duplicate vgnames).
+ */
+
static struct dm_hash_table *_pvid_hash = NULL;
static struct dm_hash_table *_vgid_hash = NULL;
static struct dm_hash_table *_vgname_hash = NULL;
@@ -262,16 +269,6 @@ void lvmcache_get_mdas(struct cmd_context *cmd,
}
}
-static void _vginfo_attach_info(struct lvmcache_vginfo *vginfo,
- struct lvmcache_info *info)
-{
- if (!vginfo)
- return;
-
- info->vginfo = vginfo;
- dm_list_add(&vginfo->infos, &info->list);
-}
-
static void _vginfo_detach_info(struct lvmcache_info *info)
{
if (!dm_list_empty(&info->list)) {
@@ -282,57 +279,80 @@ static void _vginfo_detach_info(struct lvmcache_info *info)
info->vginfo = NULL;
}
-/* If vgid supplied, require a match. */
-struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname, const char *vgid)
+static struct lvmcache_vginfo *_search_vginfos_list(const char *vgname, const char *vgid)
{
struct lvmcache_vginfo *vginfo;
- if (!vgname)
- return lvmcache_vginfo_from_vgid(vgid);
-
- if (!_vgname_hash) {
- log_debug_cache(INTERNAL_ERROR "Internal lvmcache is no yet initialized.");
- return NULL;
- }
-
- if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname))) {
- log_debug_cache("lvmcache has no info for vgname \"%s\"%s" FMTVGID ".",
- vgname, (vgid) ? " with VGID " : "", (vgid) ? : "");
- return NULL;
- }
-
- if (vgid)
- do
- if (!strncmp(vgid, vginfo->vgid, ID_LEN))
+ if (vgid) {
+ dm_list_iterate_items(vginfo, &_vginfos) {
+ if (!strcmp(vgid, vginfo->vgid))
return vginfo;
- while ((vginfo = vginfo->next));
-
- if (!vginfo)
- log_debug_cache("lvmcache has not found vgname \"%s\"%s" FMTVGID ".",
- vgname, (vgid) ? " with VGID " : "", (vgid) ? : "");
-
- return vginfo;
+ }
+ } else {
+ dm_list_iterate_items(vginfo, &_vginfos) {
+ if (!strcmp(vgname, vginfo->vgname))
+ return vginfo;
+ }
+ }
+ return NULL;
}
-struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid)
+static struct lvmcache_vginfo *_vginfo_lookup(const char *vgname, const char *vgid)
{
struct lvmcache_vginfo *vginfo;
char id[ID_LEN + 1] __attribute__((aligned(8)));
- if (!_vgid_hash || !vgid) {
- log_debug_cache(INTERNAL_ERROR "Internal cache cannot lookup vgid.");
- return NULL;
+ if (vgid) {
+ /* vgid not necessarily NULL-terminated */
+ (void) dm_strncpy(id, vgid, sizeof(id));
+
+ if ((vginfo = dm_hash_lookup(_vgid_hash, id))) {
+ if (vgname && strcmp(vginfo->vgname, vgname)) {
+ /* should never happen */
+ log_error(INTERNAL_ERROR "vginfo_lookup vgid %s has two names %s %s",
+ id, vginfo->vgname, vgname);
+ return NULL;
+ }
+ return vginfo;
+ } else {
+ /* lookup by vgid that doesn't exist */
+ return NULL;
+ }
}
- /* vgid not necessarily NULL-terminated */
- (void) dm_strncpy(id, vgid, sizeof(id));
+ if (vgname && !_found_duplicate_vgnames) {
+ if ((vginfo = dm_hash_lookup(_vgname_hash, vgname))) {
+ if (vginfo->has_duplicate_local_vgname) {
+ /* should never happen, found_duplicate_vgnames should be set */
+ log_error(INTERNAL_ERROR "vginfo_lookup %s %s has_duplicate_local_vgname", vgname, vgid);
+ return NULL;
+ }
+ return vginfo;
+ }
+ }
- if (!(vginfo = dm_hash_lookup(_vgid_hash, id))) {
- log_debug_cache("lvmcache has no info for vgid \"%s\"", id);
- return NULL;
+ if (vgname && _found_duplicate_vgnames) {
+ if ((vginfo = _search_vginfos_list(vgname, vgid))) {
+ if (vginfo->has_duplicate_local_vgname) {
+ log_debug("vginfo_lookup %s %s has_duplicate_local_vgname return none", vgname, vgid);
+ return NULL;
+ }
+ return vginfo;
+ }
}
- return vginfo;
+ /* lookup by vgname that doesn't exist */
+ return NULL;
+}
+
+struct lvmcache_vginfo *lvmcache_vginfo_from_vgname(const char *vgname, const char *vgid)
+{
+ return _vginfo_lookup(vgname, vgid);
+}
+
+struct lvmcache_vginfo *lvmcache_vginfo_from_vgid(const char *vgid)
+{
+ return _vginfo_lookup(NULL, vgid);
}
const char *lvmcache_vgname_from_vgid(struct dm_pool *mem, const char *vgid)
@@ -353,17 +373,43 @@ const char *lvmcache_vgid_from_vgname(struct cmd_context *cmd, const char *vgnam
{
struct lvmcache_vginfo *vginfo;
- if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
- return_NULL;
+ if (_found_duplicate_vgnames) {
+ if (!(vginfo = _search_vginfos_list(vgname, NULL)))
+ return_NULL;
+ } else {
+ if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
+ return_NULL;
+ }
- if (!vginfo->next)
- return dm_pool_strdup(cmd->mem, vginfo->vgid);
+ if (vginfo->has_duplicate_local_vgname) {
+ /*
+ * return NULL if there is a local VG with the same name since
+ * we don't know which to use.
+ */
+ return NULL;
+ }
- /*
- * There are multiple VGs with this name to choose from.
- * Return an error because we don't know which VG is intended.
- */
- return NULL;
+ if (vginfo->has_duplicate_foreign_vgname)
+ return NULL;
+
+ return dm_pool_strdup(cmd->mem, vginfo->vgid);
+}
+
+bool lvmcache_has_duplicate_local_vgname(const char *vgid, const char *vgname)
+{
+ struct lvmcache_vginfo *vginfo;
+
+ if (_found_duplicate_vgnames) {
+ if (!(vginfo = _search_vginfos_list(vgname, vgid)))
+ return false;
+ } else {
+ if (!(vginfo = dm_hash_lookup(_vgname_hash, vgname)))
+ return false;
+ }
+
+ if (vginfo->has_duplicate_local_vgname)
+ return true;
+ return false;
}
/*
@@ -1148,49 +1194,18 @@ int lvmcache_pvid_in_unused_duplicates(const char *pvid)
return 0;
}
-static int _free_vginfo(struct lvmcache_vginfo *vginfo)
+static void _free_vginfo(struct lvmcache_vginfo *vginfo)
{
- struct lvmcache_vginfo *primary_vginfo, *vginfo2;
- int r = 1;
-
- vginfo2 = primary_vginfo = lvmcache_vginfo_from_vgname(vginfo->vgname, NULL);
-
- if (vginfo == primary_vginfo) {
- dm_hash_remove(_vgname_hash, vginfo->vgname);
- if (vginfo->next && !dm_hash_insert(_vgname_hash, vginfo->vgname,
- vginfo->next)) {
- log_error("_vgname_hash re-insertion for %s failed",
- vginfo->vgname);
- r = 0;
- }
- } else
- while (vginfo2) {
- if (vginfo2->next == vginfo) {
- vginfo2->next = vginfo->next;
- break;
- }
- vginfo2 = vginfo2->next;
- }
-
- free(vginfo->system_id);
free(vginfo->vgname);
+ free(vginfo->system_id);
free(vginfo->creation_host);
-
- if (*vginfo->vgid && _vgid_hash &&
- lvmcache_vginfo_from_vgid(vginfo->vgid) == vginfo)
- dm_hash_remove(_vgid_hash, vginfo->vgid);
-
- dm_list_del(&vginfo->list);
-
free(vginfo);
-
- return r;
}
/*
- * vginfo must be info->vginfo unless info is NULL
+ * Remove vginfo from standard lists/hashes.
*/
-static int _drop_vginfo(struct lvmcache_info *info, struct lvmcache_vginfo *vginfo)
+static void _drop_vginfo(struct lvmcache_info *info, struct lvmcache_vginfo *vginfo)
{
if (info)
_vginfo_detach_info(info);
@@ -1198,12 +1213,16 @@ static int _drop_vginfo(struct lvmcache_info *info, struct lvmcache_vginfo *vgin
/* vginfo still referenced? */
if (!vginfo || is_orphan_vg(vginfo->vgname) ||
!dm_list_empty(&vginfo->infos))
- return 1;
+ return;
- if (!_free_vginfo(vginfo))
- return_0;
+ if (dm_hash_lookup(_vgname_hash, vginfo->vgname) == vginfo)
+ dm_hash_remove(_vgname_hash, vginfo->vgname);
- return 1;
+ dm_hash_remove(_vgid_hash, vginfo->vgid);
+
+ dm_list_del(&vginfo->list); /* _vginfos list */
+
+ _free_vginfo(vginfo);
}
void lvmcache_del(struct lvmcache_info *info)
@@ -1261,180 +1280,150 @@ static int _lvmcache_update_vgid(struct lvmcache_info *info,
return 1;
}
-static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid,
- uint32_t vgstatus, const char *creation_host,
- struct lvmcache_vginfo *primary_vginfo)
+static int _lvmcache_update_vgname(struct cmd_context *cmd,
+ struct lvmcache_info *info,
+ const char *vgname, const char *vgid,
+ const char *system_id,
+ const struct format_type *fmt)
{
- struct lvmcache_vginfo *last_vginfo = primary_vginfo;
- char uuid_primary[64] __attribute__((aligned(8)));
- char uuid_new[64] __attribute__((aligned(8)));
- int use_new = 0;
-
- /* Pre-existing VG takes precedence. Unexported VG takes precedence. */
- if (primary_vginfo) {
- if (!id_write_format((const struct id *)vgid, uuid_new, sizeof(uuid_new)))
- return_0;
+ char vgid_str[64] __attribute__((aligned(8)));
+ char other_str[64] __attribute__((aligned(8)));
+ struct lvmcache_vginfo *vginfo;
+ struct lvmcache_vginfo *other;
+ int vginfo_is_allowed;
+ int other_is_allowed;
- if (!id_write_format((const struct id *)&primary_vginfo->vgid, uuid_primary,
- sizeof(uuid_primary)))
- return_0;
+ if (!vgname || (info && info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
+ return 1;
- _found_duplicate_vgnames = 1;
+ if (!id_write_format((const struct id *)vgid, vgid_str, sizeof(vgid_str)))
+ stack;
- /*
- * vginfo is kept for each VG with the same name.
- * They are saved with the vginfo->next list.
- * These checks just decide the ordering of
- * that list.
- *
- * FIXME: it should no longer matter what order
- * the vginfo's are kept in, so we can probably
- * remove these comparisons and reordering entirely.
- *
- * If Primary not exported, new exported => keep
- * Else Primary exported, new not exported => change
- * Else Primary has hostname for this machine => keep
- * Else Primary has no hostname, new has one => change
- * Else New has hostname for this machine => change
- * Else Keep primary.
- */
- if (!(primary_vginfo->status & EXPORTED_VG) &&
- (vgstatus & EXPORTED_VG))
- log_verbose("Cache: Duplicate VG name %s: "
- "Existing %s takes precedence over "
- "exported %s", new_vginfo->vgname,
- uuid_primary, uuid_new);
- else if ((primary_vginfo->status & EXPORTED_VG) &&
- !(vgstatus & EXPORTED_VG)) {
- log_verbose("Cache: Duplicate VG name %s: "
- "%s takes precedence over exported %s",
- new_vginfo->vgname, uuid_new,
- uuid_primary);
- use_new = 1;
- } else if (primary_vginfo->creation_host &&
- !strcmp(primary_vginfo->creation_host,
- primary_vginfo->fmt->cmd->hostname))
- log_verbose("Cache: Duplicate VG name %s: "
- "Existing %s (created here) takes precedence "
- "over %s", new_vginfo->vgname, uuid_primary,
- uuid_new);
- else if (!primary_vginfo->creation_host && creation_host) {
- log_verbose("Cache: Duplicate VG name %s: "
- "%s (with creation_host) takes precedence over %s",
- new_vginfo->vgname, uuid_new,
- uuid_primary);
- use_new = 1;
- } else if (creation_host &&
- !strcmp(creation_host,
- primary_vginfo->fmt->cmd->hostname)) {
- log_verbose("Cache: Duplicate VG name %s: "
- "%s (created here) takes precedence over %s",
- new_vginfo->vgname, uuid_new,
- uuid_primary);
- use_new = 1;
- } else {
- log_verbose("Cache: Duplicate VG name %s: "
- "Prefer existing %s vs new %s",
- new_vginfo->vgname, uuid_primary, uuid_new);
+ /*
+ * Add vginfo for orphan VG
+ */
+ if (!info) {
+ if (!(vginfo = zalloc(sizeof(*vginfo)))) {
+ log_error("lvmcache adding vg list alloc failed %s", vgname);
+ return 0;
}
-
- if (!use_new) {
- while (last_vginfo->next)
- last_vginfo = last_vginfo->next;
- last_vginfo->next = new_vginfo;
- return 1;
+ if (!(vginfo->vgname = strdup(vgname))) {
+ free(vginfo);
+ log_error("lvmcache adding vg name alloc failed %s", vgname);
+ return 0;
}
+ dm_list_init(&vginfo->infos);
+ dm_list_init(&vginfo->outdated_infos);
+ dm_list_init(&vginfo->pvsummaries);
+ vginfo->fmt = fmt;
- dm_hash_remove(_vgname_hash, primary_vginfo->vgname);
- }
-
- if (!dm_hash_insert(_vgname_hash, new_vginfo->vgname, new_vginfo)) {
- log_error("cache_update: vg hash insertion failed: %s",
- new_vginfo->vgname);
- return 0;
- }
-
- if (primary_vginfo)
- new_vginfo->next = primary_vginfo;
-
- return 1;
-}
+ if (!dm_hash_insert(_vgname_hash, vgname, vginfo)) {
+ free(vginfo->vgname);
+ free(vginfo);
+ return_0;
+ }
-static int _lvmcache_update_vgname(struct lvmcache_info *info,
- const char *vgname, const char *vgid,
- uint32_t vgstatus, const char *creation_host,
- const struct format_type *fmt)
-{
- struct lvmcache_vginfo *vginfo, *primary_vginfo;
- char mdabuf[32];
+ if (!_lvmcache_update_vgid(NULL, vginfo, vgid)) {
+ free(vginfo->vgname);
+ free(vginfo);
+ return_0;
+ }
- if (!vgname || (info && info->vginfo && !strcmp(info->vginfo->vgname, vgname)))
+ /* Ensure orphans appear last on list_iterate */
+ dm_list_add(&_vginfos, &vginfo->list);
return 1;
+ }
- /* Remove existing vginfo entry */
- if (info)
- _drop_vginfo(info, info->vginfo);
+ _drop_vginfo(info, info->vginfo);
- if (!(vginfo = lvmcache_vginfo_from_vgname(vgname, vgid))) {
+ if (!(vginfo = lvmcache_vginfo_from_vgid(vgid))) {
/*
* Create a vginfo struct for this VG and put the vginfo
* into the hash table.
*/
+ log_debug_cache("lvmcache adding vginfo for %s %s", vgname, vgid_str);
+
if (!(vginfo = zalloc(sizeof(*vginfo)))) {
- log_error("lvmcache_update_vgname: list alloc failed");
+ log_error("lvmcache adding vg list alloc failed %s", vgname);
return 0;
}
if (!(vginfo->vgname = strdup(vgname))) {
free(vginfo);
- log_error("cache vgname alloc failed for %s", vgname);
+ log_error("lvmcache adding vg name alloc failed %s", vgname);
return 0;
}
dm_list_init(&vginfo->infos);
dm_list_init(&vginfo->outdated_infos);
dm_list_init(&vginfo->pvsummaries);
- /*
- * A different VG (different uuid) can exist with the same name.
- * In this case, the two VGs will have separate vginfo structs,
- * but the second will be linked onto the existing vginfo->next,
- * not in the hash.
- */
- primary_vginfo = lvmcache_vginfo_from_vgname(vgname, NULL);
+ if ((other = dm_hash_lookup(_vgname_hash, vgname))) {
+ log_debug_cache("lvmcache adding vginfo found duplicate VG name %s", vgname);
- if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host, primary_vginfo)) {
- free(vginfo->vgname);
- free(vginfo);
- return 0;
+ /*
+ * A different VG (different uuid) can exist with the
+ * same name. In this case, the two VGs will have
+ * separate vginfo structs, but one will be in the
+ * vgname_hash. If both vginfos are local/accessible,
+ * then _found_duplicate_vgnames is set which will
+ * disable any further use of the vgname_hash.
+ */
+
+ if (!memcmp(other->vgid, vgid, ID_LEN)) {
+ /* shouldn't happen since we looked up by vgid above */
+ log_error(INTERNAL_ERROR "lvmcache_update_vgname %s %s %s %s",
+ vgname, vgid_str, other->vgname, other->vgid);
+ free(vginfo->vgname);
+ free(vginfo);
+ return 0;
+ }
+
+ vginfo_is_allowed = is_system_id_allowed(cmd, system_id);
+ other_is_allowed = is_system_id_allowed(cmd, other->system_id);
+
+ if (vginfo_is_allowed && other_is_allowed) {
+ if (!id_write_format((const struct id *)other->vgid, other_str, sizeof(other_str)))
+ stack;
+
+ vginfo->has_duplicate_local_vgname = 1;
+ other->has_duplicate_local_vgname = 1;
+ _found_duplicate_vgnames = 1;
+
+ log_warn("WARNING: VG name %s is used by VGs %s and %s.",
+ vgname, vgid_str, other_str);
+ log_warn("Fix duplicate VG names with vgrename uuid, a device filter, or system IDs.");
+ }
+
+ if (!vginfo_is_allowed && !other_is_allowed) {
+ vginfo->has_duplicate_foreign_vgname = 1;
+ other->has_duplicate_foreign_vgname = 1;
+ }
+
+ if (!other_is_allowed && vginfo_is_allowed) {
+ /* the accessible vginfo must be in vgnames_hash */
+ dm_hash_remove(_vgname_hash, vgname);
+ if (!dm_hash_insert(_vgname_hash, vgname, vginfo)) {
+ log_error("lvmcache adding vginfo to name hash failed %s", vgname);
+ return 0;
+ }
+ }
+ } else {
+ if (!dm_hash_insert(_vgname_hash, vgname, vginfo)) {
+ log_error("lvmcache adding vg to name hash failed %s", vgname);
+ free(vginfo->vgname);
+ free(vginfo);
+ return 0;
+ }
}
- /* Ensure orphans appear last on list_iterate */
- if (is_orphan_vg(vgname))
- dm_list_add(&_vginfos, &vginfo->list);
- else
- dm_list_add_h(&_vginfos, &vginfo->list);
+ dm_list_add_h(&_vginfos, &vginfo->list);
}
- if (info)
- _vginfo_attach_info(vginfo, info);
- else if (!_lvmcache_update_vgid(NULL, vginfo, vgid)) /* Orphans */
- return_0;
-
- /* FIXME Check consistency of list! */
vginfo->fmt = fmt;
+ info->vginfo = vginfo;
+ dm_list_add(&vginfo->infos, &info->list);
- if (info) {
- if (info->mdas.n)
- sprintf(mdabuf, " with %u mda(s)", dm_list_size(&info->mdas));
- else
- mdabuf[0] = '\0';
- log_debug_cache("lvmcache %s: now in VG %s%s%s%s%s.",
- dev_name(info->dev),
- vgname, vginfo->vgid[0] ? " (" : "",
- vginfo->vgid[0] ? vginfo->vgid : "",
- vginfo->vgid[0] ? ")" : "", mdabuf);
- } else
- log_debug_cache("lvmcache: Initialised VG %s.", vgname);
+ log_debug_cache("lvmcache %s: now in VG %s %s", dev_name(info->dev), vgname, vgid_str);
return 1;
}
@@ -1511,9 +1500,9 @@ out:
return 1;
}
-int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt)
+int lvmcache_add_orphan_vginfo(struct cmd_context *cmd, const char *vgname, struct format_type *fmt)
{
- return _lvmcache_update_vgname(NULL, vgname, vgname, 0, "", fmt);
+ return _lvmcache_update_vgname(cmd, NULL, vgname, vgname, "", fmt);
}
static void _lvmcache_update_pvsummaries(struct lvmcache_vginfo *vginfo, struct lvmcache_vgsummary *vgsummary)
@@ -1545,6 +1534,7 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
vgid = vgname;
}
+ /* FIXME: remove this, it shouldn't be needed */
/* If PV without mdas is already in a real VG, don't make it orphan */
if (is_orphan_vg(vgname) && info->vginfo &&
mdas_empty_or_ignored(&info->mdas) &&
@@ -1556,7 +1546,7 @@ int lvmcache_update_vgname_and_id(struct cmd_context *cmd, struct lvmcache_info
* and attaches the info struct for the dev to the vginfo.
* Puts the vginfo into the vgname hash table.
*/
- if (!_lvmcache_update_vgname(info, vgname, vgid, vgsummary->vgstatus, vgsummary->creation_host, info->fmt)) {
+ if (!_lvmcache_update_vgname(cmd, info, vgname, vgid, vgsummary->system_id, info->fmt)) {
/* shouldn't happen, internal error */
log_error("Failed to update VG %s info in lvmcache.", vgname);
return 0;
@@ -2055,7 +2045,7 @@ update_vginfo:
return info;
}
-static void _lvmcache_destroy_entry(struct lvmcache_info *info)
+static void _lvmcache_destroy_info(struct lvmcache_info *info)
{
_vginfo_detach_info(info);
info->dev->pvid[0] = 0;
@@ -2063,20 +2053,11 @@ static void _lvmcache_destroy_entry(struct lvmcache_info *info)
free(info);
}
-static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo)
-{
- struct lvmcache_vginfo *next;
-
- do {
- next = vginfo->next;
- if (!_free_vginfo(vginfo))
- stack;
- } while ((vginfo = next));
-}
-
void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
{
- log_debug_cache("Dropping VG info");
+ struct lvmcache_vginfo *vginfo, *vginfo2;
+
+ log_debug_cache("Destroy lvmcache content");
if (_vgid_hash) {
dm_hash_destroy(_vgid_hash);
@@ -2084,20 +2065,24 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
}
if (_pvid_hash) {
- dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _lvmcache_destroy_entry);
+ dm_hash_iter(_pvid_hash, (dm_hash_iterate_fn) _lvmcache_destroy_info);
dm_hash_destroy(_pvid_hash);
_pvid_hash = NULL;
}
if (_vgname_hash) {
- dm_hash_iter(_vgname_hash,
- (dm_hash_iterate_fn) _lvmcache_destroy_vgnamelist);
dm_hash_destroy(_vgname_hash);
_vgname_hash = NULL;
}
+ dm_list_iterate_items_safe(vginfo, vginfo2, &_vginfos) {
+ dm_list_del(&vginfo->list);
+ _free_vginfo(vginfo);
+ }
+
if (!dm_list_empty(&_vginfos))
- log_error(INTERNAL_ERROR "_vginfos list should be empty");
+ log_error(INTERNAL_ERROR "vginfos list should be empty");
+
dm_list_init(&_vginfos);
/*
@@ -2109,6 +2094,8 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
* We want the same preferred devices to be chosen each time, so save
* the unpreferred devs here so that _choose_preferred_devs can use
* this to make the same choice each time.
+ *
+ * FIXME: I don't think is is needed any more.
*/
_destroy_device_list(&_prev_unused_duplicate_devs);
dm_list_splice(&_prev_unused_duplicate_devs, &_unused_duplicates);
@@ -2122,7 +2109,7 @@ void lvmcache_destroy(struct cmd_context *cmd, int retain_orphans, int reset)
stack;
dm_list_iterate_items(fmt, &cmd->formats) {
- if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt))
+ if (!lvmcache_add_orphan_vginfo(cmd, fmt->orphan_vg_name, fmt))
stack;
}
}
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 3412d2ca9..6cef4d102 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -75,7 +75,7 @@ struct lvmcache_info *lvmcache_add(struct cmd_context *cmd, struct labeller *lab
struct device *dev, uint64_t label_sector,
const char *vgname, const char *vgid,
uint32_t vgstatus, int *is_duplicate);
-int lvmcache_add_orphan_vginfo(const char *vgname, struct format_type *fmt);
+int lvmcache_add_orphan_vginfo(struct cmd_context *cmd, const char *vgname, struct format_type *fmt);
void lvmcache_del(struct lvmcache_info *info);
void lvmcache_del_dev(struct device *dev);
@@ -169,6 +169,7 @@ int lvmcache_get_unused_duplicates(struct cmd_context *cmd, struct dm_list *head
int vg_has_duplicate_pvs(struct volume_group *vg);
int lvmcache_found_duplicate_vgnames(void);
+bool lvmcache_has_duplicate_local_vgname(const char *vgid, const char *vgname);
int lvmcache_contains_lock_type_sanlock(struct cmd_context *cmd);
diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 88d5b3eb0..2bd7fabd2 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -1276,7 +1276,7 @@ int init_lvmcache_orphans(struct cmd_context *cmd)
struct format_type *fmt;
dm_list_iterate_items(fmt, &cmd->formats)
- if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt))
+ if (!lvmcache_add_orphan_vginfo(cmd, fmt->orphan_vg_name, fmt))
return_0;
return 1;
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 6c40cd321..b42d7a9b9 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -4751,18 +4751,6 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
lvmcache_label_rescan_vg(cmd, vgname, vgid);
}
- /* Now determine the correct vgname if none was supplied */
- if (!vgname && !(vgname = lvmcache_vgname_from_vgid(cmd->mem, vgid))) {
- log_debug_metadata("Cache did not find VG name from vgid %s", vgid);
- return NULL;
- }
-
- /* Determine the correct vgid if none was supplied */
- if (!vgid && !(vgid = lvmcache_vgid_from_vgname(cmd, vgname))) {
- log_debug_metadata("Cache did not find VG vgid from name %s", vgname);
- return NULL;
- }
-
/*
* A "format instance" is an abstraction for a VG location,
* i.e. where a VG's metadata exists on disk.
@@ -4999,6 +4987,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const
int missing_pv_dev = 0;
int missing_pv_flag = 0;
uint32_t failure = 0;
+ int original_vgid_set = vgid ? 1 : 0;
int writing = (vg_read_flags & READ_FOR_UPDATE);
int activating = (vg_read_flags & READ_FOR_ACTIVATE);
@@ -5033,7 +5022,45 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, const
goto bad;
}
+ /* I belive this is unused, the name is always set. */
+ if (!vg_name && !(vg_name = lvmcache_vgname_from_vgid(cmd->mem, vgid))) {
+ unlock_vg(cmd, NULL, vg_name);
+ log_error("VG name not found for vgid %s", vgid);
+ failure |= FAILED_NOTFOUND;
+ goto_bad;
+ }
+
+ /*
+ * If the command is process all vgs, process_each will get a list of vgname+vgid
+ * pairs, and then call vg_read() for each vgname+vigd. In this case we know
+ * which VG to read even if there are duplicate names, and we don't fail.
+ *
+ * If the user has requested one VG by name, process_each passes only the vgname
+ * to vg_read(), and we look up the vgid from lvmcache. lvmcache finds duplicate
+ * vgnames, doesn't know which is intended, returns a NULL vgid, and we fail.
+ */
+
+ if (!vgid)
+ vgid = lvmcache_vgid_from_vgname(cmd, vg_name);
+
+ if (!vgid) {
+ unlock_vg(cmd, NULL, vg_name);
+ /* Some callers don't care if the VG doesn't exist and don't want an error message. */
+ if (!(vg_read_flags & READ_OK_NOTFOUND))
+ log_error("Volume group \"%s\" not found", vg_name);
+ failure |= FAILED_NOTFOUND;
+ goto_bad;
+ }
+
+ /*
+ * vgchange -ay (no vgname arg) will activate multiple local VGs with the same
+ * name, but if the vgs have the same lv name, activating those lvs will fail.
+ */
+ if (activating && original_vgid_set && lvmcache_has_duplicate_local_vgname(vgid, vg_name))
+ log_warn("WARNING: activating multiple VGs with the same name is dangerous and may fail.");
+
if (!(vg = _vg_read(cmd, vg_name, vgid, 0, writing))) {
+ unlock_vg(cmd, NULL, vg_name);
/* Some callers don't care if the VG doesn't exist and don't want an error message. */
if (!(vg_read_flags & READ_OK_NOTFOUND))
log_error("Volume group \"%s\" not found.", vg_name);
diff --git a/test/shell/duplicate-vgnames.sh b/test/shell/duplicate-vgnames.sh
new file mode 100644
index 000000000..0f98f9c37
--- /dev/null
+++ b/test/shell/duplicate-vgnames.sh
@@ -0,0 +1,660 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2008-2013 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+
+SKIP_WITH_LVMLOCKD=1
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux prepare_devs 7
+
+# test setups:
+# # local vgs named foo # foreign vg named foo
+# a. 0 1
+# b. 0 2
+# c. 1 1
+# d. 1 2
+# e. 2 0
+# f. 2 1
+# g. 2 2
+# h. 3 3
+#
+# commands to run for each test setup:
+#
+# vgs
+# all cases show all local
+#
+# vgs --foreign
+# all cases show all local and foreign
+#
+# vgs foo
+# a. not found
+# b. not found
+# c. show 1 local
+# d. show 1 local
+# e-g. dup error
+#
+# vgs --foreign foo
+# a. show 1 foreign
+# b. dup error
+# c. show 1 local
+# d. show 1 local
+# e-g. dup error
+#
+# vgchange -ay
+# a. none
+# b. none
+# c. activate 1 local
+# d. activate 1 local
+# e-g. activate 2 local
+# (if both local vgs have lvs with same name the second will fail to activate)
+#
+# vgchange -ay foo
+# a. none
+# b. none
+# c. activate 1 local
+# d. activate 1 local
+# e-g. dup error
+#
+# lvcreate foo
+# a. none
+# b. none
+# c. create 1 local
+# d. create 1 local
+# e-g. dup error
+#
+# vgremove foo
+# a. none
+# b. none
+# c. remove 1 local
+# d. remove 1 local
+# e-g. dup error
+# (in a couple cases test that vgremove -S vg_uuid=N works for local vg when local dups exist)
+
+
+# a. 0 local, 1 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+
+vgs -o+uuid |tee out
+not grep $vg1 out
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+
+not vgs -o+uuid $vg1 |tee out
+not grep $vg1 out
+vgs --foreign -o+uuid $vg1 |tee out
+grep $vg1 out
+
+vgchange -ay
+lvs --foreign -o vguuid,active |tee out
+not grep active out
+vgchange -an
+
+not vgchange -ay $vg1
+lvs --foreign -o vguuid,active |tee out
+not grep active out
+vgchange -an
+
+not lvcreate -l1 -an -n $lv2 $vg1
+lvs --foreign -o vguuid,name |tee out
+grep $UUID1 out | not grep $lv2
+
+not vgremove $vg1
+vgs --foreign -o+uuid |tee out
+grep $UUID1 out
+vgremove -y -S vg_uuid=$UUID1
+vgs --foreign -o+uuid |tee out
+grep $UUID1 out
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+
+# b. 0 local, 2 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other2" $vg1
+aux enable_dev "$dev1"
+
+vgs -o+uuid |tee out
+not grep $vg1 out
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+
+not vgs -o+uuid $vg1 |tee out
+not grep $vg1 out
+not vgs --foreign -o+uuid $vg1 |tee out
+not grep $vg1 out
+
+vgchange -ay
+lvs --foreign -o vguuid,active |tee out
+not grep active out
+vgchange -an
+
+not vgchange -ay $vg1
+lvs --foreign -o vguuid,active |tee out
+not grep active out
+vgchange -an
+
+not lvcreate -l1 -an -n $lv2 $vg1
+lvs --foreign -o vguuid,name |tee out
+grep $UUID1 out | not grep $lv2
+grep $UUID2 out | not grep $lv2
+
+not vgremove $vg1
+vgs --foreign -o+uuid |tee out
+grep $UUID1 out
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev3"
+
+# c. 1 local, 1 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+aux enable_dev "$dev1"
+
+vgs -o+uuid |tee out
+cat out
+grep $vg1 out
+grep $UUID1 out
+not grep $UUID2 out
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+
+vgs -o+uuid $vg1 |tee out
+grep $vg1 out
+grep $UUID1 out
+not grep $UUID2 out
+vgs --foreign -o+uuid $vg1 |tee out
+grep $vg1 out
+grep $UUID1 out
+not grep $UUID2 out
+
+vgchange -ay
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | grep active
+grep $UUID2 out | not grep active
+vgchange -an
+
+vgchange -ay $vg1
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | grep active
+grep $UUID2 out | not grep active
+vgchange -an
+
+lvcreate -l1 -an -n $lv2 $vg1
+lvs --foreign -o vguuid,name |tee out
+grep $UUID1 out | grep $lv2
+grep $UUID2 out | not grep $lv2
+
+vgremove -y $vg1
+vgs -o+uuid |tee out
+not grep $UUID1 out
+vgs --foreign -o+uuid |tee out
+grep $UUID2 out
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev3"
+
+# d. 1 local, 2 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+aux disable_dev "$dev2"
+vgcreate $vg1 "$dev3"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other2" $vg1
+aux enable_dev "$dev1"
+aux enable_dev "$dev2"
+
+vgs -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+not grep $UUID2 out
+not grep $UUID3 out
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+
+vgs -o+uuid $vg1 |tee out
+grep $vg1 out
+grep $UUID1 out
+not grep $UUID2 out
+not grep $UUID3 out
+vgs --foreign -o+uuid $vg1 |tee out
+grep $vg1 out
+grep $UUID1 out
+not grep $UUID2 out
+not grep $UUID3 out
+
+vgchange -ay
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | grep active
+grep $UUID2 out | not grep active
+grep $UUID3 out | not grep active
+vgchange -an
+
+vgchange -ay $vg1
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | grep active
+grep $UUID2 out | not grep active
+grep $UUID3 out | not grep active
+vgchange -an
+
+lvcreate -l1 -an -n $lv2 $vg1
+lvs --foreign -o vguuid,name |tee out
+grep $UUID1 out | grep $lv2
+grep $UUID2 out | not grep $lv2
+grep $UUID3 out | not grep $lv2
+
+vgremove -y $vg1
+vgs -o+uuid |tee out
+not grep $UUID1 out
+vgs --foreign -o+uuid |tee out
+grep $UUID2 out
+grep $UUID3 out
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev3"
+aux wipefs_a "$dev4"
+
+# e. 2 local, 0 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+# diff lvname to prevent clash in vgchange -ay
+lvcreate -n ${lv1}_b -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux enable_dev "$dev1"
+
+vgs -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+
+not vgs -o+uuid $vg1 |tee out
+not grep $vg1 out
+not vgs --foreign -o+uuid $vg1 |tee out
+not grep $vg1 out
+
+vgchange -ay
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | grep active
+grep $UUID2 out | grep active
+vgchange -an
+
+not vgchange -ay $vg1
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | not grep active
+grep $UUID2 out | not grep active
+vgchange -an
+
+not lvcreate -l1 -an -n $lv2 $vg1
+lvs --foreign -o vguuid,name |tee out
+grep $UUID1 out | not grep $lv2
+grep $UUID2 out | not grep $lv2
+
+not vgremove $vg1
+vgs -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+vgremove -y -S vg_uuid=$UUID1
+vgs -o+uuid |tee out
+not grep $UUID1 out
+grep $UUID2 out
+vgremove -y -S vg_uuid=$UUID2
+vgs -o+uuid |tee out
+not grep $UUID1 out
+not grep $UUID2 out
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev3"
+
+# f. 2 local, 1 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+# diff lvname to prevent clash in vgchange -ay
+lvcreate -n ${lv1}_b -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev2"
+vgcreate $vg1 "$dev3"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+aux enable_dev "$dev1"
+aux enable_dev "$dev2"
+
+vgs -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+not group $UUID3 out
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+
+not vgs -o+uuid $vg1 |tee out
+not grep $vg1 out
+not vgs --foreign -o+uuid $vg1 |tee out
+not grep $vg1 out
+
+vgchange -ay
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | grep active
+grep $UUID2 out | grep active
+grep $UUID3 out | not grep active
+vgchange -an
+
+not vgchange -ay $vg1
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | not grep active
+grep $UUID2 out | not grep active
+grep $UUID3 out | not grep active
+vgchange -an
+
+not lvcreate -l1 -an -n $lv2 $vg1
+lvs --foreign -o vguuid,name |tee out
+grep $UUID1 out | not grep $lv2
+grep $UUID2 out | not grep $lv2
+grep $UUID3 out | not grep $lv2
+
+not vgremove $vg1
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+vgremove -y -S vg_uuid=$UUID1
+vgs --foreign -o+uuid |tee out
+not grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+vgremove -y -S vg_uuid=$UUID2
+vgs --foreign -o+uuid |tee out
+not grep $UUID1 out
+not grep $UUID2 out
+grep $UUID3 out
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev3"
+aux wipefs_a "$dev4"
+
+# g. 2 local, 2 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+# diff lvname to prevent clash in vgchange -ay
+lvcreate -n ${lv1}_b -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev2"
+vgcreate $vg1 "$dev3"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+aux disable_dev "$dev3"
+vgcreate $vg1 "$dev4"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID4=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other2" $vg1
+aux enable_dev "$dev1"
+aux enable_dev "$dev2"
+aux enable_dev "$dev3"
+
+vgs -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+not group $UUID3 out
+not group $UUID4 out
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+grep $UUID4 out
+
+not vgs -o+uuid $vg1 |tee out
+not grep $vg1 out
+not vgs --foreign -o+uuid $vg1 |tee out
+not grep $vg1 out
+
+vgchange -ay
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | grep active
+grep $UUID2 out | grep active
+grep $UUID3 out | not grep active
+grep $UUID4 out | not grep active
+vgchange -an
+
+not vgchange -ay $vg1
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | not grep active
+grep $UUID2 out | not grep active
+grep $UUID3 out | not grep active
+grep $UUID4 out | not grep active
+vgchange -an
+
+not lvcreate -l1 -an -n $lv2 $vg1
+lvs --foreign -o vguuid,name |tee out
+grep $UUID1 out | not grep $lv2
+grep $UUID2 out | not grep $lv2
+grep $UUID3 out | not grep $lv2
+grep $UUID4 out | not grep $lv2
+
+not vgremove $vg1
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+grep $UUID4 out
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev3"
+aux wipefs_a "$dev4"
+aux wipefs_a "$dev5"
+
+# h. 3 local, 3 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+# diff lvname to prevent clash in vgchange -ay
+lvcreate -n ${lv1}_b -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev2"
+vgcreate $vg1 "$dev3"
+# diff lvname to prevent clash in vgchange -ay
+lvcreate -n ${lv1}_bb -l1 -an $vg1
+UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev3"
+vgcreate $vg1 "$dev4"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID4=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+aux disable_dev "$dev4"
+vgcreate $vg1 "$dev5"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID5=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other2" $vg1
+aux disable_dev "$dev5"
+vgcreate $vg1 "$dev6"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID6=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other3" $vg1
+aux enable_dev "$dev1"
+aux enable_dev "$dev2"
+aux enable_dev "$dev3"
+aux enable_dev "$dev4"
+aux enable_dev "$dev5"
+
+vgs -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+not group $UUID4 out
+not group $UUID5 out
+not group $UUID6 out
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+grep $UUID4 out
+grep $UUID5 out
+grep $UUID6 out
+
+not vgs -o+uuid $vg1 |tee out
+not grep $vg1 out
+not vgs --foreign -o+uuid $vg1 |tee out
+not grep $vg1 out
+
+vgchange -ay
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | grep active
+grep $UUID2 out | grep active
+grep $UUID3 out | grep active
+grep $UUID4 out | not grep active
+grep $UUID5 out | not grep active
+grep $UUID6 out | not grep active
+vgchange -an
+
+not vgchange -ay $vg1
+lvs --foreign -o vguuid,active |tee out
+grep $UUID1 out | not grep active
+grep $UUID2 out | not grep active
+grep $UUID3 out | not grep active
+grep $UUID4 out | not grep active
+grep $UUID5 out | not grep active
+grep $UUID6 out | not grep active
+vgchange -an
+
+not lvcreate -l1 -an -n $lv2 $vg1
+lvs --foreign -o vguuid,name |tee out
+grep $UUID1 out | not grep $lv2
+grep $UUID2 out | not grep $lv2
+grep $UUID3 out | not grep $lv2
+grep $UUID4 out | not grep $lv2
+grep $UUID5 out | not grep $lv2
+grep $UUID6 out | not grep $lv2
+
+not vgremove $vg1
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+grep $UUID4 out
+grep $UUID5 out
+grep $UUID6 out
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev3"
+aux wipefs_a "$dev4"
+aux wipefs_a "$dev5"
+aux wipefs_a "$dev6"
+
+# vgreduce test with 1 local and 1 foreign vg.
+# setup
+vgcreate $vg1 "$dev1" "$dev7"
+lvcreate -n $lv1 -l1 -an $vg1 "$dev1"
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+PV1UUID=$(pvs --noheading -o uuid "$dev1")
+PV7UUID=$(pvs --noheading -o uuid "$dev7")
+aux disable_dev "$dev1"
+aux disable_dev "$dev7"
+vgcreate $vg1 "$dev2"
+PV2UUID=$(pvs --noheading -o uuid "$dev2")
+lvcreate -n $lv1 -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+aux enable_dev "$dev1"
+aux enable_dev "$dev7"
+
+vgs --foreign -o+uuid |tee out
+grep $vg1 out
+grep $UUID1 out
+grep $UUID2 out
+pvs --foreign -o+uuid |tee out
+grep $PV1UUID out
+grep $PV7UUID out
+grep $PV2UUID out
+
+vgreduce $vg1 "$dev7"
+
+pvs --foreign -o+uuid |tee out
+grep $PV1UUID out
+grep $PV7UUID out
+grep $PV2UUID out
+
+grep $PV7UUID out >out2
+not grep $vg1 out2
+
+vgremove -ff $vg1
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev7"
diff --git a/test/shell/duplicate-vgrename.sh b/test/shell/duplicate-vgrename.sh
new file mode 100644
index 000000000..86282206f
--- /dev/null
+++ b/test/shell/duplicate-vgrename.sh
@@ -0,0 +1,319 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2008-2013 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+
+SKIP_WITH_LVMLOCKD=1
+SKIP_WITH_LVMPOLLD=1
+
+. lib/inittest
+
+aux prepare_devs 4
+
+# a. 0 local, 1 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+
+not vgrename $vg1 $vg2
+vgs --foreign -o+uuid |tee out
+grep $UUID1 out
+not vgrename $UUID1 $vg2
+vgs --foreign -o+uuid |tee out
+grep $UUID1 out
+
+lvs --foreign
+
+aux wipefs_a "$dev1"
+
+# b. 0 local, 2 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other2" $vg1
+aux enable_dev "$dev1"
+
+not vgrename $vg1 $vg2
+vgs --foreign -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+not grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+not vgrename $UUID1 $vg2
+vgs --foreign -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+not grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+
+lvs --foreign
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+
+# c. 1 local, 1 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+aux enable_dev "$dev1"
+
+vgrename $vg1 $vg2
+vgs --foreign -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+not vgrename $vg2 $vg1
+vgs --foreign -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+
+lvs --foreign
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+
+# d. 1 local, 2 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+aux disable_dev "$dev2"
+vgcreate $vg1 "$dev3"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other2" $vg1
+aux enable_dev "$dev1"
+aux enable_dev "$dev2"
+
+vgrename $vg1 $vg2
+vgs --foreign -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+not vgrename $vg2 $vg1
+vgs --foreign -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+
+lvs --foreign
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev3"
+
+# e. 2 local, 0 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+lvcreate -n ${lv1}_b -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux enable_dev "$dev1"
+
+not vgrename $vg1 $vg2
+vgs -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+not grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+vgrename $UUID1 $vg2
+vgs -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+not vgrename $UUID2 $vg2
+vgs -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+
+lvs --foreign
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+
+# f. 2 local, 1 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+lvcreate -n ${lv1}_b -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev2"
+vgcreate $vg1 "$dev3"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+vgchange -y --systemid "other" $vg1
+aux enable_dev "$dev1"
+aux enable_dev "$dev2"
+lvs --foreign
+
+not vgrename $vg1 $vg2
+vgs --foreign -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+not grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+vgrename $UUID1 $vg2
+vgs --foreign -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+vgrename $vg1 $vg3
+vgs --foreign -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $vg3 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+not vgrename $vg2 $vg1
+vgs --foreign -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $vg3 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+not vgrename $vg2 $vg3
+vgs --foreign -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $vg3 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+
+lvs --foreign
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev3"
+
+# g. 3 local, 0 foreign
+# setup
+vgcreate $vg1 "$dev1"
+lvcreate -n $lv1 -l1 -an $vg1
+UUID1=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev1"
+vgcreate $vg1 "$dev2"
+lvcreate -n ${lv1}_b -l1 -an $vg1
+UUID2=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux disable_dev "$dev2"
+vgcreate $vg1 "$dev3"
+lvcreate -n ${lv1}_c -l1 -an $vg1
+UUID3=$(vgs --noheading -o vg_uuid $vg1 | xargs)
+aux enable_dev "$dev1"
+aux enable_dev "$dev2"
+
+not vgrename $vg1 $vg2
+vgs -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+not grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+vgrename $UUID1 $vg2
+vgs -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+not vgrename $vg1 $vg2
+vgs -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+not vgrename $vg1 $vg3
+vgs -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+not grep $vg3 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+not vgrename $UUID2 $vg2
+vgs -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+not grep $vg3 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+vgrename $UUID2 $vg3
+vgs -o+uuid |tee out
+lvs --foreign
+grep $vg1 out
+grep $vg2 out
+grep $vg3 out
+grep $UUID1 out
+grep $UUID2 out
+grep $UUID3 out
+
+lvs --foreign
+
+aux wipefs_a "$dev1"
+aux wipefs_a "$dev2"
+aux wipefs_a "$dev3"
+
diff --git a/test/shell/process-each-duplicate-vgnames.sh b/test/shell/process-each-duplicate-vgnames.sh
deleted file mode 100644
index a59c3bd9b..000000000
--- a/test/shell/process-each-duplicate-vgnames.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (C) 2008-2013 Red Hat, Inc. All rights reserved.
-#
-# This copyrighted material is made available to anyone wishing to use,
-# modify, copy, or redistribute it subject to the terms and conditions
-# of the GNU General Public License v.2.
-
-test_description='Test vgs with duplicate vg names'
-SKIP_WITH_LVMLOCKD=1
-SKIP_WITH_LVMPOLLD=1
-
-. lib/inittest
-
-aux prepare_devs 2
-
-pvcreate "$dev1"
-pvcreate "$dev2"
-
-aux disable_dev "$dev1" "$dev2"
-
-aux enable_dev "$dev1"
-vgcreate $vg1 "$dev1"
-UUID1=$(vgs --noheading -o vg_uuid $vg1)
-aux disable_dev "$dev1"
-
-aux enable_dev "$dev2"
-vgcreate $vg1 "$dev2"
-UUID2=$(vgs --noheading -o vg_uuid $vg1)
-
-aux enable_dev "$dev1"
-pvscan --cache "$dev1"
-pvs "$dev1"
-pvs "$dev2"
-
-vgs -o+vg_uuid | tee err
-grep $UUID1 err
-grep $UUID2 err
-
-# should we specify and test which should be displayed?
-# vgs --noheading -o vg_uuid $vg1 >err
-# grep $UUID1 err
-
-aux disable_dev "$dev2"
-vgs -o+vg_uuid | tee err
-grep $UUID1 err
-not grep $UUID2 err
-aux enable_dev "$dev2"
-pvscan --cache "$dev2"
-
-aux disable_dev "$dev1"
-vgs -o+vg_uuid | tee err
-grep $UUID2 err
-not grep $UUID1 err
-aux enable_dev "$dev1"
diff --git a/tools/toollib.c b/tools/toollib.c
index 96d0d6dff..89b637407 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1853,8 +1853,6 @@ static int _resolve_duplicate_vgnames(struct cmd_context *cmd,
if (lvmcache_vg_is_foreign(cmd, vgnl->vg_name, vgnl->vgid)) {
if (!id_write_format((const struct id*)vgnl->vgid, uuid, sizeof(uuid)))
stack;
- log_warn("WARNING: Ignoring foreign VG with matching name %s UUID %s.",
- vgnl->vg_name, uuid);
dm_list_del(&vgnl->list);
} else {
found++;
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2020-04-21 19:51 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-04-21 19:51 master - lvmcache: rework handling of VGs with duplicate vgnames David Teigland
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.