summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmar Tumballi <amarts@redhat.com>2012-04-12 17:52:10 +0530
committerAnand Avati <avati@redhat.com>2012-05-03 21:54:54 -0700
commite4b3c0d90c46e6dde97f57fa93ed215b0d34e0c4 (patch)
tree60b39fe288a35f419ec874931451ecde333a5f0a
parentd879951ca9e69632517cf13f8f8773c330c14165 (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>
-rw-r--r--libglusterfs/src/iobuf.c99
-rw-r--r--libglusterfs/src/iobuf.h8
-rw-r--r--xlators/storage/posix/src/posix.c5
3 files changed, 100 insertions, 12 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 */
};
diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c
index b92ab19e6..f98056286 100644
--- a/xlators/storage/posix/src/posix.c
+++ b/xlators/storage/posix/src/posix.c
@@ -1890,9 +1890,6 @@ out:
return 0;
}
-#define ALIGN_BUF(ptr,bound) ((void *)((unsigned long)(ptr + bound - 1) & \
- (unsigned long)(~(bound - 1))))
-
int
posix_readv (call_frame_t *frame, xlator_t *this,
fd_t *fd, size_t size, off_t offset, uint32_t flags, dict_t *xdata)
@@ -2055,7 +2052,7 @@ __posix_writev (int fd, struct iovec *vector, int count, off_t startoff,
internal_off = startoff;
for (idx = 0; idx < count; idx++) {
/* page aligned buffer */
- buf = ALIGN_BUF (alloc_buf, align);
+ buf = GF_ALIGN_BUF (alloc_buf, align);
memcpy (buf, vector[idx].iov_base, vector[idx].iov_len);