diff options
author | Amar Tumballi <amarts@redhat.com> | 2012-04-12 17:52:10 +0530 |
---|---|---|
committer | Anand Avati <avati@redhat.com> | 2012-05-03 21:54:54 -0700 |
commit | e4b3c0d90c46e6dde97f57fa93ed215b0d34e0c4 (patch) | |
tree | 60b39fe288a35f419ec874931451ecde333a5f0a /libglusterfs | |
parent | d879951ca9e69632517cf13f8f8773c330c14165 (diff) |
iobuf: option to provide larger size of buffers
provide an option to failover to standard allocation if iobuf of
required size doesn't exists. this can be achieved by keeping an
arena dedicated for all the out of boundary allocations.
Change-Id: I41a2bd7d353dc7bcb2e1a6e4b41735afe9865975
Signed-off-by: Amar Tumballi <amarts@redhat.com>
BUG: 812784
Reviewed-on: http://review.gluster.com/3136
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Anand Avati <avati@redhat.com>
Diffstat (limited to 'libglusterfs')
-rw-r--r-- | libglusterfs/src/iobuf.c | 99 | ||||
-rw-r--r-- | libglusterfs/src/iobuf.h | 8 |
2 files changed, 99 insertions, 8 deletions
diff --git a/libglusterfs/src/iobuf.c b/libglusterfs/src/iobuf.c index e1cf334ba..c2d74fd7e 100644 --- a/libglusterfs/src/iobuf.c +++ b/libglusterfs/src/iobuf.c @@ -317,6 +317,31 @@ out: return; } +static void +iobuf_create_stdalloc_arena (struct iobuf_pool *iobuf_pool) +{ + struct iobuf_arena *iobuf_arena = NULL; + + /* No locking required here as its called only once during init */ + iobuf_arena = GF_CALLOC (sizeof (*iobuf_arena), 1, + gf_common_mt_iobuf_arena); + if (!iobuf_arena) + goto err; + + INIT_LIST_HEAD (&iobuf_arena->list); + INIT_LIST_HEAD (&iobuf_arena->active.list); + INIT_LIST_HEAD (&iobuf_arena->passive.list); + + iobuf_arena->iobuf_pool = iobuf_pool; + + iobuf_arena->page_size = 0x7fffffff; + + list_add_tail (&iobuf_arena->list, + &iobuf_pool->arenas[IOBUF_ARENA_MAX_INDEX]); + +err: + return; +} struct iobuf_pool * iobuf_pool_new (void) @@ -333,7 +358,7 @@ iobuf_pool_new (void) goto out; pthread_mutex_init (&iobuf_pool->mutex, NULL); - for (i = 0; i < IOBUF_ARENA_MAX_INDEX; i++) { + for (i = 0; i <= IOBUF_ARENA_MAX_INDEX; i++) { INIT_LIST_HEAD (&iobuf_pool->arenas[i]); INIT_LIST_HEAD (&iobuf_pool->filled[i]); INIT_LIST_HEAD (&iobuf_pool->purge[i]); @@ -351,6 +376,9 @@ iobuf_pool_new (void) arena_size += page_size * num_pages; } + /* Need an arena to handle all the bigger iobuf requests */ + iobuf_create_stdalloc_arena (iobuf_pool); + iobuf_pool->arena_size = arena_size; out: @@ -509,6 +537,51 @@ out: } struct iobuf * +iobuf_get_from_stdalloc (struct iobuf_pool *iobuf_pool, size_t page_size) +{ + struct iobuf *iobuf = NULL; + struct iobuf_arena *iobuf_arena = NULL; + struct iobuf_arena *trav = NULL; + int ret = -1; + + /* The first arena in the 'MAX-INDEX' will always be used for misc */ + list_for_each_entry (trav, &iobuf_pool->arenas[IOBUF_ARENA_MAX_INDEX], + list) { + iobuf_arena = trav; + break; + } + + iobuf = GF_CALLOC (1, sizeof (*iobuf), gf_common_mt_iobuf); + if (!iobuf) + goto out; + + /* 4096 is the alignment */ + iobuf->free_ptr = GF_CALLOC (1, ((page_size + GF_IOBUF_ALIGN_SIZE) - 1), + gf_common_mt_char); + if (!iobuf->free_ptr) + goto out; + + iobuf->ptr = GF_ALIGN_BUF (iobuf->free_ptr, GF_IOBUF_ALIGN_SIZE); + iobuf->iobuf_arena = iobuf_arena; + LOCK_INIT (&iobuf->lock); + + /* Hold a ref because you are allocating and using it */ + iobuf->ref = 1; + + ret = 0; +out: + if (ret && iobuf) { + if (iobuf->free_ptr) + GF_FREE (iobuf->free_ptr); + GF_FREE (iobuf); + iobuf = NULL; + } + + return iobuf; +} + + +struct iobuf * iobuf_get2 (struct iobuf_pool *iobuf_pool, size_t page_size) { struct iobuf *iobuf = NULL; @@ -521,11 +594,17 @@ iobuf_get2 (struct iobuf_pool *iobuf_pool, size_t page_size) rounded_size = gf_iobuf_get_pagesize (page_size); if (rounded_size == -1) { - gf_log ("iobuf", GF_LOG_ERROR, "page_size (%zu) of " - "iobufs in arena being requested is greater than max " - "available", page_size); + /* make sure to provide the requested buffer with standard + memory allocations */ + iobuf = iobuf_get_from_stdalloc (iobuf_pool, page_size); + + gf_log ("iobuf", GF_LOG_DEBUG, "request for iobuf of size %zu " + "is serviced using standard calloc() (%p) as it " + "exceeds the maximum available buffer size", + page_size, iobuf); + iobuf_pool->request_misses++; - return NULL; + return iobuf; } pthread_mutex_lock (&iobuf_pool->mutex); @@ -594,9 +673,13 @@ __iobuf_put (struct iobuf *iobuf, struct iobuf_arena *iobuf_arena) index = gf_iobuf_get_arena_index (iobuf_arena->page_size); if (index == -1) { - gf_log ("iobuf", GF_LOG_ERROR, "page_size (%zu) of " - "iobufs in arena being added is greater than max " - "available", iobuf_arena->page_size); + gf_log ("iobuf", GF_LOG_DEBUG, "freeing the iobuf (%p) " + "allocated with standard calloc()", iobuf); + + /* free up properly without bothering about lists and all */ + LOCK_DESTROY (&iobuf->lock); + GF_FREE (iobuf->free_ptr); + GF_FREE (iobuf); return; } diff --git a/libglusterfs/src/iobuf.h b/libglusterfs/src/iobuf.h index 46a54dbfc..c9792ae8a 100644 --- a/libglusterfs/src/iobuf.h +++ b/libglusterfs/src/iobuf.h @@ -40,6 +40,11 @@ #define MAP_ANONYMOUS MAP_ANON #endif +#define GF_ALIGN_BUF(ptr,bound) ((void *)((unsigned long)(ptr + bound - 1) & \ + (unsigned long)(~(bound - 1)))) + +#define GF_IOBUF_ALIGN_SIZE 512 + /* one allocatable unit for the consumers of the IOBUF API */ /* each unit hosts @page_size bytes of memory */ struct iobuf; @@ -71,6 +76,9 @@ struct iobuf { int ref; /* 0 == passive, >0 == active */ void *ptr; /* usable memory region by the consumer */ + + void *free_ptr; /* in case of stdalloc, this is the + one to be freed */ }; |