aboutsummaryrefslogtreecommitdiff
path: root/daemons
diff options
context:
space:
mode:
authorPetr Rockai <prockai@redhat.com>2012-12-17 00:43:18 +0100
committerPetr Rockai <prockai@redhat.com>2012-12-17 00:47:55 +0100
commit5294a6f77a900493b3e81eb70c1698ec3c4814b8 (patch)
tree3616f42b53df8a189df640390b12be1c5d99622b /daemons
parentfae1a611d2f907aa23c237b9f84df5089d30f728 (diff)
downloadlvm2-5294a6f77a900493b3e81eb70c1698ec3c4814b8.tar.gz
lvmetad: Fix a possible race in remove_metadata.
All operations on shared hash tables need to be protected by mutexes. Moreover, lookup and subsequent key removal need to happen atomically, to avoid races (and possible double free-ing) between multiple threads trying to manipulate the same VG.
Diffstat (limited to 'daemons')
-rw-r--r--daemons/lvmetad/lvmetad-core.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index 674ddea87..a951b3052 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -601,19 +601,23 @@ static int remove_metadata(lvmetad_state *s, const char *vgid, int update_pvids)
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);
- if (!old)
+ if (!old) {
+ unlock_vgid_to_metadata(s);
return 0;
+ }
+
assert(oldname);
- if (update_pvids)
- /* FIXME: What should happen when update fails */
- update_pvid_to_vgid(s, old, "#orphan", 0);
/* need to update what we have since we found a newer version */
dm_hash_remove(s->vgid_to_metadata, vgid);
dm_hash_remove(s->vgid_to_vgname, vgid);
dm_hash_remove(s->vgname_to_vgid, oldname);
+ unlock_vgid_to_metadata(s);
+
+ if (update_pvids)
+ /* FIXME: What should happen when update fails */
+ update_pvid_to_vgid(s, old, "#orphan", 0);
dm_config_destroy(old);
return 1;
}