12a457
From 6b5789a9c9fba12b9ec06cbdde3c6dbfb3c1aaae Mon Sep 17 00:00:00 2001
12a457
From: Poornima G <pgurusid@redhat.com>
12a457
Date: Sat, 19 Mar 2016 04:38:47 -0400
12a457
Subject: [PATCH 62/64] gfapi: Fix the crashes caused by global_xlator and THIS
12a457
12a457
Issue: http://thread.gmane.org/gmane.comp.file-systems.gluster.devel/10922
12a457
12a457
The right fix for this is elaborate and intrusive, until it is in place,
12a457
this patch provides a temperory fix. This fix is necessary, as without this
12a457
libgfapi applications like qemu, samba, NFS ganesha are prone to crashes.
12a457
This patch will be reverted completely, once the actual fix gets accepted.
12a457
12a457
Credits: Rajesh Joseph, Raghavendra Talur, Anoop CS
12a457
12a457
Reviewed on: http://review.gluster.org/#/c/13784/
12a457
BUG: 1317940
12a457
Change-Id: I5931ca4731558c60909ace05c7a2756273926886
12a457
Signed-off-by: Poornima G <pgurusid@redhat.com>
12a457
Reviewed-on: https://code.engineering.redhat.com/gerrit/70407
12a457
Reviewed-by: Raghavendra Talur <rtalur@redhat.com>
12a457
Reviewed-by: Anoop Chirayath Manjiyil Sajan <anoopcs@redhat.com>
12a457
Reviewed-by: Rajesh Joseph <rjoseph@redhat.com>
12a457
Tested-by: Rajesh Joseph <rjoseph@redhat.com>
12a457
---
12a457
 api/src/glfs.c                                |   60 ++++++++++--
12a457
 libglusterfs/src/globals.c                    |    7 +-
12a457
 libglusterfs/src/logging.c                    |    4 +-
12a457
 libglusterfs/src/logging.h                    |    2 +-
12a457
 libglusterfs/src/unittest/log_mock.c          |    2 +-
12a457
 tests/bugs/libgfapi/bug-1319374-THIS-crash.sh |   27 +++++
12a457
 tests/bugs/libgfapi/bug-1319374.c             |  128 +++++++++++++++++++++++++
12a457
 7 files changed, 218 insertions(+), 12 deletions(-)
12a457
 create mode 100755 tests/bugs/libgfapi/bug-1319374-THIS-crash.sh
12a457
 create mode 100644 tests/bugs/libgfapi/bug-1319374.c
12a457
12a457
diff --git a/api/src/glfs.c b/api/src/glfs.c
12a457
index 8e2d2c3..1fc1a30 100644
12a457
--- a/api/src/glfs.c
12a457
+++ b/api/src/glfs.c
12a457
@@ -626,6 +626,49 @@ err:
12a457
         return NULL;
12a457
 }
12a457
 
12a457
+extern xlator_t global_xlator;
12a457
+extern glusterfs_ctx_t *global_ctx;
12a457
+extern pthread_mutex_t global_ctx_mutex;
12a457
+
12a457
+static int
12a457
+glfs_init_global_ctx ()
12a457
+{
12a457
+        int              ret = 0;
12a457
+        glusterfs_ctx_t *ctx = NULL;
12a457
+
12a457
+        pthread_mutex_lock (&global_ctx_mutex);
12a457
+        {
12a457
+                if (global_xlator.ctx)
12a457
+                        goto unlock;
12a457
+
12a457
+                ctx = glusterfs_ctx_new ();
12a457
+                if (!ctx) {
12a457
+                        ret = -1;
12a457
+                        goto unlock;
12a457
+                }
12a457
+
12a457
+                gf_log_globals_init (ctx, GF_LOG_NONE);
12a457
+
12a457
+                global_ctx = ctx;
12a457
+                global_xlator.ctx = global_ctx;
12a457
+
12a457
+                ret = glusterfs_ctx_defaults_init (ctx);
12a457
+                if (ret) {
12a457
+                        global_ctx = NULL;
12a457
+                        global_xlator.ctx = NULL;
12a457
+                        goto unlock;
12a457
+                }
12a457
+        }
12a457
+unlock:
12a457
+        pthread_mutex_unlock (&global_ctx_mutex);
12a457
+
12a457
+        if (ret)
12a457
+                FREE (ctx);
12a457
+
12a457
+        return ret;
12a457
+}
12a457
+
12a457
+
12a457
 struct glfs *
