void-packages/srcpkgs/lvm2/patches/lvm2-2_02_99-lvmetad-fix-a-...

87 lines
2.9 KiB
Diff
Raw Normal View History

commit 98c5eb308690d990b957012db9d48b6722ea93cb
Author: Peter Rajnoha <prajnoha@redhat.com>
Date: Tue May 14 12:47:24 2013 +0200
lvm2-2_02_99-lvmetad-fix-a-race-in-metadata-update.patch
---
WHATS_NEW | 1 +
daemons/lvmetad/lvmetad-core.c | 21 +++++++++++++--------
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 20a8125..35c5e43 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.99 -
===================================
+ Fix a crash-inducing race condition in lvmetad while updating metadata.
Fix possible race while removing metadata from lvmetad.
Fix possible deadlock when querying and updating lvmetad at the same time.
Avoid a global lock in pvs when lvmetad is in use.
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index fed9296..1f855a7 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -450,7 +450,8 @@ static response vg_lookup(lvmetad_state *s, request r)
DEBUGLOG(s, "vg_lookup: updated uuid = %s, name = %s", uuid, name);
- if (!uuid)
+ /* Check the name here. */
+ if (!uuid || !name)
return reply_unknown("VG not found");
cft = lock_vg(s, uuid);
@@ -679,16 +680,14 @@ static int update_metadata(lvmetad_state *s, const char *name, const char *_vgid
lock_vgid_to_metadata(s);
old = dm_hash_lookup(s->vgid_to_metadata, _vgid);
+ oldname = dm_hash_lookup(s->vgid_to_vgname, _vgid);
unlock_vgid_to_metadata(s);
lock_vg(s, _vgid);
seq = dm_config_find_int(metadata, "metadata/seqno", -1);
- if (old) {
+ if (old)
haveseq = dm_config_find_int(old->root, "metadata/seqno", -1);
- oldname = dm_hash_lookup(s->vgid_to_vgname, _vgid);
- assert(oldname);
- }
if (seq < 0)
goto out;
@@ -740,7 +739,7 @@ static int update_metadata(lvmetad_state *s, const char *name, const char *_vgid
if (haveseq >= 0 && haveseq < seq) {
INFO(s, "Updating metadata for %s at %d to %d", _vgid, haveseq, seq);
/* temporarily orphan all of our PVs */
- remove_metadata(s, vgid, 1);
+ update_pvid_to_vgid(s, old, "#orphan", 0);
}
lock_vgid_to_metadata(s);
@@ -750,14 +749,20 @@ static int update_metadata(lvmetad_state *s, const char *name, const char *_vgid
dm_hash_insert(s->vgid_to_metadata, vgid, cft) &&
dm_hash_insert(s->vgid_to_vgname, vgid, cfgname) &&
dm_hash_insert(s->vgname_to_vgid, name, (void*) vgid)) ? 1 : 0;
+
+ if (retval && oldname && strcmp(name, oldname))
+ dm_hash_remove(s->vgname_to_vgid, oldname);
+
+ if (haveseq >= 0 && haveseq < seq)
+ dm_config_destroy(old);
+
unlock_vgid_to_metadata(s);
if (retval)
- /* FIXME: What should happen when update fails */
retval = update_pvid_to_vgid(s, cft, vgid, 1);
unlock_pvid_to_vgid(s);
-out:
+out: /* FIXME: We should probably abort() on partial failures. */
if (!retval && cft)
dm_config_destroy(cft);
unlock_vg(s, _vgid);