diff options
-rw-r--r-- | libglusterfs/src/iobuf.c | 99 | ||||
-rw-r--r-- | libglusterfs/src/iobuf.h | 8 | ||||
-rw-r--r-- | xlators/storage/posix/src/posix.c | 5 |
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); |