74b1de
From 2f5969a77493814e242e6bac3c6bf7acf3202e0f Mon Sep 17 00:00:00 2001
74b1de
From: Xavi Hernandez <xhernandez@redhat.com>
74b1de
Date: Tue, 5 Mar 2019 18:58:20 +0100
74b1de
Subject: [PATCH 209/221] core: avoid dynamic TLS allocation when possible
74b1de
74b1de
Some interdependencies between logging and memory management functions
74b1de
make it impossible to use the logging framework before initializing
74b1de
memory subsystem because they both depend on Thread Local Storage
74b1de
allocated through pthread_key_create() during initialization.
74b1de
74b1de
This causes a crash when we try to log something very early in the
74b1de
initialization phase.
74b1de
74b1de
To prevent this, several dynamically allocated TLS structures have
74b1de
been replaced by static TLS reserved at compile time using '__thread'
74b1de
keyword. This also reduces the number of error sources, making
74b1de
initialization simpler.
74b1de
74b1de
Upstream patch:
74b1de
> BUG: 1193929
74b1de
> Upstream patch link: https://review.gluster.org/c/glusterfs/+/22302
74b1de
> Change-Id: I8ea2e072411e30790d50084b6b7e909c7bb01d50
74b1de
> Signed-off-by: Xavi Hernandez <xhernandez@redhat.com>
74b1de
74b1de
Change-Id: I8ea2e072411e30790d50084b6b7e909c7bb01d50
74b1de
Updates: bz#1722801
74b1de
Signed-off-by: Xavi Hernandez <xhernandez@redhat.com>
74b1de
Reviewed-on: https://code.engineering.redhat.com/gerrit/174711
74b1de
Tested-by: RHGS Build Bot <nigelb@redhat.com>
74b1de
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
74b1de
---
74b1de
 api/src/glfs.c                                     |   3 +-
74b1de
 cli/src/cli.c                                      |   3 +-
74b1de
 glusterfsd/src/glusterfsd.c                        |   4 +-
74b1de
 libglusterfs/src/globals.c                         | 289 ++++-----------------
74b1de
 libglusterfs/src/glusterfs/globals.h               |   6 +-
74b1de
 libglusterfs/src/glusterfs/mem-pool.h              |   7 +-
74b1de
 libglusterfs/src/libglusterfs.sym                  |   3 +-
74b1de
 libglusterfs/src/mem-pool.c                        |  98 +++----
74b1de
 libglusterfs/src/syncop.c                          | 133 ++--------
74b1de
 .../changelog/lib/src/gf-changelog-helpers.c       |  51 +---
74b1de
 xlators/features/changelog/lib/src/gf-changelog.c  |   3 +-
74b1de
 xlators/nfs/server/src/mount3udp_svc.c             |   6 +-
74b1de
 12 files changed, 114 insertions(+), 492 deletions(-)
74b1de
74b1de
diff --git a/api/src/glfs.c b/api/src/glfs.c
74b1de
index 6bbb620..f36616d 100644
74b1de
--- a/api/src/glfs.c
74b1de
+++ b/api/src/glfs.c
74b1de
@@ -829,8 +829,7 @@ pub_glfs_new(const char *volname)
74b1de
      * Do this as soon as possible in case something else depends on
74b1de
      * pool allocations.
74b1de
      */
74b1de
-    mem_pools_init_early();
74b1de
-    mem_pools_init_late();
74b1de
+    mem_pools_init();
74b1de
 
74b1de
     fs = glfs_new_fs(volname);
74b1de
     if (!fs)
74b1de
diff --git a/cli/src/cli.c b/cli/src/cli.c
74b1de
index ff39a98..99a16a0 100644
74b1de
--- a/cli/src/cli.c
74b1de
+++ b/cli/src/cli.c
74b1de
@@ -795,8 +795,7 @@ main(int argc, char *argv[])
74b1de
     int ret = -1;
74b1de
     glusterfs_ctx_t *ctx = NULL;
74b1de
 
74b1de
-    mem_pools_init_early();
74b1de
-    mem_pools_init_late();
74b1de
+    mem_pools_init();
74b1de
 
74b1de
     ctx = glusterfs_ctx_new();
74b1de
     if (!ctx)
74b1de
diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c
74b1de
index 6aee4c1..2172af4 100644
74b1de
--- a/glusterfsd/src/glusterfsd.c
74b1de
+++ b/glusterfsd/src/glusterfsd.c
74b1de
@@ -2722,8 +2722,6 @@ main(int argc, char *argv[])
74b1de
     };
74b1de
     cmd_args_t *cmd = NULL;
74b1de
 
74b1de
-    mem_pools_init_early();
74b1de
-
74b1de
     gf_check_and_set_mem_acct(argc, argv);
74b1de
 
74b1de
     ctx = glusterfs_ctx_new();
74b1de
@@ -2838,7 +2836,7 @@ main(int argc, char *argv[])
74b1de
      * the parent, but we want to do it as soon as possible after that in
74b1de
      * case something else depends on pool allocations.
74b1de
      */
74b1de
-    mem_pools_init_late();
74b1de
+    mem_pools_init();
74b1de
 
74b1de
 #ifdef GF_LINUX_HOST_OS
74b1de
     ret = set_oom_score_adj(ctx);
