9ae3f9
From 51090a4b3cb000d601083f12d1875547819fc03f Mon Sep 17 00:00:00 2001
9ae3f9
From: Mohit Agrawal <moagrawal@redhat.com>
9ae3f9
Date: Wed, 4 Mar 2020 09:17:26 +0530
9ae3f9
Subject: [PATCH 447/449] core[brick_mux]: brick crashed when creating and
9ae3f9
 deleting volumes over time
9ae3f9
9ae3f9
Problem: In brick_mux environment, while volumes are created/stopped in a loop
9ae3f9
         after running a long time the main brick is crashed.The brick is crashed
9ae3f9
         because the main brick process was not cleaned up memory for all objects
9ae3f9
         at the time of detaching a volume.
9ae3f9
         Below are the objects that are missed at the time of detaching a volume
9ae3f9
         1) xlator object for a brick graph
9ae3f9
         2) local_pool for posix_lock xlator
9ae3f9
         3) rpc object cleanup at quota xlator
9ae3f9
         4) inode leak at brick xlator
9ae3f9
9ae3f9
Solution: To avoid the crash resolve all leak at the time of detaching a brick
9ae3f9
> Change-Id: Ibb6e46c5fba22b9441a88cbaf6b3278823235913
9ae3f9
> updates: #977
9ae3f9
> Signed-off-by: Mohit Agrawal <moagrawa@redhat.com>
9ae3f9
> (Cherry pick from commit e589d8de66d3325da8fbbbe44d1a5bd6335e08ab)
9ae3f9
> (Reviewed on upstream link https://review.gluster.org/#/c/glusterfs/+/24209/)
9ae3f9
9ae3f9
BUG: 1790336
9ae3f9
Change-Id: Ibb6e46c5fba22b9441a88cbaf6b3278823235913
9ae3f9
Signed-off-by: Mohit Agrawal <moagrawa@redhat.com>
9ae3f9
Reviewed-on: https://code.engineering.redhat.com/gerrit/202782
9ae3f9
Tested-by: RHGS Build Bot <nigelb@redhat.com>
9ae3f9
Reviewed-by: Xavi Hernandez Juan <xhernandez@redhat.com>
9ae3f9
---
9ae3f9
 libglusterfs/src/glusterfs/glusterfs.h             |  1 +
9ae3f9
 libglusterfs/src/graph.c                           |  1 +
9ae3f9
 libglusterfs/src/graph.y                           |  2 +-
9ae3f9
 libglusterfs/src/xlator.c                          | 29 ++++++++----
9ae3f9
 xlators/features/changelog/src/changelog.c         |  1 +
9ae3f9
 xlators/features/locks/src/posix.c                 |  4 ++
9ae3f9
 xlators/features/quota/src/quota-enforcer-client.c | 14 +++++-
9ae3f9
 xlators/features/quota/src/quota.c                 | 54 ++++++++++++++++++++--
9ae3f9
 xlators/features/quota/src/quota.h                 |  3 ++
9ae3f9
 xlators/protocol/server/src/server.c               | 12 +++--
9ae3f9
 10 files changed, 103 insertions(+), 18 deletions(-)
9ae3f9
9ae3f9
diff --git a/libglusterfs/src/glusterfs/glusterfs.h b/libglusterfs/src/glusterfs/glusterfs.h
9ae3f9
index 177a020..584846e 100644
9ae3f9
--- a/libglusterfs/src/glusterfs/glusterfs.h
9ae3f9
+++ b/libglusterfs/src/glusterfs/glusterfs.h
9ae3f9
@@ -603,6 +603,7 @@ struct _glusterfs_graph {
9ae3f9
     int used; /* Should be set when fuse gets
9ae3f9
                         first CHILD_UP */
9ae3f9
     uint32_t volfile_checksum;
9ae3f9
+    pthread_mutex_t mutex;
9ae3f9
 };
9ae3f9
 typedef struct _glusterfs_graph glusterfs_graph_t;
9ae3f9
 
9ae3f9
diff --git a/libglusterfs/src/graph.c b/libglusterfs/src/graph.c
9ae3f9
index bb5e67a..1cd92db 100644
9ae3f9
--- a/libglusterfs/src/graph.c
9ae3f9
+++ b/libglusterfs/src/graph.c
9ae3f9
@@ -1092,6 +1092,7 @@ glusterfs_graph_destroy_residual(glusterfs_graph_t *graph)
9ae3f9
     ret = xlator_tree_free_memacct(graph->first);
9ae3f9
 
9ae3f9
     list_del_init(&graph->list);
9ae3f9
+    pthread_mutex_destroy(&graph->mutex);
9ae3f9
     GF_FREE(graph);
9ae3f9
 
9ae3f9
     return ret;
9ae3f9
diff --git a/libglusterfs/src/graph.y b/libglusterfs/src/graph.y
9ae3f9
index 5b92985..5733515 100644
9ae3f9
--- a/libglusterfs/src/graph.y
9ae3f9
+++ b/libglusterfs/src/graph.y
9ae3f9
@@ -541,7 +541,7 @@ glusterfs_graph_new ()
9ae3f9
                 return NULL;
9ae3f9
 
9ae3f9
         INIT_LIST_HEAD (&graph->list);
9ae3f9
-
9ae3f9
+        pthread_mutex_init(&graph->mutex, NULL);
9ae3f9
         gettimeofday (&graph->dob, NULL);
9ae3f9
 
9ae3f9
         return graph;
9ae3f9
diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c
9ae3f9
index 108b96a..36cc32c 100644
9ae3f9
--- a/libglusterfs/src/xlator.c
9ae3f9
+++ b/libglusterfs/src/xlator.c
9ae3f9
@@ -938,6 +938,8 @@ xlator_mem_cleanup(xlator_t *this)
9ae3f9
     xlator_list_t **trav_p = NULL;
9ae3f9
     xlator_t *top = NULL;
9ae3f9
     xlator_t *victim = NULL;
9ae3f9
+    glusterfs_graph_t *graph = NULL;
9ae3f9
+    gf_boolean_t graph_cleanup = _gf_false;
9ae3f9
 
9ae3f9
     if (this->call_cleanup || !this->ctx)
9ae3f9
         return;
9ae3f9
@@ -945,6 +947,12 @@ xlator_mem_cleanup(xlator_t *this)
9ae3f9
     this->call_cleanup = 1;
9ae3f9
     ctx = this->ctx;
9ae3f9
 
9ae3f9
+    inode_table = this->itable;
9ae3f9
+    if (inode_table) {
9ae3f9
+        inode_table_destroy(inode_table);
9ae3f9
+        this->itable = NULL;
9ae3f9
+    }
9ae3f9
+
9ae3f9
     xlator_call_fini(trav);
9ae3f9
 
9ae3f9
     while (prev) {
9ae3f9
@@ -953,12 +961,6 @@ xlator_mem_cleanup(xlator_t *this)
9ae3f9
         prev = trav;
9ae3f9
     }
9ae3f9
 
9ae3f9
-    inode_table = this->itable;
9ae3f9
-    if (inode_table) {
9ae3f9
-        inode_table_destroy(inode_table);
9ae3f9
-        this->itable = NULL;
9ae3f9
-    }
9ae3f9
-
9ae3f9
     if (this->fini) {
9ae3f9
         this->fini(this);
9ae3f9
     }
9ae3f9
@@ -968,17 +970,28 @@ xlator_mem_cleanup(xlator_t *this)
9ae3f9
     if (ctx->active) {
9ae3f9
         top = ctx->active->first;
9ae3f9
         LOCK(&ctx->volfile_lock);
9ae3f9
-        /* TODO here we have leak for xlator node in a graph */
9ae3f9
-        /* Need to move only top xlator from a graph */
9ae3f9
         for (trav_p = &top->children; *trav_p; trav_p = &(*trav_p)->next) {
9ae3f9
             victim = (*trav_p)->xlator;
9ae3f9
             if (victim->call_cleanup && !strcmp(victim->name, this->name)) {
9ae3f9
+                graph_cleanup = _gf_true;
9ae3f9
                 (*trav_p) = (*trav_p)->next;
9ae3f9
                 break;
9ae3f9
             }
9ae3f9
         }
9ae3f9
         UNLOCK(&ctx->volfile_lock);
9ae3f9
     }
9ae3f9
+
9ae3f9
+    if (graph_cleanup) {
9ae3f9
+        prev = this;
9ae3f9
+        graph = ctx->active;
9ae3f9
+        pthread_mutex_lock(&graph->mutex);
9ae3f9
+        while (prev) {
9ae3f9
+            trav = prev->next;
9ae3f9
+            GF_FREE(prev);
9ae3f9
+            prev = trav;
9ae3f9
+        }
9ae3f9
+        pthread_mutex_unlock(&graph->mutex);
9ae3f9
+    }
9ae3f9
 }
