diff options
author | Petr Rockai <prockai@redhat.com> | 2012-12-17 00:43:18 +0100 |
---|---|---|
committer | Petr Rockai <prockai@redhat.com> | 2012-12-17 00:47:55 +0100 |
commit | 5294a6f77a900493b3e81eb70c1698ec3c4814b8 (patch) | |
tree | 3616f42b53df8a189df640390b12be1c5d99622b /daemons | |
parent | fae1a611d2f907aa23c237b9f84df5089d30f728 (diff) | |
download | lvm2-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.c | 14 |
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; } |