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