9ae3f9
 
9ae3f9
 void
9ae3f9
diff --git a/xlators/features/changelog/src/changelog.c b/xlators/features/changelog/src/changelog.c
9ae3f9
index ff06c09..b54112c 100644
9ae3f9
--- a/xlators/features/changelog/src/changelog.c
9ae3f9
+++ b/xlators/features/changelog/src/changelog.c
9ae3f9
@@ -2872,6 +2872,7 @@ fini(xlator_t *this)
9ae3f9
         if (priv->active || priv->rpc_active) {
9ae3f9
             /* terminate RPC server/threads */
9ae3f9
             changelog_cleanup_rpc(this, priv);
9ae3f9
+            GF_FREE(priv->ev_dispatcher);
9ae3f9
         }
9ae3f9
         /* call barrier_disable to cancel timer */
9ae3f9
         if (priv->barrier_enabled)
9ae3f9
diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c
9ae3f9
index 9a14c64..50f1265 100644
9ae3f9
--- a/xlators/features/locks/src/posix.c
9ae3f9
+++ b/xlators/features/locks/src/posix.c
9ae3f9
@@ -4102,6 +4102,10 @@ fini(xlator_t *this)
9ae3f9
     if (!priv)
9ae3f9
         return;
9ae3f9
     this->private = NULL;
