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