74b1de
diff --git a/libglusterfs/src/globals.c b/libglusterfs/src/globals.c
74b1de
index 4fec063..02098e6 100644
74b1de
--- a/libglusterfs/src/globals.c
74b1de
+++ b/libglusterfs/src/globals.c
74b1de
@@ -99,16 +99,19 @@ const char *gf_upcall_list[GF_UPCALL_FLAGS_MAXVALUE] = {
74b1de
 glusterfs_ctx_t *global_ctx = NULL;
74b1de
 pthread_mutex_t global_ctx_mutex = PTHREAD_MUTEX_INITIALIZER;
74b1de
 xlator_t global_xlator;
74b1de
-static pthread_key_t this_xlator_key;
74b1de
-static pthread_key_t synctask_key;
74b1de
-static pthread_key_t uuid_buf_key;
74b1de
-static char global_uuid_buf[GF_UUID_BUF_SIZE];
74b1de
-static pthread_key_t lkowner_buf_key;
74b1de
-static char global_lkowner_buf[GF_LKOWNER_BUF_SIZE];
74b1de
-static pthread_key_t leaseid_buf_key;
74b1de
 static int gf_global_mem_acct_enable = 1;
74b1de
 static pthread_once_t globals_inited = PTHREAD_ONCE_INIT;
74b1de
 
74b1de
+static pthread_key_t free_key;
74b1de
+
74b1de
+static __thread xlator_t *thread_xlator = NULL;
74b1de
+static __thread void *thread_synctask = NULL;
74b1de
+static __thread void *thread_leaseid = NULL;
74b1de
+static __thread struct syncopctx thread_syncopctx = {};
74b1de
+static __thread char thread_uuid_buf[GF_UUID_BUF_SIZE] = {};
74b1de
+static __thread char thread_lkowner_buf[GF_LKOWNER_BUF_SIZE] = {};
74b1de
+static __thread char thread_leaseid_buf[GF_LEASE_ID_BUF_SIZE] = {};
74b1de
+
74b1de
 int
74b1de
 gf_global_mem_acct_enable_get(void)
74b1de
 {
74b1de
@@ -122,12 +125,6 @@ gf_global_mem_acct_enable_set(int val)
74b1de
     return 0;
74b1de
 }
74b1de
 
74b1de
-void
74b1de
-glusterfs_this_destroy(void *ptr)
74b1de
-{
74b1de
-    FREE(ptr);
74b1de
-}
74b1de
-
74b1de
 static struct xlator_cbks global_cbks = {
74b1de
     .forget = NULL,
74b1de
     .release = NULL,
74b1de
@@ -212,18 +209,9 @@ struct volume_options global_xl_options[] = {
74b1de
 
74b1de
 static volume_opt_list_t global_xl_opt_list;
74b1de
 
74b1de
-int
74b1de
+void
74b1de
 glusterfs_this_init()
74b1de
 {
74b1de
-    int ret = 0;
74b1de
-    ret = pthread_key_create(&this_xlator_key, glusterfs_this_destroy);
74b1de
-    if (ret != 0) {
74b1de
-        gf_msg("", GF_LOG_WARNING, ret, LG_MSG_PTHREAD_KEY_CREATE_FAILED,
74b1de
-               "failed to create "
74b1de
-               "the pthread key");
74b1de
-        return ret;
74b1de
-    }
74b1de
-
74b1de
     global_xlator.name = "glusterfs";
74b1de
     global_xlator.type = GF_GLOBAL_XLATOR_NAME;
74b1de
     global_xlator.cbks = &global_cbks;
74b1de
@@ -237,301 +225,120 @@ glusterfs_this_init()
74b1de
     global_xl_opt_list.given_opt = global_xl_options;
74b1de
 
74b1de
     list_add_tail(&global_xl_opt_list.list, &global_xlator.volume_options);
74b1de
-
74b1de
-    return ret;
74b1de
 }
74b1de
 
74b1de
 xlator_t **
74b1de
 __glusterfs_this_location()
74b1de
 {
74b1de
-    xlator_t **this_location = NULL;
74b1de
-    int ret = 0;
74b1de
-
74b1de
-    this_location = pthread_getspecific(this_xlator_key);
74b1de
-
74b1de
-    if (!this_location) {
74b1de
-        this_location = CALLOC(1, sizeof(*this_location));
74b1de
-        if (!this_location)
74b1de
-            goto out;
74b1de
+    xlator_t **this_location;
74b1de
 
74b1de
-        ret = pthread_setspecific(this_xlator_key, this_location);
74b1de
-        if (ret != 0) {
74b1de
-            FREE(this_location);
74b1de
-            this_location = NULL;
74b1de
-            goto out;
74b1de
-        }
74b1de
-    }
74b1de
-out:
74b1de
-    if (this_location) {
74b1de
-        if (!*this_location)
74b1de
-            *this_location = &global_xlator;
74b1de
+    this_location = &thread_xlator;
74b1de
+    if (*this_location == NULL) {
74b1de
+        thread_xlator = &global_xlator;
74b1de
     }
74b1de
+
74b1de
     return this_location;
74b1de
 }
74b1de
 
74b1de
 xlator_t *
74b1de
 glusterfs_this_get()
74b1de
 {
74b1de
-    xlator_t **this_location = NULL;
74b1de
-
74b1de
-    this_location = __glusterfs_this_location();
74b1de
-    if (!this_location)
74b1de
-        return &global_xlator;
74b1de
-
74b1de
-    return *this_location;
74b1de
+    return *__glusterfs_this_location();
74b1de
 }
74b1de
 
74b1de
-int
74b1de
+void
74b1de
 glusterfs_this_set(xlator_t *this)
74b1de
 {
74b1de
-    xlator_t **this_location = NULL;
74b1de
-
74b1de
-    this_location = __glusterfs_this_location();
74b1de
-    if (!this_location)
74b1de
-        return -ENOMEM;
74b1de
-
74b1de
-    *this_location = this;
74b1de
-
74b1de
-    return 0;
74b1de
+    thread_xlator = this;
74b1de
 }
74b1de
 
74b1de
 /* SYNCOPCTX */
74b1de
-static pthread_key_t syncopctx_key;
74b1de
-
74b1de
-static void
74b1de
-syncopctx_key_destroy(void *ptr)
74b1de
-{
74b1de
-    struct syncopctx *opctx = ptr;
74b1de
-
74b1de
-    if (opctx) {
74b1de
-        if (opctx->groups)
74b1de
-            GF_FREE(opctx->groups);
74b1de
-
74b1de
-        GF_FREE(opctx);
74b1de
-    }
74b1de
-
74b1de
-    return;
74b1de
-}
74b1de
 
74b1de
 void *
74b1de
 syncopctx_getctx()
74b1de
 {
74b1de
-    void *opctx = NULL;
74b1de
-
74b1de
-    opctx = pthread_getspecific(syncopctx_key);
74b1de
-
74b1de
-    return opctx;
74b1de
-}
74b1de
-
74b1de
-int
74b1de
-syncopctx_setctx(void *ctx)
74b1de
-{
74b1de
-    int ret = 0;
74b1de
-
74b1de
-    ret = pthread_setspecific(syncopctx_key, ctx);
74b1de
-
74b1de
-    return ret;
74b1de
-}
74b1de
-
74b1de
-static int
74b1de
-syncopctx_init(void)
74b1de
-{
74b1de
-    int ret;
74b1de
-
74b1de
-    ret = pthread_key_create(&syncopctx_key, syncopctx_key_destroy);
74b1de
-
74b1de
-    return ret;
74b1de
+    return &thread_syncopctx;
74b1de
 }
74b1de
 
74b1de
 /* SYNCTASK */
74b1de
 
74b1de
-int
74b1de
-synctask_init()
74b1de
-{
74b1de
-    int ret = 0;
74b1de
-
74b1de
-    ret = pthread_key_create(&synctask_key, NULL);
74b1de
-
74b1de
-    return ret;
74b1de
-}
74b1de
-
74b1de
 void *
74b1de
 synctask_get()
74b1de
 {
74b1de
-    void *synctask = NULL;
74b1de
-
74b1de
-    synctask = pthread_getspecific(synctask_key);
74b1de
-
74b1de
-    return synctask;
74b1de
+    return thread_synctask;
74b1de
 }
74b1de
 
74b1de
-int
74b1de
+void
74b1de
 synctask_set(void *synctask)
74b1de
 {
74b1de
-    int ret = 0;
74b1de
-
74b1de
-    pthread_setspecific(synctask_key, synctask);
74b1de
-
74b1de
-    return ret;
74b1de
+    thread_synctask = synctask;
74b1de
 }
74b1de
 
74b1de
 // UUID_BUFFER
74b1de
 
74b1de
-void
74b1de
-glusterfs_uuid_buf_destroy(void *ptr)
74b1de
-{
74b1de
-    FREE(ptr);
74b1de
-}
74b1de
-
74b1de
-int
74b1de
-glusterfs_uuid_buf_init()
74b1de
-{
74b1de
-    int ret = 0;
74b1de
-
74b1de
-    ret = pthread_key_create(&uuid_buf_key, glusterfs_uuid_buf_destroy);
74b1de
-    return ret;
74b1de
-}
74b1de
-
74b1de
 char *
74b1de
 glusterfs_uuid_buf_get()
74b1de
 {
74b1de
-    char *buf;
74b1de
-    int ret = 0;
74b1de
-
74b1de
-    buf = pthread_getspecific(uuid_buf_key);
74b1de
-    if (!buf) {
74b1de
-        buf = MALLOC(GF_UUID_BUF_SIZE);
74b1de
-        ret = pthread_setspecific(uuid_buf_key, (void *)buf);
74b1de
-        if (ret)
74b1de
-            buf = global_uuid_buf;
74b1de
-    }
74b1de
-    return buf;
74b1de
+    return thread_uuid_buf;
74b1de
 }
74b1de
 
74b1de
 /* LKOWNER_BUFFER */
74b1de
 
74b1de
-void
74b1de
-glusterfs_lkowner_buf_destroy(void *ptr)
74b1de
-{
74b1de
-    FREE(ptr);
74b1de
-}
74b1de
-
74b1de
-int
74b1de
-glusterfs_lkowner_buf_init()
74b1de
-{
74b1de
-    int ret = 0;
74b1de
-
74b1de
-    ret = pthread_key_create(&lkowner_buf_key, glusterfs_lkowner_buf_destroy);
74b1de
-    return ret;
74b1de
-}
74b1de
-
74b1de
 char *
74b1de
 glusterfs_lkowner_buf_get()
74b1de
 {
74b1de
-    char *buf;
74b1de
-    int ret = 0;
74b1de
-
74b1de
-    buf = pthread_getspecific(lkowner_buf_key);
74b1de
-    if (!buf) {
74b1de
-        buf = MALLOC(GF_LKOWNER_BUF_SIZE);
74b1de
-        ret = pthread_setspecific(lkowner_buf_key, (void *)buf);
74b1de
-        if (ret)
74b1de
-            buf = global_lkowner_buf;
74b1de
-    }
74b1de
-    return buf;
74b1de
+    return thread_lkowner_buf;
74b1de
 }
74b1de
 
74b1de
 /* Leaseid buffer */
74b1de
-void
74b1de
-glusterfs_leaseid_buf_destroy(void *ptr)
74b1de
-{
74b1de
-    FREE(ptr);
74b1de
-}
74b1de
-
74b1de
-int
74b1de
-glusterfs_leaseid_buf_init()
74b1de
-{
74b1de
-    int ret = 0;
74b1de
-
74b1de
-    ret = pthread_key_create(&leaseid_buf_key, glusterfs_leaseid_buf_destroy);
74b1de
-    return ret;
74b1de
-}
74b1de
 
74b1de
 char *
74b1de
 glusterfs_leaseid_buf_get()
74b1de
 {
74b1de
     char *buf = NULL;
74b1de
-    int ret = 0;
74b1de
 
74b1de
-    buf = pthread_getspecific(leaseid_buf_key);
74b1de
-    if (!buf) {
74b1de
-        buf = CALLOC(1, GF_LEASE_ID_BUF_SIZE);
74b1de
-        ret = pthread_setspecific(leaseid_buf_key, (void *)buf);
74b1de
-        if (ret) {
74b1de
-            FREE(buf);
74b1de
-            buf = NULL;
74b1de
-        }
74b1de
+    buf = thread_leaseid;
74b1de
+    if (buf == NULL) {
74b1de
+        buf = thread_leaseid_buf;
74b1de
+        thread_leaseid = buf;
74b1de
     }
74b1de
+
74b1de
     return buf;
74b1de
 }
74b1de
 
74b1de
 char *
74b1de
 glusterfs_leaseid_exist()
74b1de
 {
74b1de
-    return pthread_getspecific(leaseid_buf_key);
74b1de
+    return thread_leaseid;
74b1de
 }
74b1de
 
74b1de
 static void
74b1de
-gf_globals_init_once()
74b1de
+glusterfs_cleanup(void *ptr)
74b1de
 {
74b1de
-    int ret = 0;
74b1de
-
74b1de
-    ret = glusterfs_this_init();
74b1de
-    if (ret) {
74b1de
-        gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_TRANSLATOR_INIT_FAILED,
74b1de
-               "ERROR: glusterfs-translator init failed");
74b1de
-        goto out;
74b1de
-    }
74b1de
-
74b1de
-    ret = glusterfs_uuid_buf_init();
74b1de
-    if (ret) {
74b1de
-        gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_UUID_BUF_INIT_FAILED,
74b1de
-               "ERROR: glusterfs uuid buffer init failed");
74b1de
-        goto out;
74b1de
+    if (thread_syncopctx.groups != NULL) {
74b1de
+        GF_FREE(thread_syncopctx.groups);
74b1de
     }
74b1de
 
74b1de
-    ret = glusterfs_lkowner_buf_init();
74b1de
-    if (ret) {
74b1de
-        gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_LKOWNER_BUF_INIT_FAILED,
74b1de
-               "ERROR: glusterfs lkowner buffer init failed");
74b1de
-        goto out;
74b1de
-    }
74b1de
+    mem_pool_thread_destructor();
74b1de
+}
74b1de
 
74b1de
-    ret = glusterfs_leaseid_buf_init();
74b1de
-    if (ret) {
74b1de
-        gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_LEASEID_BUF_INIT_FAILED,
74b1de
-               "ERROR: glusterfs leaseid buffer init failed");
74b1de
-        goto out;
74b1de
-    }
74b1de
+static void
74b1de
+gf_globals_init_once()
74b1de
+{
74b1de
+    int ret = 0;
74b1de
 
74b1de
-    ret = synctask_init();
74b1de
-    if (ret) {
74b1de
-        gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_SYNCTASK_INIT_FAILED,
74b1de
-               "ERROR: glusterfs synctask init failed");
74b1de
-        goto out;
74b1de
-    }
74b1de
+    glusterfs_this_init();
74b1de
 
74b1de
-    ret = syncopctx_init();
74b1de
-    if (ret) {
74b1de
-        gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_SYNCOPCTX_INIT_FAILED,
74b1de
-               "ERROR: glusterfs syncopctx init failed");
74b1de
-        goto out;
74b1de
-    }
74b1de
-out:
74b1de
+    /* This is needed only to cleanup the potential allocation of
74b1de
+     * thread_syncopctx.groups. */
74b1de
+    ret = pthread_key_create(&free_key, glusterfs_cleanup);
74b1de
+    if (ret != 0) {
74b1de
+        gf_msg("", GF_LOG_ERROR, ret, LG_MSG_PTHREAD_KEY_CREATE_FAILED,
74b1de
+               "failed to create the pthread key");
74b1de
 
74b1de
-    if (ret) {
74b1de
         gf_msg("", GF_LOG_CRITICAL, 0, LG_MSG_GLOBAL_INIT_FAILED,
74b1de
                "Exiting as global initialization failed");
74b1de
+
74b1de
         exit(ret);
74b1de
     }
74b1de
 }
74b1de
diff --git a/libglusterfs/src/glusterfs/globals.h b/libglusterfs/src/glusterfs/globals.h
74b1de
index e45db14..55476f6 100644
74b1de
--- a/libglusterfs/src/glusterfs/globals.h
74b1de
+++ b/libglusterfs/src/glusterfs/globals.h
74b1de
@@ -147,7 +147,7 @@ xlator_t **
74b1de
 __glusterfs_this_location(void);
74b1de
 xlator_t *
74b1de
 glusterfs_this_get(void);
74b1de
-int
74b1de
+void
74b1de
 glusterfs_this_set(xlator_t *);
74b1de
 
74b1de
 extern xlator_t global_xlator;
74b1de
@@ -156,13 +156,11 @@ extern struct volume_options global_xl_options[];
74b1de
 /* syncopctx */
74b1de
 void *
74b1de
 syncopctx_getctx(void);
74b1de
-int
74b1de
-syncopctx_setctx(void *ctx);
74b1de
 
74b1de
 /* task */
74b1de
 void *
74b1de
 synctask_get(void);
74b1de
-int
74b1de
+void
74b1de
 synctask_set(void *);
74b1de
 
74b1de
 /* uuid_buf */
74b1de
diff --git a/libglusterfs/src/glusterfs/mem-pool.h b/libglusterfs/src/glusterfs/mem-pool.h
74b1de
index 0250b59..c5a486b 100644
74b1de
--- a/libglusterfs/src/glusterfs/mem-pool.h
74b1de
+++ b/libglusterfs/src/glusterfs/mem-pool.h
74b1de
@@ -279,9 +279,7 @@ struct mem_pool_shared {
74b1de
 };
74b1de
 
74b1de
 void
74b1de
-mem_pools_init_early(void); /* basic initialization of memory pools */
74b1de
-void
74b1de
-mem_pools_init_late(void); /* start the pool_sweeper thread */
74b1de
+mem_pools_init(void); /* start the pool_sweeper thread */
74b1de
 void
74b1de
 mem_pools_fini(void); /* cleanup memory pools */
74b1de
 
74b1de
@@ -306,6 +304,9 @@ void
74b1de
 mem_pool_destroy(struct mem_pool *pool);
74b1de
 
74b1de
 void
74b1de
+mem_pool_thread_destructor(void);
74b1de
+
74b1de
+void
74b1de
 gf_mem_acct_enable_set(void *ctx);
74b1de
 
74b1de
 #endif /* _MEM_POOL_H */
74b1de
diff --git a/libglusterfs/src/libglusterfs.sym b/libglusterfs/src/libglusterfs.sym
74b1de
index 7a2edef..86215d2 100644
74b1de
--- a/libglusterfs/src/libglusterfs.sym
74b1de
+++ b/libglusterfs/src/libglusterfs.sym
74b1de
@@ -872,8 +872,7 @@ mem_get0
74b1de
 mem_pool_destroy
74b1de
 mem_pool_new_fn
74b1de
 mem_pools_fini
74b1de
-mem_pools_init_early
74b1de
-mem_pools_init_late
74b1de
+mem_pools_init
74b1de
 mem_put
74b1de
 mkdir_p
74b1de
 next_token
74b1de
diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c
74b1de
index 9b4ea52..ab78804 100644
74b1de
--- a/libglusterfs/src/mem-pool.c
74b1de
+++ b/libglusterfs/src/mem-pool.c
74b1de
@@ -353,7 +353,6 @@ free:
74b1de
     FREE(ptr);
74b1de
 }
