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_gre...@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 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel