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