[pve-devel] [PATCH pve-cluster] Fix #2553: Prevent the Deadlock by aligning the lockorder
Kevin Greßlehner
kevin_gressi at live.at
Tue Jan 14 12:48:28 CET 2020
Kevin Greßlehner (1):
Fix #2553: Fix for Deadlock by aligning the lockorder - Lock
&memdb->mutex in memdb_read and refer to a new method
"memdb_read_nolock" in memdb.c which doesn't handle locks by itself.
This method then handles the stuff which was originally in
memdb_read. Therefore everything except
cfs_create_guest_conf_property_msg uses memdb_read (which handles
the locking itself), and cfs_create_guest_conf_property_msg prelocks
&memdb->mutex and invokes memdb_read_nolock.
Signed-off-by: Kevin Greßlehner <kevin_gressi at live.at>
---
Approach #3 (Comment #7 of Bug #2553):
Tested for 6h straight - no Crashes nor Deadlocks appeared.
data/src/memdb.c | 42 +++++++++++++++++++++++++++---------------
data/src/memdb.h | 6 ++++++
data/src/status.c | 12 ++++++++----
3 files changed, 41 insertions(+), 19 deletions(-)
diff --git a/data/src/memdb.c b/data/src/memdb.c
index efc99ea..6c268df 100644
--- a/data/src/memdb.c
+++ b/data/src/memdb.c
@@ -659,32 +659,44 @@ int memdb_mkdir(
return ret;
}
+//Original memdb_read without locking - Caller MUST handle the locking - Fix for #2553
+int
+memdb_read_nolock(
+ memdb_t *memdb,
+ const char *path,
+ gpointer *data_ret)
+{
+ g_return_val_if_fail(memdb != NULL, -EINVAL);
+ g_return_val_if_fail(path != NULL, -EINVAL);
+ g_return_val_if_fail(data_ret != NULL, -EINVAL);
+
+ memdb_tree_entry_t *te, *parent;
+
+ if ((te = memdb_lookup_path(memdb, path, &parent))) {
+ if (te->type == DT_REG) {
+ *data_ret = g_memdup(te->data.value, te->size);
+ guint32 size = te->size;
+ return size;
+ }
+ }
+
+ return -ENOENT;
+}
+
int
memdb_read(
memdb_t *memdb,
const char *path,
gpointer *data_ret)
{
- g_return_val_if_fail(memdb != NULL, -EINVAL);
- g_return_val_if_fail(path != NULL, -EINVAL);
- g_return_val_if_fail(data_ret != NULL, -EINVAL);
-
- memdb_tree_entry_t *te, *parent;
-
+ int res;
g_mutex_lock (&memdb->mutex);
- if ((te = memdb_lookup_path(memdb, path, &parent))) {
- if (te->type == DT_REG) {
- *data_ret = g_memdup(te->data.value, te->size);
- guint32 size = te->size;
- g_mutex_unlock (&memdb->mutex);
- return size;
- }
- }
+ res = memdb_read_nolock(memdb, path, data_ret);
g_mutex_unlock (&memdb->mutex);
- return -ENOENT;
+ return res;
}
static int
diff --git a/data/src/memdb.h b/data/src/memdb.h
index 60df035..7659358 100644
--- a/data/src/memdb.h
+++ b/data/src/memdb.h
@@ -162,6 +162,12 @@ memdb_read(
const char *path,
gpointer *data_ret);
+int
+memdb_read_nolock(
+ memdb_t *memdb,
+ const char *path,
+ gpointer *data_ret);
+
int
memdb_create(
memdb_t *memdb,
diff --git a/data/src/status.c b/data/src/status.c
index 491082c..1dd2737 100644
--- a/data/src/status.c
+++ b/data/src/status.c
@@ -883,6 +883,9 @@ cfs_create_guest_conf_property_msg(GString *str, memdb_t *memdb, const char *pro
int res = 0;
GString *path = NULL;
+ //Prelock &memdb->mutex in order to enable the usage of memdb_read_nolock
+ //to prevent Deadlocks as in #2553
+ g_mutex_lock (&memdb->mutex);
g_mutex_lock (&mutex);
g_string_printf(str,"{\n");
@@ -899,8 +902,8 @@ cfs_create_guest_conf_property_msg(GString *str, memdb_t *memdb, const char *pro
if (vminfo == NULL) goto enoent;
if (!vminfo_to_path(vminfo, path)) goto err;
-
- int size = memdb_read(memdb, path->str, &tmp);
+ //use memdb_read_nolock because lock is handled here
+ int size = memdb_read_nolock(memdb, path->str, &tmp);
if (tmp == NULL) goto err;
if (size <= prop_len) goto ret;
@@ -924,7 +927,8 @@ cfs_create_guest_conf_property_msg(GString *str, memdb_t *memdb, const char *pro
g_free(tmp); // no-op if already null
tmp = NULL;
- int size = memdb_read(memdb, path->str, &tmp);
+ //use memdb_read_nolock because lock is handled here
+ int size = memdb_read_nolock(memdb, path->str, &tmp);
if (tmp == NULL || size <= prop_len) continue;
char *val = _get_property_value(tmp, size, prop, prop_len);
@@ -945,7 +949,7 @@ ret:
}
g_string_append_printf(str,"\n}\n");
g_mutex_unlock (&mutex);
-
+ g_mutex_unlock (&memdb->mutex);
return res;
err:
res = -EIO;
--
2.20.1
More information about the pve-devel
mailing list