e3c68b
From 4d95e271a9042bf2d789a4d900ad263b6ea47681 Mon Sep 17 00:00:00 2001
e3c68b
From: Mohammed Rafi KC <rkavunga@redhat.com>
e3c68b
Date: Wed, 23 Jan 2019 21:55:01 +0530
e3c68b
Subject: [PATCH 100/124] clnt/rpc: ref leak during disconnect.
e3c68b
e3c68b
During disconnect cleanup, we are not cancelling reconnect
e3c68b
timer, which causes a ref leak each time when a disconnect
e3c68b
happen.
e3c68b
e3c68b
Backport of: https://review.gluster.org/#/c/glusterfs/+/22087/
e3c68b
e3c68b
>Change-Id: I9d05d1f368d080e04836bf6a0bb018bf8f7b5b8a
e3c68b
>updates: bz#1659708
e3c68b
>Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
e3c68b
e3c68b
Change-Id: I5a2dbb17e663a4809bb4c435cacadbf0ab694a76
e3c68b
BUG: 1471742
e3c68b
Signed-off-by: Mohammed Rafi KC <rkavunga@redhat.com>
e3c68b
Reviewed-on: https://code.engineering.redhat.com/gerrit/167844
e3c68b
Tested-by: RHGS Build Bot <nigelb@redhat.com>
e3c68b
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
e3c68b
---
e3c68b
 libglusterfs/src/timer.c                           | 16 +++++++----
e3c68b
 rpc/rpc-lib/src/rpc-clnt.c                         | 11 +++++++-
e3c68b
 .../mgmt/glusterd/src/glusterd-snapshot-utils.c    | 32 ++++++++++++++++++----
e3c68b
 3 files changed, 47 insertions(+), 12 deletions(-)
e3c68b
e3c68b
diff --git a/libglusterfs/src/timer.c b/libglusterfs/src/timer.c
e3c68b
index d882543..2643c07 100644
e3c68b
--- a/libglusterfs/src/timer.c
e3c68b
+++ b/libglusterfs/src/timer.c
e3c68b
@@ -75,13 +75,13 @@ gf_timer_call_cancel(glusterfs_ctx_t *ctx, gf_timer_t *event)
e3c68b
     if (ctx == NULL || event == NULL) {
e3c68b
         gf_msg_callingfn("timer", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,
e3c68b
                          "invalid argument");
e3c68b
-        return 0;
e3c68b
+        return -1;
e3c68b
     }
e3c68b
 
e3c68b
     if (ctx->cleanup_started) {
e3c68b
         gf_msg_callingfn("timer", GF_LOG_INFO, 0, LG_MSG_CTX_CLEANUP_STARTED,
e3c68b
                          "ctx cleanup started");
e3c68b
-        return 0;
e3c68b
+        return -1;
e3c68b
     }
e3c68b
 
e3c68b
     LOCK(&ctx->lock);
e3c68b
@@ -93,10 +93,9 @@ gf_timer_call_cancel(glusterfs_ctx_t *ctx, gf_timer_t *event)
e3c68b
     if (!reg) {
e3c68b
         /* This can happen when cleanup may have just started and
e3c68b
          * gf_timer_registry_destroy() sets ctx->timer to NULL.
e3c68b
-         * Just bail out as success as gf_timer_proc() takes
e3c68b
-         * care of cleaning up the events.
e3c68b
+         * gf_timer_proc() takes care of cleaning up the events.
e3c68b
          */
e3c68b
-        return 0;
e3c68b
+        return -1;
e3c68b
     }
e3c68b
 
e3c68b
     LOCK(&reg->lock);
e3c68b
@@ -203,6 +202,13 @@ gf_timer_proc(void *data)
e3c68b
         list_for_each_entry_safe(event, tmp, &reg->active, list)
e3c68b
         {
e3c68b
             list_del(&event->list);
e3c68b
+            /* TODO Possible resource leak
e3c68b
+             * Before freeing the event, we need to call the respective
e3c68b
+             * event functions and free any resources.
e3c68b
+             * For example, In case of rpc_clnt_reconnect, we need to
e3c68b
+             * unref rpc object which was taken when added to timer
e3c68b
+             * wheel.
e3c68b
+             */
e3c68b
             GF_FREE(event);
e3c68b
         }
e3c68b
     }
e3c68b
diff --git a/rpc/rpc-lib/src/rpc-clnt.c b/rpc/rpc-lib/src/rpc-clnt.c
e3c68b
index 3f7bb3c..6f47515 100644
e3c68b
--- a/rpc/rpc-lib/src/rpc-clnt.c
e3c68b
+++ b/rpc/rpc-lib/src/rpc-clnt.c
e3c68b
@@ -495,6 +495,7 @@ rpc_clnt_connection_cleanup(rpc_clnt_connection_t *conn)
e3c68b
     int unref = 0;
e3c68b
     int ret = 0;
e3c68b
     gf_boolean_t timer_unref = _gf_false;