74b1de
 
74b1de
-static pthread_key_t pool_key;
74b1de
 static pthread_mutex_t pool_lock = PTHREAD_MUTEX_INITIALIZER;
74b1de
 static struct list_head pool_threads;
74b1de
 static pthread_mutex_t pool_free_lock = PTHREAD_MUTEX_INITIALIZER;
74b1de
@@ -361,6 +360,8 @@ static struct list_head pool_free_threads;
74b1de
 static struct mem_pool_shared pools[NPOOLS];
74b1de
 static size_t pool_list_size;
74b1de
 
74b1de
+static __thread per_thread_pool_list_t *thread_pool_list = NULL;
74b1de
+
74b1de
 #if !defined(GF_DISABLE_MEMPOOL)
74b1de
 #define N_COLD_LISTS 1024
74b1de
 #define POOL_SWEEP_SECS 30
74b1de
@@ -373,7 +374,6 @@ typedef struct {
74b1de
 
74b1de
 enum init_state {
74b1de
     GF_MEMPOOL_INIT_NONE = 0,
74b1de
-    GF_MEMPOOL_INIT_PREINIT,
74b1de
     GF_MEMPOOL_INIT_EARLY,
74b1de
     GF_MEMPOOL_INIT_LATE,
74b1de
     GF_MEMPOOL_INIT_DESTROY
74b1de
@@ -486,9 +486,9 @@ pool_sweeper(void *arg)
74b1de
 }
74b1de
 
74b1de
 void
74b1de
-pool_destructor(void *arg)
74b1de
+mem_pool_thread_destructor(void)
74b1de
 {
74b1de
-    per_thread_pool_list_t *pool_list = arg;
74b1de
+    per_thread_pool_list_t *pool_list = thread_pool_list;
74b1de
 
74b1de
     /* The pool-sweeper thread will take it from here.
74b1de
      *
74b1de
@@ -499,7 +499,10 @@ pool_destructor(void *arg)
74b1de
      * This change can modify what mem_put() does, but both possibilities are
74b1de
      * fine until the sweeper thread kicks in. The real synchronization must be
74b1de
      * between mem_put() and the sweeper thread. */
74b1de
-    pool_list->poison = 1;
74b1de
+    if (pool_list != NULL) {
74b1de
+        pool_list->poison = 1;
74b1de
+        thread_pool_list = NULL;
74b1de
+    }
74b1de
 }
74b1de
 
74b1de
 static __attribute__((constructor)) void
74b1de
@@ -522,46 +525,14 @@ mem_pools_preinit(void)
74b1de
     pool_list_size = sizeof(per_thread_pool_list_t) +
74b1de
                      sizeof(per_thread_pool_t) * (NPOOLS - 1);
74b1de
 
74b1de
-    init_done = GF_MEMPOOL_INIT_PREINIT;
74b1de
+    init_done = GF_MEMPOOL_INIT_EARLY;
74b1de
 }
