aboutsummaryrefslogtreecommitdiff
path: root/daemons
diff options
context:
space:
mode:
authorPetr Rockai <prockai@redhat.com>2012-10-08 09:12:51 +0200
committerPetr Rockai <prockai@redhat.com>2012-10-08 09:12:51 +0200
commit6e312c56adb04e709819868c6fa89f5984013a65 (patch)
treeec185bd57ef51a17a6c1fed7be9baa04bf131424 /daemons
parent0dfafd77d4c5682ac9ee37f3a2a4dce92659187c (diff)
downloadlvm2-6e312c56adb04e709819868c6fa89f5984013a65.tar.gz
lvmetad: Avoid overlapping locks that could cause a deadlock (BZ 862253).
Diffstat (limited to 'daemons')
-rw-r--r--daemons/lvmetad/lvmetad-core.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c
index 0c39a7786..dce7535b5 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);