e3c68b
+    gf_boolean_t reconnect_unref = _gf_false;
e3c68b
 
e3c68b
     if (!conn) {
e3c68b
         goto out;
e3c68b
@@ -514,6 +515,12 @@ rpc_clnt_connection_cleanup(rpc_clnt_connection_t *conn)
e3c68b
                 timer_unref = _gf_true;
e3c68b
             conn->timer = NULL;
e3c68b
         }
e3c68b
+        if (conn->reconnect) {
e3c68b
+            ret = gf_timer_call_cancel(clnt->ctx, conn->reconnect);
e3c68b
+            if (!ret)
e3c68b
+                reconnect_unref = _gf_true;
e3c68b
+            conn->reconnect = NULL;
e3c68b
+        }
e3c68b
 
e3c68b
         conn->connected = 0;
e3c68b
         conn->disconnected = 1;
e3c68b
@@ -533,6 +540,8 @@ rpc_clnt_connection_cleanup(rpc_clnt_connection_t *conn)
e3c68b
     if (timer_unref)
e3c68b
         rpc_clnt_unref(clnt);
e3c68b
 
e3c68b
+    if (reconnect_unref)
e3c68b
+        rpc_clnt_unref(clnt);
e3c68b
 out:
e3c68b
     return 0;
e3c68b
 }
e3c68b
@@ -830,7 +839,7 @@ rpc_clnt_handle_disconnect(struct rpc_clnt *clnt, rpc_clnt_connection_t *conn)
e3c68b
     pthread_mutex_lock(&conn->lock);
e3c68b
     {
e3c68b
         if (!conn->rpc_clnt->disabled && (conn->reconnect == NULL)) {
e3c68b
-            ts.tv_sec = 10;
e3c68b
+            ts.tv_sec = 3;
e3c68b
             ts.tv_nsec = 0;
e3c68b
 
e3c68b
             rpc_clnt_ref(clnt);
e3c68b
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
e3c68b
index 041946d..b3c4158 100644
e3c68b
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
e3c68b
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
e3c68b
@@ -3364,6 +3364,25 @@ out:
e3c68b
     return ret;
e3c68b
 }
e3c68b
 
e3c68b
+int
e3c68b
+glusterd_is_path_mounted(const char *path)
e3c68b
+{
e3c68b
+    FILE *mtab = NULL;
e3c68b
+    struct mntent *part = NULL;
e3c68b
+    int is_mounted = 0;
e3c68b
+
e3c68b
+    if ((mtab = setmntent("/etc/mtab", "r")) != NULL) {
e3c68b
+        while ((part = getmntent(mtab)) != NULL) {
e3c68b
+            if ((part->mnt_fsname != NULL) &&
e3c68b
+                (strcmp(part->mnt_dir, path)) == 0) {
e3c68b
+                is_mounted = 1;
e3c68b
+                break;
e3c68b
+            }
e3c68b
+        }
e3c68b
+        endmntent(mtab);
e3c68b
+    }
e3c68b
+    return is_mounted;
e3c68b
+}
e3c68b
 /* This function will do unmount for snaps.
e3c68b
  */
e3c68b
 int32_t
e3c68b
@@ -3388,14 +3407,11 @@ glusterd_snap_unmount(xlator_t *this, glusterd_volinfo_t *volinfo)
e3c68b
             continue;
e3c68b
         }
e3c68b
 
e3c68b
-        /* Fetch the brick mount path from the brickinfo->path */
e3c68b
-        ret = glusterd_get_brick_root(brickinfo->path, &brick_mount_path);
e3c68b
+        ret = glusterd_find_brick_mount_path(brickinfo->path,
e3c68b
+                                             &brick_mount_path);
e3c68b
         if (ret) {
e3c68b
-            gf_msg(this->name, GF_LOG_INFO, 0, GD_MSG_BRICK_PATH_UNMOUNTED,
e3c68b
+            gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRK_MNTPATH_GET_FAIL,
e3c68b
                    "Failed to find brick_mount_path for %s", brickinfo->path);
e3c68b
-            /* There is chance that brick path is already
e3c68b
-             * unmounted. */
e3c68b
-            ret = 0;
e3c68b
             goto out;
e3c68b
         }
e3c68b
         /* unmount cannot be done when the brick process is still in
e3c68b
@@ -3440,6 +3456,10 @@ glusterd_umount(const char *path)
e3c68b
     GF_ASSERT(this);
e3c68b
     GF_ASSERT(path);
e3c68b
 
e3c68b
+    if (!glusterd_is_path_mounted(path)) {
e3c68b
+        return 0;
e3c68b
+    }
e3c68b
+
e3c68b
     runinit(&runner);
e3c68b
     snprintf(msg, sizeof(msg), "umount path %s", path);
e3c68b
     runner_add_args(&runner, _PATH_UMOUNT, "-f", path, NULL);
e3c68b
-- 
e3c68b
1.8.3.1
e3c68b