74b1de
 
74b1de
-/* Use mem_pools_init_early() function for basic initialization. There will be
74b1de
- * no cleanup done by the pool_sweeper thread until mem_pools_init_late() has
74b1de
- * been called. Calling mem_get() will be possible after this function has
74b1de
- * setup the basic structures. */
74b1de
+/* Call mem_pools_init() once threading has been configured completely. This
74b1de
+ * prevent the pool_sweeper thread from getting killed once the main() thread
74b1de
+ * exits during deamonizing. */
74b1de
 void
74b1de
-mem_pools_init_early(void)
74b1de
-{
74b1de
-    pthread_mutex_lock(&init_mutex);
74b1de
-    /* Use a pthread_key destructor to clean up when a thread exits.
74b1de
-     *
74b1de
-     * We won't increase init_count here, that is only done when the
74b1de
-     * pool_sweeper thread is started too.
74b1de
-     */
74b1de
-    if (init_done == GF_MEMPOOL_INIT_PREINIT ||
74b1de
-        init_done == GF_MEMPOOL_INIT_DESTROY) {
74b1de
-        /* key has not been created yet */
74b1de
-        if (pthread_key_create(&pool_key, pool_destructor) != 0) {
74b1de
-            gf_log("mem-pool", GF_LOG_CRITICAL,
74b1de
-                   "failed to initialize mem-pool key");
74b1de
-        }
74b1de
-
74b1de
-        init_done = GF_MEMPOOL_INIT_EARLY;
74b1de
-    } else {
74b1de
-        gf_log("mem-pool", GF_LOG_CRITICAL,
74b1de
-               "incorrect order of mem-pool initialization "
74b1de
-               "(init_done=%d)",
74b1de
-               init_done);
74b1de
-    }
74b1de
-
74b1de
-    pthread_mutex_unlock(&init_mutex);
74b1de
-}
74b1de
-
74b1de
-/* Call mem_pools_init_late() once threading has been configured completely.
74b1de
- * This prevent the pool_sweeper thread from getting killed once the main()
74b1de
- * thread exits during deamonizing. */
74b1de
-void
74b1de
-mem_pools_init_late(void)
74b1de
+mem_pools_init(void)
74b1de
 {
74b1de
     pthread_mutex_lock(&init_mutex);
74b1de
     if ((init_count++) == 0) {
74b1de
@@ -580,13 +551,12 @@ mem_pools_fini(void)
74b1de
     switch (init_count) {
74b1de
         case 0:
74b1de
             /*
74b1de
-             * If init_count is already zero (as e.g. if somebody called
74b1de
-             * this before mem_pools_init_late) then the sweeper was
74b1de
-             * probably never even started so we don't need to stop it.
74b1de
-             * Even if there's some crazy circumstance where there is a
74b1de
-             * sweeper but init_count is still zero, that just means we'll
74b1de
-             * leave it running.  Not perfect, but far better than any
74b1de
-             * known alternative.
74b1de
+             * If init_count is already zero (as e.g. if somebody called this
74b1de
+             * before mem_pools_init) then the sweeper was probably never even
74b1de
+             * started so we don't need to stop it. Even if there's some crazy
74b1de
+             * circumstance where there is a sweeper but init_count is still
74b1de
+             * zero, that just means we'll leave it running. Not perfect, but
74b1de
+             * far better than any known alternative.
74b1de
              */
74b1de
             break;
74b1de
         case 1: {
74b1de
@@ -594,20 +564,17 @@ mem_pools_fini(void)
74b1de
             per_thread_pool_list_t *next_pl;
74b1de
             unsigned int i;
74b1de
 
74b1de
-            /* if only mem_pools_init_early() was called, sweeper_tid will
74b1de
-             * be invalid and the functions will error out. That is not
74b1de
-             * critical. In all other cases, the sweeper_tid will be valid
74b1de
-             * and the thread gets stopped. */
74b1de
+            /* if mem_pools_init() was not called, sweeper_tid will be invalid
74b1de
+             * and the functions will error out. That is not critical. In all
74b1de
+             * other cases, the sweeper_tid will be valid and the thread gets
74b1de
+             * stopped. */
74b1de
             (void)pthread_cancel(sweeper_tid);
74b1de
             (void)pthread_join(sweeper_tid, NULL);
74b1de
 
74b1de
-            /* Need to clean the pool_key to prevent further usage of the
74b1de
-             * per_thread_pool_list_t structure that is stored for each
74b1de
-             * thread.
74b1de
-             * This also prevents calling pool_destructor() when a thread
74b1de
-             * exits, so there is no chance on a use-after-free of the
74b1de
-             * per_thread_pool_list_t structure. */
74b1de
-            (void)pthread_key_delete(pool_key);
74b1de
+            /* At this point all threads should have already terminated, so
74b1de
+             * it should be safe to destroy all pending per_thread_pool_list_t
74b1de
+             * structures that are stored for each thread. */
74b1de
+            mem_pool_thread_destructor();
74b1de
 
74b1de
             /* free all objects from all pools */
74b1de
             list_for_each_entry_safe(pool_list, next_pl, &pool_threads,
74b1de
@@ -642,11 +609,7 @@ mem_pools_fini(void)
74b1de
 
74b1de
 #else
74b1de
 void
74b1de
-mem_pools_init_early(void)
74b1de
-{
74b1de
-}
74b1de
-void
74b1de
-mem_pools_init_late(void)
74b1de
+mem_pools_init(void)
74b1de
 {
74b1de
 }
74b1de
 void
74b1de
@@ -734,7 +697,7 @@ mem_get_pool_list(void)
74b1de
     per_thread_pool_list_t *pool_list;
74b1de
     unsigned int i;
74b1de
 
74b1de
-    pool_list = pthread_getspecific(pool_key);
74b1de
+    pool_list = thread_pool_list;
74b1de
     if (pool_list) {
74b1de
         return pool_list;
74b1de
     }
74b1de
@@ -767,7 +730,8 @@ mem_get_pool_list(void)
74b1de
     list_add(&pool_list->thr_list, &pool_threads);
74b1de
     (void)pthread_mutex_unlock(&pool_lock);
74b1de
 
74b1de
-    (void)pthread_setspecific(pool_key, pool_list);
74b1de
+    thread_pool_list = pool_list;
74b1de
+
74b1de
     return pool_list;
74b1de
 }
74b1de
 
74b1de
diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c
74b1de
index c05939a..2eb7b49 100644
74b1de
--- a/libglusterfs/src/syncop.c
74b1de
+++ b/libglusterfs/src/syncop.c
74b1de
@@ -26,28 +26,10 @@ syncopctx_setfsuid(void *uid)
74b1de
 
74b1de
     opctx = syncopctx_getctx();
74b1de
 
74b1de
-    /* alloc for this thread the first time */
74b1de
-    if (!opctx) {
74b1de
-        opctx = GF_CALLOC(1, sizeof(*opctx), gf_common_mt_syncopctx);
74b1de
-        if (!opctx) {
74b1de
-            ret = -1;
74b1de
-            goto out;
74b1de
-        }
74b1de
-
74b1de
-        ret = syncopctx_setctx(opctx);
74b1de
-        if (ret != 0) {
74b1de
-            GF_FREE(opctx);
74b1de
-            opctx = NULL;
74b1de
-            goto out;
74b1de
-        }
74b1de
-    }
74b1de
+    opctx->uid = *(uid_t *)uid;
74b1de
+    opctx->valid |= SYNCOPCTX_UID;
74b1de
 
74b1de
 out:
74b1de
-    if (opctx && uid) {
74b1de
-        opctx->uid = *(uid_t *)uid;
74b1de
-        opctx->valid |= SYNCOPCTX_UID;
74b1de
-    }
74b1de
-
74b1de
     return ret;
74b1de
 }
74b1de
 
74b1de
@@ -66,28 +48,10 @@ syncopctx_setfsgid(void *gid)
74b1de
 
74b1de
     opctx = syncopctx_getctx();
74b1de
 
74b1de
-    /* alloc for this thread the first time */
74b1de
-    if (!opctx) {
74b1de
-        opctx = GF_CALLOC(1, sizeof(*opctx), gf_common_mt_syncopctx);
74b1de
-        if (!opctx) {
74b1de
-            ret = -1;
74b1de
-            goto out;
74b1de
-        }
74b1de
-
74b1de
-        ret = syncopctx_setctx(opctx);
74b1de
-        if (ret != 0) {
74b1de
-            GF_FREE(opctx);
74b1de
-            opctx = NULL;
74b1de
-            goto out;
74b1de
-        }
74b1de
-    }
74b1de
+    opctx->gid = *(gid_t *)gid;
74b1de
+    opctx->valid |= SYNCOPCTX_GID;
74b1de
 
74b1de
 out:
74b1de
-    if (opctx && gid) {
74b1de
-        opctx->gid = *(gid_t *)gid;
74b1de
-        opctx->valid |= SYNCOPCTX_GID;
74b1de
-    }
74b1de
-
74b1de
     return ret;
74b1de
 }
74b1de
 
74b1de
@@ -107,43 +71,20 @@ syncopctx_setfsgroups(int count, const void *groups)
74b1de
 
74b1de
     opctx = syncopctx_getctx();
74b1de
 
74b1de
-    /* alloc for this thread the first time */
74b1de
-    if (!opctx) {
74b1de
-        opctx = GF_CALLOC(1, sizeof(*opctx), gf_common_mt_syncopctx);
74b1de
-        if (!opctx) {
74b1de
-            ret = -1;
74b1de
-            goto out;
74b1de
-        }
74b1de
-
74b1de
-        ret = syncopctx_setctx(opctx);
74b1de
-        if (ret != 0) {
74b1de
-            GF_FREE(opctx);
74b1de
-            opctx = NULL;
74b1de
-            goto out;
74b1de
-        }
74b1de
-    }
74b1de
-
74b1de
     /* resize internal groups as required */
74b1de
     if (count && opctx->grpsize < count) {
74b1de
         if (opctx->groups) {
74b1de
-            tmpgroups = GF_REALLOC(opctx->groups, (sizeof(gid_t) * count));
74b1de
-            /* NOTE: Not really required to zero the reallocation,
74b1de
-             * as ngrps controls the validity of data,
74b1de
-             * making a note irrespective */
74b1de
-            if (tmpgroups == NULL) {
74b1de
-                opctx->grpsize = 0;
74b1de
-                GF_FREE(opctx->groups);
74b1de
-                opctx->groups = NULL;
74b1de
-                ret = -1;
74b1de
-                goto out;
74b1de
-            }
74b1de
-        } else {
74b1de
-            tmpgroups = GF_CALLOC(count, sizeof(gid_t), gf_common_mt_syncopctx);
74b1de
-            if (tmpgroups == NULL) {
74b1de
-                opctx->grpsize = 0;
74b1de
-                ret = -1;
74b1de
-                goto out;
74b1de
-            }
74b1de
+            /* Group list will be updated later, so no need to keep current
74b1de
+             * data and waste time copying it. It's better to free the current
74b1de
+             * allocation and then allocate a fresh new memory block. */
74b1de
+            GF_FREE(opctx->groups);
74b1de
+            opctx->groups = NULL;
74b1de
+            opctx->grpsize = 0;
74b1de
+        }
74b1de
+        tmpgroups = GF_MALLOC(count * sizeof(gid_t), gf_common_mt_syncopctx);
74b1de
+        if (tmpgroups == NULL) {
74b1de
+            ret = -1;
74b1de
+            goto out;
74b1de
         }
74b1de
 
74b1de
         opctx->groups = tmpgroups;
74b1de
@@ -177,28 +118,10 @@ syncopctx_setfspid(void *pid)
74b1de
 
74b1de
     opctx = syncopctx_getctx();
74b1de
 
74b1de
-    /* alloc for this thread the first time */
74b1de
-    if (!opctx) {
74b1de
-        opctx = GF_CALLOC(1, sizeof(*opctx), gf_common_mt_syncopctx);
74b1de
-        if (!opctx) {
74b1de
-            ret = -1;
74b1de
-            goto out;
74b1de
-        }
74b1de
-
74b1de
-        ret = syncopctx_setctx(opctx);
74b1de
-        if (ret != 0) {
74b1de
-            GF_FREE(opctx);
74b1de
-            opctx = NULL;
74b1de
-            goto out;
74b1de
-        }
74b1de
-    }
74b1de
+    opctx->pid = *(pid_t *)pid;
74b1de
+    opctx->valid |= SYNCOPCTX_PID;
74b1de
 
74b1de
 out:
74b1de
-    if (opctx && pid) {
74b1de
-        opctx->pid = *(pid_t *)pid;
74b1de
-        opctx->valid |= SYNCOPCTX_PID;
74b1de
-    }
74b1de
-
74b1de
     return ret;
74b1de
 }
74b1de
 
74b1de
@@ -217,28 +140,10 @@ syncopctx_setfslkowner(gf_lkowner_t *lk_owner)
74b1de
 
74b1de
     opctx = syncopctx_getctx();
74b1de
 
74b1de
-    /* alloc for this thread the first time */
74b1de
-    if (!opctx) {
74b1de
-        opctx = GF_CALLOC(1, sizeof(*opctx), gf_common_mt_syncopctx);
74b1de
-        if (!opctx) {
74b1de
-            ret = -1;
74b1de
-            goto out;
74b1de
-        }
74b1de
-
74b1de
-        ret = syncopctx_setctx(opctx);
74b1de
-        if (ret != 0) {
74b1de
-            GF_FREE(opctx);
74b1de
-            opctx = NULL;
74b1de
-            goto out;
74b1de
-        }
74b1de
-    }
74b1de
+    opctx->lk_owner = *lk_owner;
74b1de
+    opctx->valid |= SYNCOPCTX_LKOWNER;
74b1de
 
74b1de
 out:
74b1de
-    if (opctx && lk_owner) {
74b1de
-        opctx->lk_owner = *lk_owner;
74b1de
-        opctx->valid |= SYNCOPCTX_LKOWNER;
74b1de
-    }
74b1de
-
74b1de
     return ret;
74b1de
 }
74b1de
 
74b1de
diff --git a/xlators/features/changelog/lib/src/gf-changelog-helpers.c b/xlators/features/changelog/lib/src/gf-changelog-helpers.c
74b1de
index 03dac5e..e5a9db4 100644
74b1de
--- a/xlators/features/changelog/lib/src/gf-changelog-helpers.c
74b1de
+++ b/xlators/features/changelog/lib/src/gf-changelog-helpers.c
74b1de
@@ -64,20 +64,7 @@ gf_rfc3986_encode_space_newline(unsigned char *s, char *enc, char *estr)
74b1de
  *       made a part of libglusterfs.
74b1de
  */
74b1de
 
74b1de
-static pthread_key_t rl_key;
74b1de
-static pthread_once_t rl_once = PTHREAD_ONCE_INIT;
74b1de
-
74b1de
-static void
74b1de
-readline_destructor(void *ptr)
74b1de
-{
74b1de
-    GF_FREE(ptr);
74b1de
-}
74b1de
-
74b1de
-static void
74b1de
-readline_once(void)
74b1de
-{
74b1de
-    pthread_key_create(&rl_key, readline_destructor);
74b1de
-}
74b1de
+static __thread read_line_t thread_tsd = {};
74b1de
 
74b1de
 static ssize_t
74b1de
 my_read(read_line_t *tsd, int fd, char *ptr)
74b1de
@@ -97,27 +84,6 @@ my_read(read_line_t *tsd, int fd, char *ptr)
74b1de
     return 1;
74b1de
 }