12a457
 pub_glfs_new (const char *volname)
12a457
 {
12a457
@@ -654,11 +697,9 @@ pub_glfs_new (const char *volname)
12a457
                 goto fini;
12a457
 
12a457
         old_THIS = THIS;
12a457
-        /* THIS is set to NULL so that we do not modify the caller xlators'
12a457
-         * ctx, instead we set the global_xlator->ctx
12a457
-         */
12a457
-        THIS = NULL;
12a457
-        THIS->ctx = ctx;
12a457
+        ret = glfs_init_global_ctx ();
12a457
+        if (ret)
12a457
+                goto fini;
12a457
 
12a457
         /* then ctx_defaults_init, for xlator_mem_acct_init(THIS) */
12a457
 
12a457
@@ -770,12 +811,16 @@ GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_volfile, 3.4.0);
12a457
 int
12a457
 pub_glfs_set_logging (struct glfs *fs, const char *logfile, int loglevel)
12a457
 {
12a457
-        int  ret = -1;
12a457
-        char *tmplog = NULL;
12a457
+        int              ret     = -1;
12a457
+        char            *tmplog  = NULL;
12a457
+        glusterfs_ctx_t *old_ctx = NULL;
12a457
 
12a457
         DECLARE_OLD_THIS;
12a457
         __GLFS_ENTRY_VALIDATE_FS (fs, invalid_fs);
12a457
 
12a457
+        old_ctx = THIS->ctx;
12a457
+        THIS->ctx = fs->ctx;
12a457
+
12a457
         if (!logfile) {
12a457
                 ret = gf_set_log_file_path (&fs->ctx->cmd_args);
12a457
                 if (ret)
12a457
@@ -798,6 +843,7 @@ pub_glfs_set_logging (struct glfs *fs, const char *logfile, int loglevel)
12a457
                 goto out;
12a457
 
12a457
 out:
12a457
+        THIS->ctx = old_ctx;
12a457
         __GLFS_EXIT_FS;
12a457
 
12a457
 invalid_fs:
12a457
diff --git a/libglusterfs/src/globals.c b/libglusterfs/src/globals.c
12a457
index 8943637..1b25e43 100644
12a457
--- a/libglusterfs/src/globals.c
12a457
+++ b/libglusterfs/src/globals.c
12a457
@@ -76,6 +76,11 @@ const char *gf_fop_list[GF_FOP_MAXVALUE] = {
12a457
 };
12a457
 /* THIS */
12a457
 
12a457
+/* This global ctx is a bad hack to prevent some of the libgfapi crashes.
12a457
+ * This should be removed once the patch on resource pool is accepted
12a457
+ */
12a457
+glusterfs_ctx_t *global_ctx = NULL;
12a457
+pthread_mutex_t global_ctx_mutex = PTHREAD_MUTEX_INITIALIZER;
12a457
 xlator_t global_xlator;
12a457
 static pthread_key_t this_xlator_key;
12a457
 static pthread_key_t synctask_key;
12a457
@@ -387,7 +392,7 @@ glusterfs_globals_init (glusterfs_ctx_t *ctx)
12a457
 {
12a457
         int ret = 0;
12a457
 
12a457
-        gf_log_globals_init (ctx);
12a457
+        gf_log_globals_init (ctx, GF_LOG_INFO);
12a457
 
12a457
         ret =  pthread_once (&globals_inited, gf_globals_init_once);
12a457
 
12a457
diff --git a/libglusterfs/src/logging.c b/libglusterfs/src/logging.c
12a457
index 04b44b8..2d0a4ea 100644
12a457
--- a/libglusterfs/src/logging.c
12a457
+++ b/libglusterfs/src/logging.c
12a457
@@ -645,13 +645,13 @@ gf_syslog (int facility_priority, char *format, ...)
12a457
 }
12a457
 
12a457
 void
12a457
-gf_log_globals_init (void *data)
12a457
+gf_log_globals_init (void *data, gf_loglevel_t level)
12a457
 {
12a457
         glusterfs_ctx_t *ctx = data;
12a457
 
12a457
         pthread_mutex_init (&ctx->log.logfile_mutex, NULL);
12a457
 
12a457
-        ctx->log.loglevel         = GF_LOG_INFO;
12a457
+        ctx->log.loglevel         = level;
12a457
         ctx->log.gf_log_syslog    = 1;
12a457
         ctx->log.sys_log_level    = GF_LOG_CRITICAL;
12a457
         ctx->log.logger           = gf_logger_glusterlog;
12a457
diff --git a/libglusterfs/src/logging.h b/libglusterfs/src/logging.h
12a457
index 4ad52d8..a08e8c7 100644
12a457
--- a/libglusterfs/src/logging.h
12a457
+++ b/libglusterfs/src/logging.h
12a457
@@ -139,7 +139,7 @@ typedef struct log_buf_ {
12a457
         struct list_head msg_list;
12a457
 } log_buf_t;
12a457
 
12a457
-void gf_log_globals_init (void *ctx);
12a457
+void gf_log_globals_init (void *ctx, gf_loglevel_t level);
12a457
 int gf_log_init (void *data, const char *filename, const char *ident);
12a457
 
12a457
 void gf_log_logrotate (int signum);
12a457
diff --git a/tests/bugs/libgfapi/bug-1319374-THIS-crash.sh b/tests/bugs/libgfapi/bug-1319374-THIS-crash.sh
12a457
new file mode 100755
12a457
index 0000000..9aea739
12a457
--- /dev/null
12a457
+++ b/tests/bugs/libgfapi/bug-1319374-THIS-crash.sh
12a457
@@ -0,0 +1,27 @@
12a457
+#!/bin/bash
12a457
+
12a457
+. $(dirname $0)/../../include.rc
12a457
+. $(dirname $0)/../../volume.rc
12a457
+
12a457
+cleanup;
12a457
+
12a457
+TEST glusterd
12a457
+TEST pidof glusterd
12a457
+TEST $CLI volume info;
12a457
+
12a457
+TEST $CLI volume create $V0 $H0:$B0/brick1 $H0:$B0/brick2;
12a457
+EXPECT 'Created' volinfo_field $V0 'Status';
12a457
+
12a457
+TEST $CLI volume start $V0;
12a457
+EXPECT 'Started' volinfo_field $V0 'Status';
12a457
+
12a457
+TEST $CLI volume set $V0 diagnostics.client-log-flush-timeout 30
12a457
+
12a457
+logdir=`gluster --print-logdir`
12a457
+
12a457
+build_tester $(dirname $0)/bug-1319374.c -lgfapi
12a457
+TEST $(dirname $0)/bug-1319374 $V0 $logdir/bug-1319374.log
12a457
+
12a457
+cleanup_tester $(dirname $0)/bug-1319374
12a457
+
12a457
+cleanup;
12a457
diff --git a/tests/bugs/libgfapi/bug-1319374.c b/tests/bugs/libgfapi/bug-1319374.c
12a457
new file mode 100644
12a457
index 0000000..878d897
12a457
--- /dev/null
12a457
+++ b/tests/bugs/libgfapi/bug-1319374.c
12a457
@@ -0,0 +1,128 @@
12a457
+#include <glusterfs/api/glfs.h>
12a457
+#include <glusterfs/api/glfs-handles.h>
12a457
+#include <errno.h>
12a457
+#include <stdio.h>
12a457
+#include <stdlib.h>
12a457
+
12a457
+#define NO_INIT 1
12a457
+
12a457
+glfs_t *
12a457
+setup_new_client(char *volname, char *log_file, int flag)
12a457
+{
12a457
+        int ret = 0;
12a457
+        glfs_t *fs = NULL;
12a457
+
12a457
+        fs = glfs_new (volname);
12a457
+        if (!fs) {
12a457
+                fprintf (stderr, "\nglfs_new: returned NULL (%s)\n",
12a457
+                                 strerror (errno));
12a457
+                goto error;
12a457
+        }
12a457
+
12a457
+        ret = glfs_set_volfile_server (fs, "tcp", "localhost", 24007);
12a457
+        if (ret < 0) {
12a457
+                fprintf (stderr, "\nglfs_set_volfile_server failed ret:%d (%s)\n",
12a457
+                                 ret, strerror (errno));
12a457
+                goto error;
12a457
+        }
12a457
+
12a457
+        ret = glfs_set_logging (fs, log_file, 7);
12a457
+        if (ret < 0) {
12a457
+                fprintf (stderr, "\nglfs_set_logging failed with ret: %d (%s)\n",
12a457
+                                 ret, strerror (errno));
12a457
+                goto error;
12a457
+        }
12a457
+
12a457
+        if (flag == NO_INIT)
12a457
+                goto out;
12a457
+
12a457
+        ret = glfs_init (fs);
12a457
+        if (ret < 0) {
12a457
+                fprintf (stderr, "\nglfs_init failed with ret: %d (%s)\n",
12a457
+                                  ret, strerror (errno));
12a457
+                goto error;
12a457
+        }
12a457
+
12a457
+out:
12a457
+        return fs;
12a457
+error:
12a457
+        return NULL;
12a457
+}
12a457
+
12a457
+int
12a457
+main (int argc, char *argv[])
12a457
+{
12a457
+        int        ret         = 0;
12a457
+        glfs_t    *fs1         = NULL;
12a457
+        glfs_t    *fs2         = NULL;
12a457
+        glfs_t    *fs3         = NULL;
12a457
+        char      *volname     = NULL;
12a457
+        char      *log_file    = NULL;
12a457
+
12a457
+        if (argc != 3) {
12a457
+                fprintf (stderr,
12a457
+                                "Expect following args %s <Vol> <log file location>\n"
12a457
+                                , argv[0]);
12a457
+                return -1;
12a457
+        }
12a457
+
12a457
+        volname = argv[1];
12a457
+        log_file = argv[2];
12a457
+
12a457
+        fs1 = setup_new_client (volname, log_file, NO_INIT);
12a457
+        if (!fs1) {
12a457
+                fprintf (stderr, "\nsetup_new_client: returned NULL (%s)\n",
12a457
+                                 strerror (errno));
12a457
+                goto error;
12a457
+        }
12a457
+
12a457
+        fs2 = setup_new_client (volname, log_file, 0);
12a457
+        if (!fs2) {
12a457
+                fprintf (stderr, "\nsetup_new_client: returned NULL (%s)\n",
12a457
+                                 strerror (errno));
12a457
+                goto error;
12a457
+        }
12a457
+
12a457
+        fs3 = setup_new_client (volname, log_file, 0);
12a457
+        if (!fs3) {
12a457
+                fprintf (stderr, "\nsetup_new_client: returned NULL (%s)\n",
12a457
+                                 strerror (errno));
12a457
+                goto error;
12a457
+        }
12a457
+
12a457
+        ret = glfs_fini (fs3);
12a457
+        if (ret < 0) {
12a457
+                fprintf (stderr, "glfs_fini failed with ret: %d (%s)\n",
12a457
+                         ret, strerror (errno));
12a457
+                goto error;
12a457
+        }
12a457
+
12a457
+        /* The crash is seen in gf_log_flush_timeout_cbk(), and this gets
12a457
+         * triggered when 30s timer expires, hence the sleep of 31s
12a457
+         */
12a457
+        sleep (31);
12a457
+        ret = glfs_fini (fs2);
12a457
+        if (ret < 0) {
12a457
+                fprintf (stderr, "glfs_fini failed with ret: %d (%s)\n",
12a457
+                         ret, strerror (errno));
12a457
+                goto error;
12a457
+        }
12a457
+
12a457
+        ret = glfs_init (fs1);
12a457
+        if (ret < 0) {
12a457
+                fprintf (stderr, "\nglfs_init failed with ret: %d (%s)\n",
12a457
+                                  ret, strerror (errno));
12a457
+                goto error;
12a457
+        }
12a457
+
12a457
+        ret = glfs_fini (fs1);
12a457
+        if (ret < 0) {
12a457
+                fprintf (stderr, "glfs_fini failed with ret: %d (%s)\n",
12a457
+                         ret, strerror (errno));
12a457
+                goto error;
12a457
+        }
12a457
+
12a457
+        return 0;
12a457
+error:
12a457
+        return -1;
12a457
+}
12a457
-- 
12a457
1.7.1
12a457