e3c68b
From 11b64d494c52004002f900888694d20ef8af6df6 Mon Sep 17 00:00:00 2001
e3c68b
From: Mohammed Rafi KC <rkavunga@redhat.com>
e3c68b
Date: Sat, 11 May 2019 22:40:22 +0530
e3c68b
Subject: [PATCH 158/169] glusterfsd/cleanup: Protect graph object under a lock
e3c68b
e3c68b
While processing a cleanup_and_exit function, we are
e3c68b
accessing a graph object. But this has not been protected
e3c68b
under a lock. Because a parallel cleanup of a graph is quite
e3c68b
possible which might lead to an invalid memory access
e3c68b
e3c68b
Upstream patch:https://review.gluster.org/#/c/glusterfs/+/22709/
e3c68b
e3c68b
>Change-Id: Id05ca70d5b57e172b0401d07b6a1f5386c044e79
e3c68b
>fixes: bz#1708926
e3c68b
>Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
e3c68b
e3c68b
Change-Id: I55ab0525c79baa99a3bd929ee979c5519be5ab21
e3c68b
BUG: 1716626
e3c68b
Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
e3c68b
Reviewed-on: https://code.engineering.redhat.com/gerrit/172283
e3c68b
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
e3c68b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e3c68b
---
e3c68b
 libglusterfs/src/graph.c                        | 58 +++++++++++++++----------
e3c68b
 libglusterfs/src/statedump.c                    | 16 +++++--
e3c68b
 tests/bugs/glusterd/optimized-basic-testcases.t |  4 +-
e3c68b
 3 files changed, 50 insertions(+), 28 deletions(-)
e3c68b
e3c68b
diff --git a/libglusterfs/src/graph.c b/libglusterfs/src/graph.c
e3c68b
index 4c8b02d..18fb2d9 100644
e3c68b
--- a/libglusterfs/src/graph.c
e3c68b
+++ b/libglusterfs/src/graph.c
e3c68b
@@ -1392,8 +1392,12 @@ glusterfs_graph_cleanup(void *arg)
e3c68b
     }
e3c68b
     pthread_mutex_unlock(&ctx->notify_lock);
e3c68b
 
e3c68b
-    glusterfs_graph_fini(graph);
e3c68b
-    glusterfs_graph_destroy(graph);
e3c68b
+    pthread_mutex_lock(&ctx->cleanup_lock);
e3c68b
+    {
e3c68b
+        glusterfs_graph_fini(graph);
e3c68b
+        glusterfs_graph_destroy(graph);
e3c68b
+    }
e3c68b
+    pthread_mutex_unlock(&ctx->cleanup_lock);
e3c68b
 out:
e3c68b
     return NULL;
e3c68b
 }
e3c68b
@@ -1468,31 +1472,37 @@ glusterfs_process_svc_detach(glusterfs_ctx_t *ctx, gf_volfile_t *volfile_obj)
e3c68b
 
e3c68b
     if (!ctx || !ctx->active || !volfile_obj)
e3c68b
         goto out;
e3c68b
-    parent_graph = ctx->active;
e3c68b
-    graph = volfile_obj->graph;
e3c68b
-    if (!graph)
e3c68b
-        goto out;
e3c68b
-    if (graph->first)
e3c68b
-        xl = graph->first;
e3c68b
 
e3c68b
-    last_xl = graph->last_xl;
e3c68b
-    if (last_xl)
e3c68b
-        last_xl->next = NULL;
e3c68b
-    if (!xl || xl->cleanup_starting)
e3c68b
-        goto out;
e3c68b
+    pthread_mutex_lock(&ctx->cleanup_lock);
e3c68b
+    {
e3c68b
+        parent_graph = ctx->active;
e3c68b
+        graph = volfile_obj->graph;
e3c68b
+        if (!graph)
e3c68b
+            goto unlock;
e3c68b
+        if (graph->first)
e3c68b
+            xl = graph->first;
e3c68b
+
e3c68b
+        last_xl = graph->last_xl;
e3c68b
+        if (last_xl)
e3c68b
+            last_xl->next = NULL;
e3c68b
+        if (!xl || xl->cleanup_starting)
e3c68b
+            goto unlock;
e3c68b
 
e3c68b
-    xl->cleanup_starting = 1;
e3c68b
-    gf_msg("mgmt", GF_LOG_INFO, 0, LG_MSG_GRAPH_DETACH_STARTED,
e3c68b
-           "detaching child %s", volfile_obj->vol_id);
e3c68b
+        xl->cleanup_starting = 1;
e3c68b
+        gf_msg("mgmt", GF_LOG_INFO, 0, LG_MSG_GRAPH_DETACH_STARTED,
e3c68b
+               "detaching child %s", volfile_obj->vol_id);
e3c68b
 
e3c68b
-    list_del_init(&volfile_obj->volfile_list);
e3c68b
-    glusterfs_mux_xlator_unlink(parent_graph->top, xl);
e3c68b
-    parent_graph->last_xl = glusterfs_get_last_xlator(parent_graph);
e3c68b
-    parent_graph->xl_count -= graph->xl_count;
e3c68b
-    parent_graph->leaf_count -= graph->leaf_count;
e3c68b
-    default_notify(xl, GF_EVENT_PARENT_DOWN, xl);
e3c68b
-    parent_graph->id++;
e3c68b
-    ret = 0;
e3c68b
+        list_del_init(&volfile_obj->volfile_list);
e3c68b
+        glusterfs_mux_xlator_unlink(parent_graph->top, xl);
e3c68b
+        parent_graph->last_xl = glusterfs_get_last_xlator(parent_graph);
e3c68b
+        parent_graph->xl_count -= graph->xl_count;
e3c68b
+        parent_graph->leaf_count -= graph->leaf_count;
e3c68b
+        default_notify(xl, GF_EVENT_PARENT_DOWN, xl);
e3c68b
+        parent_graph->id++;
e3c68b
+        ret = 0;
e3c68b
+    }
e3c68b
+unlock:
e3c68b
+    pthread_mutex_unlock(&ctx->cleanup_lock);
e3c68b
 out:
