summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/mem-pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs/src/mem-pool.c')
-rw-r--r--libglusterfs/src/mem-pool.c154
1 files changed, 76 insertions, 78 deletions
diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c
index f3dfc2149..b901dd7a8 100644
--- a/libglusterfs/src/mem-pool.c
+++ b/libglusterfs/src/mem-pool.c
@@ -1,20 +1,11 @@
/*
- Copyright (c) 2008-2011 Gluster, Inc. <http://www.gluster.com>
- This file is part of GlusterFS.
-
- GlusterFS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3 of the License,
- or (at your option) any later version.
-
- GlusterFS is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see
- <http://www.gnu.org/licenses/>.
+ Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
*/
#include "mem-pool.h"
@@ -39,37 +30,18 @@
#define GLUSTERFS_ENV_MEM_ACCT_STR "GLUSTERFS_DISABLE_MEM_ACCT"
-static int gf_mem_acct_enable = 0;
-
-int
-gf_mem_acct_is_enabled ()
-{
- return gf_mem_acct_enable;
-}
-
void
-gf_mem_acct_enable_set ()
+gf_mem_acct_enable_set (void *data)
{
- char *opt = NULL;
- long val = -1;
+ glusterfs_ctx_t *ctx = NULL;
-#ifdef DEBUG
- gf_mem_acct_enable = 1;
- return;
-#endif
+ ctx = data;
- opt = getenv (GLUSTERFS_ENV_MEM_ACCT_STR);
+ GF_ASSERT (ctx);
- if (!opt)
- return;
-
- val = strtol (opt, NULL, 0);
-
- if (val)
- gf_mem_acct_enable = 0;
- else
- gf_mem_acct_enable = 1;
+ ctx->mem_acct_enable = 1;
+ return;
}
void
@@ -84,22 +56,17 @@ gf_mem_set_acct_info (xlator_t *xl, char **alloc_ptr,
ptr = (char *) (*alloc_ptr);
- if (!xl) {
- GF_ASSERT (0);
- }
+ GF_ASSERT (xl != NULL);
- if (!(xl->mem_acct.rec)) {
- GF_ASSERT (0);
- }
+ GF_ASSERT (xl->mem_acct.rec != NULL);
- if (type > xl->mem_acct.num_types) {
- GF_ASSERT (0);
- }
+ GF_ASSERT (type <= xl->mem_acct.num_types);
LOCK(&xl->mem_acct.rec[type].lock);
{
xl->mem_acct.rec[type].size += size;
xl->mem_acct.rec[type].num_allocs++;
+ xl->mem_acct.rec[type].total_allocs++;
xl->mem_acct.rec[type].max_size =
max (xl->mem_acct.rec[type].max_size,
xl->mem_acct.rec[type].size);
@@ -133,7 +100,7 @@ __gf_calloc (size_t nmemb, size_t size, uint32_t type)
char *ptr = NULL;
xlator_t *xl = NULL;
- if (!gf_mem_acct_enable)
+ if (!THIS->ctx->mem_acct_enable)
return CALLOC (nmemb, size);
xl = THIS;
@@ -159,7 +126,7 @@ __gf_malloc (size_t size, uint32_t type)
char *ptr = NULL;
xlator_t *xl = NULL;
- if (!gf_mem_acct_enable)
+ if (!THIS->ctx->mem_acct_enable)
return MALLOC (size);
xl = THIS;
@@ -184,7 +151,7 @@ __gf_realloc (void *ptr, size_t size)
xlator_t *xl = NULL;
uint32_t type = 0;
- if (!gf_mem_acct_enable)
+ if (!THIS->ctx->mem_acct_enable)
return REALLOC (ptr, size);
tot_size = size + GF_MEM_HEADER_SIZE + GF_MEM_TRAILER_SIZE;
@@ -257,7 +224,7 @@ __gf_free (void *free_ptr)
uint32_t type = 0;
xlator_t *xl = NULL;
- if (!gf_mem_acct_enable) {
+ if (!THIS->ctx->mem_acct_enable) {
FREE (free_ptr);
return;
}
@@ -267,20 +234,16 @@ __gf_free (void *free_ptr)
ptr = (char *)free_ptr - 8 - 4;
- if (GF_MEM_HEADER_MAGIC != *(uint32_t *)ptr) {
- //Possible corruption, assert here
- GF_ASSERT (0);
- }
+ //Possible corruption, assert here
+ GF_ASSERT (GF_MEM_HEADER_MAGIC == *(uint32_t *)ptr);
*(uint32_t *)ptr = 0;
ptr = ptr - sizeof(xlator_t *);
memcpy (&xl, ptr, sizeof(xlator_t *));
- if (!xl) {
- //gf_free expects xl to be available
- GF_ASSERT (0);
- }
+ //gf_free expects xl to be available
+ GF_ASSERT (xl != NULL);
if (!xl->mem_acct.rec) {
ptr = (char *)free_ptr - GF_MEM_HEADER_SIZE;
@@ -293,11 +256,10 @@ __gf_free (void *free_ptr)
ptr = ptr - 4;
type = *(uint32_t *)ptr;
- if (GF_MEM_TRAILER_MAGIC != *(uint32_t *)
- ((char *)free_ptr + req_size)) {
- // This points to a memory overrun
- GF_ASSERT (0);
- }
+ // This points to a memory overrun
+ GF_ASSERT (GF_MEM_TRAILER_MAGIC ==
+ *(uint32_t *)((char *)free_ptr + req_size));
+
*(uint32_t *) ((char *)free_ptr + req_size) = 0;
LOCK (&xl->mem_acct.rec[type].lock);
@@ -314,16 +276,18 @@ free:
struct mem_pool *
mem_pool_new_fn (unsigned long sizeof_type,
- unsigned long count)
+ unsigned long count, char *name)
{
struct mem_pool *mem_pool = NULL;
unsigned long padded_sizeof_type = 0;
void *pool = NULL;
int i = 0;
+ int ret = 0;
struct list_head *list = NULL;
+ glusterfs_ctx_t *ctx = NULL;
if (!sizeof_type || !count) {
- gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument");
+ gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument");
return NULL;
}
padded_sizeof_type = sizeof_type + GF_MEM_POOL_PAD_BOUNDARY;
@@ -332,8 +296,18 @@ mem_pool_new_fn (unsigned long sizeof_type,
if (!mem_pool)
return NULL;
+ ret = gf_asprintf (&mem_pool->name, "%s:%s", THIS->name, name);
+ if (ret < 0)
+ return NULL;
+
+ if (!mem_pool->name) {
+ GF_FREE (mem_pool);
+ return NULL;
+ }
+
LOCK_INIT (&mem_pool->lock);
INIT_LIST_HEAD (&mem_pool->list);
+ INIT_LIST_HEAD (&mem_pool->global_list);
mem_pool->padded_sizeof_type = padded_sizeof_type;
mem_pool->cold_count = count;
@@ -341,6 +315,7 @@ mem_pool_new_fn (unsigned long sizeof_type,
pool = GF_CALLOC (count, padded_sizeof_type, gf_common_mt_long);
if (!pool) {
+ GF_FREE (mem_pool->name);
GF_FREE (mem_pool);
return NULL;
}
@@ -354,6 +329,14 @@ mem_pool_new_fn (unsigned long sizeof_type,
mem_pool->pool = pool;
mem_pool->pool_end = pool + (count * (padded_sizeof_type));
+ /* add this pool to the global list */
+ ctx = THIS->ctx;
+ if (!ctx)
+ goto out;
+
+ list_add (&mem_pool->global_list, &ctx->mempool_list);
+
+out:
return mem_pool;
}
@@ -363,7 +346,7 @@ mem_get0 (struct mem_pool *mem_pool)
void *ptr = NULL;
if (!mem_pool) {
- gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument");
+ gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument");
return NULL;
}
@@ -384,12 +367,13 @@ mem_get (struct mem_pool *mem_pool)
struct mem_pool **pool_ptr = NULL;
if (!mem_pool) {
- gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument");
+ gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument");
return NULL;
}
LOCK (&mem_pool->lock);
{
+ mem_pool->alloc_count++;
if (mem_pool->cold_count) {
list = mem_pool->list.next;
list_del (list);
@@ -397,6 +381,9 @@ mem_get (struct mem_pool *mem_pool)
mem_pool->hot_count++;
mem_pool->cold_count--;
+ if (mem_pool->max_alloc < mem_pool->hot_count)
+ mem_pool->max_alloc = mem_pool->hot_count;
+
ptr = list;
in_use = (ptr + GF_MEM_POOL_LIST_BOUNDARY +
GF_MEM_POOL_PTR);
@@ -408,7 +395,7 @@ mem_get (struct mem_pool *mem_pool)
/* This is a problem area. If we've run out of
* chunks in our slab above, we need to allocate
* enough memory to service this request.
- * The problem is, these indvidual chunks will fail
+ * The problem is, these individual chunks will fail
* the first address range check in __is_member. Now, since
* we're not allocating a full second slab, we wont have
* enough info perform the range check in __is_member.
@@ -425,10 +412,12 @@ mem_get (struct mem_pool *mem_pool)
* because it is too much work knowing that a better slab
* allocator is coming RSN.
*/
+ mem_pool->pool_misses++;
+ mem_pool->curr_stdalloc++;
+ if (mem_pool->max_stdalloc < mem_pool->curr_stdalloc)
+ mem_pool->max_stdalloc = mem_pool->curr_stdalloc;
ptr = GF_CALLOC (1, mem_pool->padded_sizeof_type,
gf_common_mt_mem_pool);
- gf_log_callingfn ("mem-pool", GF_LOG_DEBUG, "Mem pool is full. "
- "Callocing mem");
/* Memory coming from the heap need not be transformed from a
* chunkhead to a usable pointer since it is not coming from
@@ -449,7 +438,7 @@ static int
__is_member (struct mem_pool *pool, void *ptr)
{
if (!pool || !ptr) {
- gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument");
+ gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument");
return -1;
}
@@ -474,20 +463,22 @@ mem_put (void *ptr)
struct mem_pool *pool = NULL;
if (!ptr) {
- gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument");
+ gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument");
return;
}
list = head = mem_pool_ptr2chunkhead (ptr);
tmp = mem_pool_from_ptr (head);
if (!tmp) {
- gf_log ("mem-pool", GF_LOG_ERROR, "ptr header is corrupted");
+ gf_log_callingfn ("mem-pool", GF_LOG_ERROR,
+ "ptr header is corrupted");
return;
}
pool = *tmp;
if (!pool) {
- gf_log ("mem-pool", GF_LOG_ERROR, "mem-pool ptr is NULL");
+ gf_log_callingfn ("mem-pool", GF_LOG_ERROR,
+ "mem-pool ptr is NULL");
return;
}
LOCK (&pool->lock);
@@ -527,6 +518,7 @@ mem_put (void *ptr)
* not have enough info to distinguish between the two
* situations.
*/
+ pool->curr_stdalloc--;
GF_FREE (list);
break;
default:
@@ -543,7 +535,13 @@ mem_pool_destroy (struct mem_pool *pool)
if (!pool)
return;
+ gf_log (THIS->name, GF_LOG_INFO, "size=%lu max=%d total=%"PRIu64,
+ pool->padded_sizeof_type, pool->max_alloc, pool->alloc_count);
+
+ list_del (&pool->global_list);
+
LOCK_DESTROY (&pool->lock);
+ GF_FREE (pool->name);
GF_FREE (pool->pool);
GF_FREE (pool);