86 lines
2.9 KiB
Diff
86 lines
2.9 KiB
Diff
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);
|