[lvm-devel] master - lvmetad: Avoid overlapping locks that could cause a deadlock (BZ 862253).
Petr Rockai
mornfall at fedoraproject.org
Mon Oct 8 10:10:00 UTC 2012
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=6e312c56adb04e709819868c6fa89f5984013a65
Commit: 6e312c56adb04e709819868c6fa89f5984013a65
Parent: 0dfafd77d4c5682ac9ee37f3a2a4dce92659187c
Author: Petr Rockai <prockai at redhat.com>
AuthorDate: Mon Oct 8 09:12:51 2012 +0200
Committer: Petr Rockai <prockai at redhat.com>
CommitterDate: Mon Oct 8 09:12:51 2012 +0200
lvmetad: Avoid overlapping locks that could cause a deadlock (BZ 862253).
---
daemons/lvmetad/lvmetad-core.c | 16 ++++++++++++----
1 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index 0c39a77..dce7535 100644
--- a/daemons/lvmetad/lvmetad-core.c
+++ b/daemons/lvmetad/lvmetad-core.c
@@ -38,6 +38,7 @@ typedef struct {
struct dm_hash_table *pvid_to_vgid;
struct {
struct dm_hash_table *vg;
+ pthread_mutex_t vg_lock_map;
pthread_mutex_t pvid_to_pvmeta;
pthread_mutex_t vgid_to_metadata;
pthread_mutex_t pvid_to_vgid;
@@ -112,7 +113,7 @@ static struct dm_config_tree *lock_vg(lvmetad_state *s, const char *id) {
pthread_mutex_t *vg;
struct dm_config_tree *cft;
- lock_vgid_to_metadata(s);
+ pthread_mutex_lock(&s->lock.vg_lock_map);
vg = dm_hash_lookup(s->lock.vg, id);
if (!vg) {
pthread_mutexattr_t rec;
@@ -126,8 +127,14 @@ static struct dm_config_tree *lock_vg(lvmetad_state *s, const char *id) {
return NULL;
}
}
+ /* We never remove items from s->lock.vg => the pointer remains valid. */
+ pthread_mutex_unlock(&s->lock.vg_lock_map);
+
DEBUG(s, "locking VG %s", id);
pthread_mutex_lock(vg);
+
+ /* Protect against structure changes of the vgid_to_metadata hash. */
+ lock_vgid_to_metadata(s);
cft = dm_hash_lookup(s->vgid_to_metadata, id);
unlock_vgid_to_metadata(s);
return cft;
@@ -137,11 +144,11 @@ static void unlock_vg(lvmetad_state *s, const char *id) {
pthread_mutex_t *vg;
DEBUG(s, "unlocking VG %s", id);
- lock_vgid_to_metadata(s); /* someone might be changing the s->lock.vg structure right
- * now, so avoid stepping on each other's toes */
+ /* Protect the s->lock.vg structure from concurrent access. */
+ pthread_mutex_lock(&s->lock.vg_lock_map);
if ((vg = dm_hash_lookup(s->lock.vg, id)))
pthread_mutex_unlock(vg);
- unlock_vgid_to_metadata(s);
+ pthread_mutex_unlock(&s->lock.vg_lock_map);
}
static struct dm_config_node *pvs(struct dm_config_node *vg)
@@ -975,6 +982,7 @@ static int init(daemon_state *s)
pthread_mutex_init(&ls->lock.pvid_to_pvmeta, &rec);
pthread_mutex_init(&ls->lock.vgid_to_metadata, &rec);
pthread_mutex_init(&ls->lock.pvid_to_vgid, NULL);
+ pthread_mutex_init(&ls->lock.vg_lock_map, NULL);
pthread_mutex_init(&ls->token_lock, NULL);
create_metadata_hashes(ls);
More information about the lvm-devel
mailing list