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