e3c68b
     if (!ret) {
e3c68b
         list_del_init(&volfile_obj->volfile_list);
e3c68b
diff --git a/libglusterfs/src/statedump.c b/libglusterfs/src/statedump.c
e3c68b
index 0cf80c0..0d58f8f 100644
e3c68b
--- a/libglusterfs/src/statedump.c
e3c68b
+++ b/libglusterfs/src/statedump.c
e3c68b
@@ -805,11 +805,17 @@ gf_proc_dump_info(int signum, glusterfs_ctx_t *ctx)
e3c68b
     int brick_count = 0;
e3c68b
     int len = 0;
e3c68b
 
e3c68b
-    gf_proc_dump_lock();
e3c68b
-
e3c68b
     if (!ctx)
e3c68b
         goto out;
e3c68b
 
e3c68b
+    /*
e3c68b
+     * Multiplexed daemons can change the active graph when attach/detach
e3c68b
+     * is called. So this has to be protected with the cleanup lock.
e3c68b
+     */
e3c68b
+    if (mgmt_is_multiplexed_daemon(ctx->cmd_args.process_name))
e3c68b
+        pthread_mutex_lock(&ctx->cleanup_lock);
e3c68b
+    gf_proc_dump_lock();
e3c68b
+
e3c68b
     if (!mgmt_is_multiplexed_daemon(ctx->cmd_args.process_name) &&
e3c68b
         (ctx && ctx->active)) {
e3c68b
         top = ctx->active->first;
e3c68b
@@ -923,7 +929,11 @@ gf_proc_dump_info(int signum, glusterfs_ctx_t *ctx)
e3c68b
 out:
e3c68b
     GF_FREE(dump_options.dump_path);
e3c68b
     dump_options.dump_path = NULL;
e3c68b
-    gf_proc_dump_unlock();
e3c68b
+    if (ctx) {
e3c68b
+        gf_proc_dump_unlock();
e3c68b
+        if (mgmt_is_multiplexed_daemon(ctx->cmd_args.process_name))
e3c68b
+            pthread_mutex_unlock(&ctx->cleanup_lock);
e3c68b
+    }
e3c68b
 
e3c68b
     return;
e3c68b
 }
e3c68b
diff --git a/tests/bugs/glusterd/optimized-basic-testcases.t b/tests/bugs/glusterd/optimized-basic-testcases.t
e3c68b
index d700b5e..110f1b9 100644
e3c68b
--- a/tests/bugs/glusterd/optimized-basic-testcases.t
e3c68b
+++ b/tests/bugs/glusterd/optimized-basic-testcases.t
e3c68b
@@ -289,7 +289,9 @@ mkdir -p /xyz/var/lib/glusterd/abc
e3c68b
 TEST  $CLI volume create "test" $H0:/xyz/var/lib/glusterd/abc
e3c68b
 EXPECT 'Created' volinfo_field "test" 'Status';
e3c68b
 
e3c68b
-EXPECT "1" generate_statedump_and_check_for_glusterd_info
e3c68b
+#While taking a statedump, there is a TRY_LOCK on call_frame, which might may cause
e3c68b
+#failure. So Adding a EXPECT_WITHIN
e3c68b
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "^1$" generate_statedump_and_check_for_glusterd_info
e3c68b
 
e3c68b
 cleanup_statedump `pidof glusterd`
e3c68b
 cleanup
e3c68b
-- 
e3c68b
1.8.3.1
e3c68b