summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/iobuf.c
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs/src/iobuf.c')
-rw-r--r--libglusterfs/src/iobuf.c247
1 files changed, 173 insertions, 74 deletions
diff --git a/libglusterfs/src/iobuf.c b/libglusterfs/src/iobuf.c
index 8b6fddf5eb8..fc5630fcc71 100644
--- a/libglusterfs/src/iobuf.c
+++ b/libglusterfs/src/iobuf.c
@@ -39,8 +39,8 @@ __iobuf_arena_init_iobufs (struct iobuf_arena *iobuf_arena)
GF_VALIDATE_OR_GOTO ("iobuf", iobuf_arena, out);
- arena_size = iobuf_arena->iobuf_pool->arena_size;
- page_size = iobuf_arena->iobuf_pool->page_size;
+ arena_size = iobuf_arena->arena_size;
+ page_size = iobuf_arena->page_size;
iobuf_cnt = arena_size / page_size;
iobuf_arena->iobufs = GF_CALLOC (sizeof (*iobuf), iobuf_cnt,
@@ -80,8 +80,8 @@ __iobuf_arena_destroy_iobufs (struct iobuf_arena *iobuf_arena)
GF_VALIDATE_OR_GOTO ("iobuf", iobuf_arena, out);
- arena_size = iobuf_arena->iobuf_pool->arena_size;
- page_size = iobuf_arena->iobuf_pool->page_size;
+ arena_size = iobuf_arena->arena_size;
+ page_size = iobuf_arena->page_size;
iobuf_cnt = arena_size / page_size;
if (!iobuf_arena->iobufs) {
@@ -127,10 +127,10 @@ out:
struct iobuf_arena *
-__iobuf_arena_alloc (struct iobuf_pool *iobuf_pool)
+__iobuf_arena_alloc (struct iobuf_pool *iobuf_pool, size_t page_size)
{
struct iobuf_arena *iobuf_arena = NULL;
- size_t arena_size = 0;
+ size_t arena_size = 0, rounded_size = 0;
GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out);
@@ -145,6 +145,16 @@ __iobuf_arena_alloc (struct iobuf_pool *iobuf_pool)
iobuf_arena->iobuf_pool = iobuf_pool;
arena_size = iobuf_pool->arena_size;
+
+ rounded_size = gf_roundup_power_of_two (page_size);
+ iobuf_arena->page_size = rounded_size;
+
+ if ((arena_size % rounded_size) != 0) {
+ arena_size = (arena_size / rounded_size) * rounded_size;
+ }
+
+ iobuf_arena->arena_size = arena_size;
+
iobuf_arena->mem_base = mmap (NULL, arena_size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (iobuf_arena->mem_base == MAP_FAILED) {
@@ -171,50 +181,69 @@ out:
struct iobuf_arena *
-__iobuf_arena_unprune (struct iobuf_pool *iobuf_pool)
+__iobuf_arena_unprune (struct iobuf_pool *iobuf_pool, size_t page_size)
{
- struct iobuf_arena *iobuf_arena = NULL;
- struct iobuf_arena *tmp = NULL;
-
+ struct iobuf_arena *iobuf_arena = NULL;
+ struct iobuf_arena *tmp = NULL;
+ int index = 0;
+
GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out);
+
+ index = log_base2 (page_size);
+ if (index > GF_VARIABLE_IOBUF_COUNT) {
+ gf_log ("iobuf", GF_LOG_DEBUG, "no arena corresponding to "
+ "page_size (%"GF_PRI_SIZET") is present. max supported "
+ "size (%llu)", page_size,
+ 1LL << GF_VARIABLE_IOBUF_COUNT);
+ return NULL;
+ }
- list_for_each_entry (tmp, &iobuf_pool->purge.list, list) {
+ list_for_each_entry (tmp, &iobuf_pool->purge[index], list) {
list_del_init (&tmp->list);
iobuf_arena = tmp;
break;
}
-
out:
return iobuf_arena;
}
struct iobuf_arena *
-__iobuf_pool_add_arena (struct iobuf_pool *iobuf_pool)
+__iobuf_pool_add_arena (struct iobuf_pool *iobuf_pool, size_t page_size)
{
- struct iobuf_arena *iobuf_arena = NULL;
+ struct iobuf_arena *iobuf_arena = NULL;
+ int index = 0;
+ uint32_t rounded_size = 0;
- GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out);
+ rounded_size = gf_roundup_power_of_two (page_size);
+
+ index = log_base2 (rounded_size);
+ if (index > GF_VARIABLE_IOBUF_COUNT) {
+ gf_log ("iobuf", GF_LOG_DEBUG, "page_size %u of "
+ "iobufs in arena being added is greater than max "
+ "supported size (%llu)", rounded_size,
+ 1ULL << GF_VARIABLE_IOBUF_COUNT);
+ return NULL;
+ }
- iobuf_arena = __iobuf_arena_unprune (iobuf_pool);
+ iobuf_arena = __iobuf_arena_unprune (iobuf_pool, rounded_size);
if (!iobuf_arena)
- iobuf_arena = __iobuf_arena_alloc (iobuf_pool);
+ iobuf_arena = __iobuf_arena_alloc (iobuf_pool, rounded_size);
if (!iobuf_arena) {
gf_log (THIS->name, GF_LOG_WARNING, "arena not found");
return NULL;
}
- list_add_tail (&iobuf_arena->list, &iobuf_pool->arenas.list);
+ list_add_tail (&iobuf_arena->list, &iobuf_pool->arenas[index]);
-out:
return iobuf_arena;
}
struct iobuf_arena *
-iobuf_pool_add_arena (struct iobuf_pool *iobuf_pool)
+iobuf_pool_add_arena (struct iobuf_pool *iobuf_pool, size_t page_size)
{
struct iobuf_arena *iobuf_arena = NULL;
@@ -222,7 +251,7 @@ iobuf_pool_add_arena (struct iobuf_pool *iobuf_pool)
pthread_mutex_lock (&iobuf_pool->mutex);
{
- iobuf_arena = __iobuf_pool_add_arena (iobuf_pool);
+ iobuf_arena = __iobuf_pool_add_arena (iobuf_pool, page_size);
}
pthread_mutex_unlock (&iobuf_pool->mutex);
@@ -235,17 +264,19 @@ void
iobuf_pool_destroy (struct iobuf_pool *iobuf_pool)
{
struct iobuf_arena *iobuf_arena = NULL;
- struct iobuf_arena *tmp = NULL;
+ struct iobuf_arena *tmp = NULL;
+ int i = 0;
GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out);
- list_for_each_entry_safe (iobuf_arena, tmp, &iobuf_pool->arenas.list,
- list) {
-
- list_del_init (&iobuf_arena->list);
- iobuf_pool->arena_cnt--;
+ for (i = 0; i < GF_VARIABLE_IOBUF_COUNT; i++) {
+ list_for_each_entry_safe (iobuf_arena, tmp,
+ &iobuf_pool->arenas[i], list) {
+ list_del_init (&iobuf_arena->list);
+ iobuf_pool->arena_cnt--;
+ __iobuf_arena_destroy (iobuf_arena);
+ }
- __iobuf_arena_destroy (iobuf_arena);
}
out:
@@ -257,28 +288,34 @@ struct iobuf_pool *
iobuf_pool_new (size_t arena_size, size_t page_size)
{
struct iobuf_pool *iobuf_pool = NULL;
+ int i = 0;
+ unsigned long long max_size = 0;
- if (arena_size < page_size) {
- gf_log (THIS->name, GF_LOG_WARNING,
+ max_size = ((1ULL << (GF_VARIABLE_IOBUF_COUNT)) - 1);
+ if ((arena_size < page_size) || (max_size < arena_size)) {
+ gf_log ("", GF_LOG_WARNING,
"arena size (%zu) is less than page size(%zu)",
arena_size, page_size);
- return NULL;
+ goto out;
}
iobuf_pool = GF_CALLOC (sizeof (*iobuf_pool), 1,
gf_common_mt_iobuf_pool);
if (!iobuf_pool)
- return NULL;
+ goto out;
pthread_mutex_init (&iobuf_pool->mutex, NULL);
- INIT_LIST_HEAD (&iobuf_pool->arenas.list);
- INIT_LIST_HEAD (&iobuf_pool->filled.list);
- INIT_LIST_HEAD (&iobuf_pool->purge.list);
+ for (i = 0; i < GF_VARIABLE_IOBUF_COUNT; i++) {
+ INIT_LIST_HEAD (&iobuf_pool->arenas[i]);
+ INIT_LIST_HEAD (&iobuf_pool->filled[i]);
+ INIT_LIST_HEAD (&iobuf_pool->purge[i]);
+ }
iobuf_pool->arena_size = arena_size;
- iobuf_pool->page_size = page_size;
+ iobuf_pool->default_page_size = page_size;
- iobuf_pool_add_arena (iobuf_pool);
+ iobuf_pool_add_arena (iobuf_pool, page_size);
+out:
return iobuf_pool;
}
@@ -289,23 +326,25 @@ __iobuf_pool_prune (struct iobuf_pool *iobuf_pool)
{
struct iobuf_arena *iobuf_arena = NULL;
struct iobuf_arena *tmp = NULL;
+ int i = 0;
GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out);
- if (list_empty (&iobuf_pool->arenas.list))
- /* buffering - preserve this one arena (if at all)
- for __iobuf_arena_unprune */
- return;
-
- list_for_each_entry_safe (iobuf_arena, tmp, &iobuf_pool->purge.list,
- list) {
- if (iobuf_arena->active_cnt)
+ for (i = 0; i < GF_VARIABLE_IOBUF_COUNT; i++) {
+ if (list_empty (&iobuf_pool->arenas[i])) {
continue;
+ }
- list_del_init (&iobuf_arena->list);
- iobuf_pool->arena_cnt--;
+ list_for_each_entry_safe (iobuf_arena, tmp,
+ &iobuf_pool->purge[i], list) {
+ if (iobuf_arena->active_cnt)
+ continue;
- __iobuf_arena_destroy (iobuf_arena);
+ list_del_init (&iobuf_arena->list);
+ iobuf_pool->arena_cnt--;
+
+ __iobuf_arena_destroy (iobuf_arena);
+ }
}
out:
@@ -330,15 +369,27 @@ out:
struct iobuf_arena *
-__iobuf_select_arena (struct iobuf_pool *iobuf_pool)
+__iobuf_select_arena (struct iobuf_pool *iobuf_pool, size_t page_size)
{
- struct iobuf_arena *iobuf_arena = NULL;
- struct iobuf_arena *trav = NULL;
+ struct iobuf_arena *iobuf_arena = NULL;
+ struct iobuf_arena *trav = NULL;
+ size_t rounded_size = 0;
+ int index = 0;
GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out);
+ rounded_size = gf_roundup_power_of_two (page_size);
+
+ index = log_base2 (rounded_size);
+ if (index > GF_VARIABLE_IOBUF_COUNT) {
+ gf_log ("iobuf", GF_LOG_DEBUG, "size of iobuf requested (%"
+ GF_PRI_SIZET") is greater than max supported size (%"
+ "llu)", rounded_size, 1ULL << GF_VARIABLE_IOBUF_COUNT);
+ return NULL;
+ }
+
/* look for unused iobuf from the head-most arena */
- list_for_each_entry (trav, &iobuf_pool->arenas.list, list) {
+ list_for_each_entry (trav, &iobuf_pool->arenas[index], list) {
if (trav->passive_cnt) {
iobuf_arena = trav;
break;
@@ -347,7 +398,7 @@ __iobuf_select_arena (struct iobuf_pool *iobuf_pool)
if (!iobuf_arena) {
/* all arenas were full */
- iobuf_arena = __iobuf_pool_add_arena (iobuf_pool);
+ iobuf_arena = __iobuf_pool_add_arena (iobuf_pool, rounded_size);
}
out:
@@ -372,12 +423,12 @@ __iobuf_unref (struct iobuf *iobuf)
return iobuf;
}
-
struct iobuf *
-__iobuf_get (struct iobuf_arena *iobuf_arena)
+__iobuf_get (struct iobuf_arena *iobuf_arena, size_t page_size)
{
- struct iobuf *iobuf = NULL;
- struct iobuf_pool *iobuf_pool = NULL;
+ struct iobuf *iobuf = NULL;
+ struct iobuf_pool *iobuf_pool = NULL;
+ int index = 0;
GF_VALIDATE_OR_GOTO ("iobuf", iobuf_arena, out);
@@ -393,33 +444,67 @@ __iobuf_get (struct iobuf_arena *iobuf_arena)
iobuf_arena->active_cnt++;
if (iobuf_arena->passive_cnt == 0) {
+ index = log_base2 (page_size);
list_del (&iobuf_arena->list);
- list_add (&iobuf_arena->list, &iobuf_pool->filled.list);
+ list_add (&iobuf_arena->list, &iobuf_pool->filled[index]);
}
out:
return iobuf;
}
+struct iobuf *
+iobuf_get2 (struct iobuf_pool *iobuf_pool, size_t page_size)
+{
+ struct iobuf *iobuf = NULL;
+ struct iobuf_arena *iobuf_arena = NULL;
+ size_t rounded_size = 0;
+
+ if (page_size == 0) {
+ page_size = iobuf_pool->default_page_size;
+ }
+
+ rounded_size = gf_roundup_power_of_two (page_size);
+
+ pthread_mutex_lock (&iobuf_pool->mutex);
+ {
+ /* most eligible arena for picking an iobuf */
+ iobuf_arena = __iobuf_select_arena (iobuf_pool, rounded_size);
+ if (!iobuf_arena)
+ goto unlock;
+
+ iobuf = __iobuf_get (iobuf_arena, rounded_size);
+ if (!iobuf)
+ goto unlock;
+
+ __iobuf_ref (iobuf);
+ }
+unlock:
+ pthread_mutex_unlock (&iobuf_pool->mutex);
+
+ return iobuf;
+}
struct iobuf *
iobuf_get (struct iobuf_pool *iobuf_pool)
{
- struct iobuf *iobuf = NULL;
- struct iobuf_arena *iobuf_arena = NULL;
+ struct iobuf *iobuf = NULL;
+ struct iobuf_arena *iobuf_arena = NULL;
GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out);
pthread_mutex_lock (&iobuf_pool->mutex);
{
/* most eligible arena for picking an iobuf */
- iobuf_arena = __iobuf_select_arena (iobuf_pool);
+ iobuf_arena = __iobuf_select_arena (iobuf_pool,
+ iobuf_pool->default_page_size);
if (!iobuf_arena) {
gf_log (THIS->name, GF_LOG_WARNING, "arena not found");
goto unlock;
}
- iobuf = __iobuf_get (iobuf_arena);
+ iobuf = __iobuf_get (iobuf_arena,
+ iobuf_pool->default_page_size);
if (!iobuf) {
gf_log (THIS->name, GF_LOG_WARNING, "iobuf not found");
goto unlock;
@@ -434,20 +519,30 @@ out:
return iobuf;
}
-
void
__iobuf_put (struct iobuf *iobuf, struct iobuf_arena *iobuf_arena)
{
struct iobuf_pool *iobuf_pool = NULL;
+ int index = 0;
GF_VALIDATE_OR_GOTO ("iobuf", iobuf_arena, out);
GF_VALIDATE_OR_GOTO ("iobuf", iobuf, out);
iobuf_pool = iobuf_arena->iobuf_pool;
+ index = log_base2 (iobuf_arena->page_size);
+ if (index > GF_VARIABLE_IOBUF_COUNT) {
+ gf_log ("iobuf", GF_LOG_DEBUG, "size of iobuf being returned to"
+ " pool(%"GF_PRI_SIZET") is greater than max supported "
+ "size(%llu) arena = %p",
+ iobuf_arena->page_size, 1ULL << GF_VARIABLE_IOBUF_COUNT,
+ iobuf_arena);
+ return;
+ }
+
if (iobuf_arena->passive_cnt == 0) {
list_del (&iobuf_arena->list);
- list_add_tail (&iobuf_arena->list, &iobuf_pool->arenas.list);
+ list_add_tail (&iobuf_arena->list, &iobuf_pool->arenas[index]);
}
list_del_init (&iobuf->list);
@@ -458,7 +553,7 @@ __iobuf_put (struct iobuf *iobuf, struct iobuf_arena *iobuf_arena)
if (iobuf_arena->active_cnt == 0) {
list_del (&iobuf_arena->list);
- list_add_tail (&iobuf_arena->list, &iobuf_pool->purge.list);
+ list_add_tail (&iobuf_arena->list, &iobuf_pool->purge[index]);
}
out:
return;
@@ -703,7 +798,7 @@ iobuf_size (struct iobuf *iobuf)
goto out;
}
- size = iobuf->iobuf_arena->iobuf_pool->page_size;
+ size = iobuf->iobuf_arena->page_size;
out:
return size;
}
@@ -789,6 +884,7 @@ iobuf_stats_dump (struct iobuf_pool *iobuf_pool)
char msg[1024];
struct iobuf_arena *trav = NULL;
int i = 1;
+ int j = 0;
int ret = -1;
GF_VALIDATE_OR_GOTO ("iobuf", iobuf_pool, out);
@@ -802,19 +898,22 @@ iobuf_stats_dump (struct iobuf_pool *iobuf_pool)
}
gf_proc_dump_add_section("iobuf.global");
gf_proc_dump_write("iobuf.global.iobuf_pool","%p", iobuf_pool);
- gf_proc_dump_write("iobuf.global.iobuf_pool.page_size", "%d",
- iobuf_pool->page_size);
+ gf_proc_dump_write("iobuf.global.iobuf_pool.default_page_size", "%d",
+ iobuf_pool->default_page_size);
gf_proc_dump_write("iobuf.global.iobuf_pool.arena_size", "%d",
iobuf_pool->arena_size);
gf_proc_dump_write("iobuf.global.iobuf_pool.arena_cnt", "%d",
iobuf_pool->arena_cnt);
- list_for_each_entry (trav, &iobuf_pool->arenas.list, list) {
- snprintf(msg, sizeof(msg), "iobuf.global.iobuf_pool.arena.%d",
- i);
- gf_proc_dump_add_section(msg);
- iobuf_arena_info_dump(trav,msg);
- i++;
+ for (j = 0; j < GF_VARIABLE_IOBUF_COUNT; j++) {
+ list_for_each_entry (trav, &iobuf_pool->arenas[j], list) {
+ snprintf(msg, sizeof(msg),
+ "iobuf.global.iobuf_pool.arena.%d", i);
+ gf_proc_dump_add_section(msg);
+ iobuf_arena_info_dump(trav,msg);
+ i++;
+ }
+
}
pthread_mutex_unlock(&iobuf_pool->mutex);