9ae3f9
+    if (this->local_pool) {
9ae3f9
+        mem_pool_destroy(this->local_pool);
9ae3f9
+        this->local_pool = NULL;
9ae3f9
+    }
9ae3f9
     GF_FREE(priv->brickname);
9ae3f9
     GF_FREE(priv);
9ae3f9
 
9ae3f9
diff --git a/xlators/features/quota/src/quota-enforcer-client.c b/xlators/features/quota/src/quota-enforcer-client.c
9ae3f9
index 1a4c2e3..097439d 100644
9ae3f9
--- a/xlators/features/quota/src/quota-enforcer-client.c
9ae3f9
+++ b/xlators/features/quota/src/quota-enforcer-client.c
9ae3f9
@@ -362,16 +362,28 @@ quota_enforcer_notify(struct rpc_clnt *rpc, void *mydata,
9ae3f9
 {
9ae3f9
     xlator_t *this = NULL;
9ae3f9
     int ret = 0;
9ae3f9
+    quota_priv_t *priv = NULL;
9ae3f9
 
9ae3f9
     this = mydata;
9ae3f9
-
9ae3f9
+    priv = this->private;
9ae3f9
     switch (event) {
9ae3f9
         case RPC_CLNT_CONNECT: {
9ae3f9
+            pthread_mutex_lock(&priv->conn_mutex);
9ae3f9
+            {
9ae3f9
+                priv->conn_status = _gf_true;
9ae3f9
+            }
9ae3f9
+            pthread_mutex_unlock(&priv->conn_mutex);
9ae3f9
             gf_msg_trace(this->name, 0, "got RPC_CLNT_CONNECT");
9ae3f9
             break;
9ae3f9
         }
9ae3f9
 
9ae3f9
         case RPC_CLNT_DISCONNECT: {
9ae3f9
+            pthread_mutex_lock(&priv->conn_mutex);
9ae3f9
+            {
9ae3f9
+                priv->conn_status = _gf_false;
9ae3f9
+                pthread_cond_signal(&priv->conn_cond);
9ae3f9
+            }
9ae3f9
+            pthread_mutex_unlock(&priv->conn_mutex);
9ae3f9
             gf_msg_trace(this->name, 0, "got RPC_CLNT_DISCONNECT");
9ae3f9
             break;
9ae3f9
         }
9ae3f9
diff --git a/xlators/features/quota/src/quota.c b/xlators/features/quota/src/quota.c
9ae3f9
index a0c236d..d1123ce 100644
9ae3f9
--- a/xlators/features/quota/src/quota.c
9ae3f9
+++ b/xlators/features/quota/src/quota.c
9ae3f9
@@ -5014,6 +5014,43 @@ quota_forget(xlator_t *this, inode_t *inode)
9ae3f9
     return 0;
9ae3f9
 }
9ae3f9
 
9ae3f9
+int
9ae3f9
+notify(xlator_t *this, int event, void *data, ...)
9ae3f9
+{
9ae3f9
+    quota_priv_t *priv = NULL;
9ae3f9
+    int ret = 0;
9ae3f9
+    rpc_clnt_t *rpc = NULL;
9ae3f9
+    gf_boolean_t conn_status = _gf_true;
9ae3f9
+    xlator_t *victim = data;
9ae3f9
+
9ae3f9
+    priv = this->private;
9ae3f9
+    if (!priv || !priv->is_quota_on)
9ae3f9
+        goto out;
9ae3f9
+
9ae3f9
+    if (event == GF_EVENT_PARENT_DOWN) {
9ae3f9
+        rpc = priv->rpc_clnt;
9ae3f9
+        if (rpc) {
9ae3f9
+            rpc_clnt_disable(rpc);
9ae3f9
+            pthread_mutex_lock(&priv->conn_mutex);
9ae3f9
+            {
9ae3f9
+                conn_status = priv->conn_status;
9ae3f9
+                while (conn_status) {
9ae3f9
+                    (void)pthread_cond_wait(&priv->conn_cond,
9ae3f9
+                                            &priv->conn_mutex);
9ae3f9
+                    conn_status = priv->conn_status;
9ae3f9
+                }
9ae3f9
+            }
9ae3f9
+            pthread_mutex_unlock(&priv->conn_mutex);
9ae3f9
+            gf_log(this->name, GF_LOG_INFO,
9ae3f9
+                   "Notify GF_EVENT_PARENT_DOWN for brick %s", victim->name);
9ae3f9
+        }
9ae3f9
+    }
9ae3f9
+
9ae3f9
+out:
9ae3f9
+    ret = default_notify(this, event, data);
9ae3f9
+    return ret;
9ae3f9
+}
9ae3f9
+
9ae3f9
 int32_t
9ae3f9
 init(xlator_t *this)
9ae3f9
 {
9ae3f9
@@ -5056,6 +5093,10 @@ init(xlator_t *this)
9ae3f9
         goto err;
9ae3f9
     }
9ae3f9
 
9ae3f9
+    pthread_mutex_init(&priv->conn_mutex, NULL);
9ae3f9
+    pthread_cond_init(&priv->conn_cond, NULL);
9ae3f9
+    priv->conn_status = _gf_false;
9ae3f9
+
9ae3f9
     if (priv->is_quota_on) {
9ae3f9
         rpc = quota_enforcer_init(this, this->options);
9ae3f9
         if (rpc == NULL) {
9ae3f9
@@ -5169,20 +5210,22 @@ fini(xlator_t *this)
9ae3f9
 {
9ae3f9
     quota_priv_t *priv = NULL;
9ae3f9
     rpc_clnt_t *rpc = NULL;
9ae3f9
-    int i = 0, cnt = 0;
9ae3f9
 
9ae3f9
     priv = this->private;
9ae3f9
     if (!priv)
9ae3f9
         return;
9ae3f9
     rpc = priv->rpc_clnt;
9ae3f9
     priv->rpc_clnt = NULL;
9ae3f9
-    this->private = NULL;
9ae3f9
     if (rpc) {
9ae3f9
-        cnt = GF_ATOMIC_GET(rpc->refcount);
9ae3f9
-        for (i = 0; i < cnt; i++)
9ae3f9
-            rpc_clnt_unref(rpc);
9ae3f9
+        rpc_clnt_connection_cleanup(&rpc->conn);
9ae3f9
+        rpc_clnt_unref(rpc);
9ae3f9
     }
9ae3f9
+
9ae3f9
+    this->private = NULL;
9ae3f9
     LOCK_DESTROY(&priv->lock);
9ae3f9
+    pthread_mutex_destroy(&priv->conn_mutex);
9ae3f9
+    pthread_cond_destroy(&priv->conn_cond);
9ae3f9
+
9ae3f9
     GF_FREE(priv);
9ae3f9
     if (this->local_pool) {
9ae3f9
         mem_pool_destroy(this->local_pool);
9ae3f9
@@ -5314,6 +5357,7 @@ struct volume_options options[] = {
9ae3f9
 xlator_api_t xlator_api = {
9ae3f9
     .init = init,
9ae3f9
     .fini = fini,
9ae3f9
+    .notify = notify,
9ae3f9
     .reconfigure = reconfigure,
9ae3f9
     .mem_acct_init = mem_acct_init,
9ae3f9
     .op_version = {1}, /* Present from the initial version */
9ae3f9
diff --git a/xlators/features/quota/src/quota.h b/xlators/features/quota/src/quota.h
9ae3f9
index a5a99ca..e51ffd4 100644
9ae3f9
--- a/xlators/features/quota/src/quota.h
9ae3f9
+++ b/xlators/features/quota/src/quota.h
9ae3f9
@@ -217,6 +217,9 @@ struct quota_priv {
9ae3f9
     char *volume_uuid;
9ae3f9
     uint64_t validation_count;
9ae3f9
     int32_t quotad_conn_status;
9ae3f9
+    pthread_mutex_t conn_mutex;
9ae3f9
+    pthread_cond_t conn_cond;
9ae3f9
+    gf_boolean_t conn_status;
9ae3f9
 };
9ae3f9
 typedef struct quota_priv quota_priv_t;
9ae3f9
 
9ae3f9
diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c
9ae3f9
index a5f09fe..54d9c0f 100644
9ae3f9
--- a/xlators/protocol/server/src/server.c
9ae3f9
+++ b/xlators/protocol/server/src/server.c
9ae3f9
@@ -409,7 +409,13 @@ server_call_xlator_mem_cleanup(xlator_t *this, char *victim_name)
9ae3f9
 
9ae3f9
     arg = calloc(1, sizeof(*arg));
9ae3f9
     arg->this = this;
9ae3f9
-    arg->victim_name = gf_strdup(victim_name);
9ae3f9
+    arg->victim_name = strdup(victim_name);
9ae3f9
+    if (!arg->victim_name) {
9ae3f9
+        gf_smsg(this->name, GF_LOG_CRITICAL, ENOMEM, LG_MSG_NO_MEMORY,
9ae3f9
+                "Memory allocation is failed");
9ae3f9
+        return;
9ae3f9
+    }
9ae3f9
+
9ae3f9
     th_ret = gf_thread_create_detached(&th_id, server_graph_janitor_threads,
9ae3f9
                                        arg, "graphjanitor");
9ae3f9
     if (th_ret) {
9ae3f9
@@ -417,7 +423,7 @@ server_call_xlator_mem_cleanup(xlator_t *this, char *victim_name)
9ae3f9
                "graph janitor Thread"
9ae3f9
                " creation is failed for brick %s",
9ae3f9
                victim_name);
9ae3f9
-        GF_FREE(arg->victim_name);
9ae3f9
+        free(arg->victim_name);
9ae3f9
         free(arg);
9ae3f9
     }
9ae3f9
 }
9ae3f9
@@ -628,7 +634,7 @@ server_graph_janitor_threads(void *data)
9ae3f9
     }
9ae3f9
 
9ae3f9
 out:
9ae3f9
-    GF_FREE(arg->victim_name);
9ae3f9
+    free(arg->victim_name);
9ae3f9
     free(arg);
9ae3f9
     return NULL;
9ae3f9
 }
9ae3f9
-- 
9ae3f9
1.8.3.1
9ae3f9