74b1de
 
74b1de
-static int
74b1de
-gf_readline_init_once(read_line_t **tsd)
74b1de
-{
74b1de
-    if (pthread_once(&rl_once, readline_once) != 0)
74b1de
-        return -1;
74b1de
-
74b1de
-    *tsd = pthread_getspecific(rl_key);
74b1de
-    if (*tsd)
74b1de
-        goto out;
74b1de
-
74b1de
-    *tsd = GF_CALLOC(1, sizeof(**tsd), gf_changelog_mt_libgfchangelog_rl_t);
74b1de
-    if (!*tsd)
74b1de
-        return -1;
74b1de
-
74b1de
-    if (pthread_setspecific(rl_key, *tsd) != 0)
74b1de
-        return -1;
74b1de
-
74b1de
-out:
74b1de
-    return 0;
74b1de
-}
74b1de
-
74b1de
 ssize_t
74b1de
 gf_readline(int fd, void *vptr, size_t maxlen)
74b1de
 {
74b1de
@@ -125,10 +91,7 @@ gf_readline(int fd, void *vptr, size_t maxlen)
74b1de
     size_t rc = 0;
74b1de
     char c = ' ';
74b1de
     char *ptr = NULL;
74b1de
-    read_line_t *tsd = NULL;
74b1de
-
74b1de
-    if (gf_readline_init_once(&tsd))
74b1de
-        return -1;
74b1de
+    read_line_t *tsd = &thread_tsd;
74b1de
 
74b1de
     ptr = vptr;
74b1de
     for (n = 1; n < maxlen; n++) {
74b1de
@@ -151,10 +114,7 @@ off_t
74b1de
 gf_lseek(int fd, off_t offset, int whence)
74b1de
 {
74b1de
     off_t off = 0;
74b1de
-    read_line_t *tsd = NULL;
74b1de
-
74b1de
-    if (gf_readline_init_once(&tsd))
74b1de
-        return -1;
74b1de
+    read_line_t *tsd = &thread_tsd;
74b1de
 
74b1de
     off = sys_lseek(fd, offset, whence);
74b1de
     if (off == -1)
74b1de
@@ -169,10 +129,7 @@ gf_lseek(int fd, off_t offset, int whence)
74b1de
 int
74b1de
 gf_ftruncate(int fd, off_t length)
74b1de
 {
74b1de
-    read_line_t *tsd = NULL;
74b1de
-
74b1de
-    if (gf_readline_init_once(&tsd))
74b1de
-        return -1;
74b1de
+    read_line_t *tsd = &thread_tsd;
74b1de
 
74b1de
     if (sys_ftruncate(fd, 0))
74b1de
         return -1;
74b1de
diff --git a/xlators/features/changelog/lib/src/gf-changelog.c b/xlators/features/changelog/lib/src/gf-changelog.c
74b1de
index 7ed9e55..d6acb37 100644
74b1de
--- a/xlators/features/changelog/lib/src/gf-changelog.c
74b1de
+++ b/xlators/features/changelog/lib/src/gf-changelog.c
74b1de
@@ -237,9 +237,8 @@ gf_changelog_init_master()
74b1de
 {
74b1de
     int ret = 0;
74b1de
 
74b1de
-    mem_pools_init_early();
74b1de
     ret = gf_changelog_init_context();
74b1de
-    mem_pools_init_late();
74b1de
+    mem_pools_init();
74b1de
 
74b1de
     return ret;
74b1de
 }
74b1de
diff --git a/xlators/nfs/server/src/mount3udp_svc.c b/xlators/nfs/server/src/mount3udp_svc.c
74b1de
index d5e4169..0688779eb 100644
74b1de
--- a/xlators/nfs/server/src/mount3udp_svc.c
74b1de
+++ b/xlators/nfs/server/src/mount3udp_svc.c
74b1de
@@ -216,11 +216,7 @@ mount3udp_thread(void *argv)
74b1de
 
74b1de
     GF_ASSERT(nfsx);
74b1de
 
74b1de
-    if (glusterfs_this_set(nfsx)) {
74b1de
-        gf_msg(GF_MNT, GF_LOG_ERROR, ENOMEM, NFS_MSG_XLATOR_SET_FAIL,
74b1de
-               "Failed to set xlator, nfs.mount-udp will not work");
74b1de
-        return NULL;
74b1de
-    }
74b1de
+    glusterfs_this_set(nfsx);
74b1de
 
74b1de
     transp = svcudp_create(RPC_ANYSOCK);
74b1de
     if (transp == NULL) {
74b1de
-- 
74b1de
1.8.3.1
74b1de