From f82c499dfee90f16cd2a1352d05afae7ae830c14 Mon Sep 17 00:00:00 2001 From: David Teigland Date: Fri, 18 Sep 2015 09:42:38 -0500 Subject: lvmetad: fix update_metadata with new vgid When vgchange -u changes the vgid in an existing VG, it invokes update_metadata() in lvmetad with the existing VG name but a new vgid. update_metadata() doesn't recognize this condition, and ends up with in correct state, e.g. the existing name is missing in the vgname_to_vgid hash table. This fixes update_metadata() to recognize when an existing VG name is being updated with a new vgid, and in that case first calls remove_metadata() on the old vgid, before continuing with update_metadata() which will add the updated VG as if it were new. One known shortcoming of this approach is that the VG is missing from lvmetad hash tables completely in the short time between the remove and adding it again. Other commands that look up the VG in that window will not find it. --- daemons/lvmetad/lvmetad-core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c index 89aaaf84c..f8c712978 100644 --- a/daemons/lvmetad/lvmetad-core.c +++ b/daemons/lvmetad/lvmetad-core.c @@ -843,13 +843,26 @@ static int update_metadata(lvmetad_state *s, const char *name, const char *_vgid int seq; int haveseq = -1; const char *oldname = NULL; + const char *oldvgid = NULL; const char *vgid; char *cfgname; lock_vgid_to_metadata(s); old = dm_hash_lookup(s->vgid_to_metadata, _vgid); oldname = dm_hash_lookup(s->vgid_to_vgname, _vgid); + /* If _vgid is unknown, it may be a new vgid for an existing vg. */ + if (!oldname) + oldvgid = dm_hash_lookup(s->vgname_to_vgid, name); unlock_vgid_to_metadata(s); + + if (oldvgid) { + DEBUGLOG(s, "Existing name %s with vgid %s has new vgid %s", + name, oldvgid, _vgid); + remove_metadata(s, oldvgid, 1); + oldname = NULL; + oldvgid = NULL; + } + lock_vg(s, _vgid); seq = dm_config_find_int(metadata, "metadata/seqno", -1); -- cgit v1.2.1