per Intel policy to include file commit date using git cmd below. The policy does not apply to non-Intel (C) notices. git log --follow -C90% --format=%ad --date default <file> | tail -1 and then pull just the 4 digit year from the result. Intel copyrights were not added to files where Intel either had no contribution ot the contribution lacked substance (ie license header updates, formatting changes, etc). Contribution date used "--follow -C95%" to get the most accurate date. Note that several files in this patch didn't end the license/(c) block with a blank comment line so these were added as the vast majority of files do have this last blank line. Simply there for consistency. Signed-off-by: paul luse <paul.e.luse@intel.com> Change-Id: Id5b7ce4f658fe87132f14139ead58d6e285c04d4 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15192 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Community-CI: Mellanox Build Bot
294 lines
6.0 KiB
C
294 lines
6.0 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright (C) 2022 Intel Corporation.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include "spdk/stdinc.h"
|
|
#include "spdk/queue.h"
|
|
#include "spdk/util.h"
|
|
#include "spdk/env.h"
|
|
#include "spdk/likely.h"
|
|
|
|
#include "ftl_mempool.h"
|
|
#include "ftl_bitmap.h"
|
|
|
|
struct ftl_mempool_element {
|
|
SLIST_ENTRY(ftl_mempool_element) entry;
|
|
};
|
|
|
|
struct ftl_mempool {
|
|
SLIST_HEAD(, ftl_mempool_element) list;
|
|
size_t element_size;
|
|
void *buffer;
|
|
size_t buffer_size;
|
|
size_t count;
|
|
size_t alignment;
|
|
int socket_id;
|
|
struct ftl_bitmap *inuse_bmp;
|
|
void *inuse_buf;
|
|
};
|
|
|
|
static inline bool is_element_valid(struct ftl_mempool *mpool,
|
|
void *element) __attribute__((unused));
|
|
|
|
static inline bool ftl_mempool_is_initialized(struct ftl_mempool *mpool) __attribute__((unused));
|
|
|
|
static size_t
|
|
element_size_aligned(size_t size, size_t alignment)
|
|
{
|
|
if (!alignment) {
|
|
return size;
|
|
}
|
|
|
|
if (size % alignment) {
|
|
return (size / alignment + 1) * alignment;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
static inline bool
|
|
is_element_valid(struct ftl_mempool *mpool, void *element)
|
|
{
|
|
if (element < mpool->buffer) {
|
|
return false;
|
|
}
|
|
|
|
if (element + mpool->element_size > mpool->buffer + mpool->buffer_size) {
|
|
return false;
|
|
}
|
|
|
|
if (!mpool->alignment) {
|
|
return true;
|
|
}
|
|
|
|
if ((size_t)element % mpool->alignment) {
|
|
return false;
|
|
}
|
|
|
|
if ((element - mpool->buffer) % mpool->element_size != 0) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
struct ftl_mempool *ftl_mempool_create(size_t count, size_t size,
|
|
size_t alignment, int socket_id)
|
|
{
|
|
struct ftl_mempool *mp;
|
|
void *buffer;
|
|
size_t i;
|
|
|
|
assert(count > 0);
|
|
assert(size > 0);
|
|
|
|
if (!spdk_u64_is_pow2(alignment)) {
|
|
return NULL;
|
|
}
|
|
|
|
mp = calloc(1, sizeof(*mp));
|
|
if (!mp) {
|
|
return NULL;
|
|
}
|
|
|
|
size = spdk_max(size, sizeof(struct ftl_mempool_element));
|
|
|
|
mp->count = count;
|
|
mp->element_size = element_size_aligned(size, alignment);
|
|
mp->alignment = alignment;
|
|
mp->socket_id = socket_id;
|
|
SLIST_INIT(&mp->list);
|
|
|
|
mp->buffer_size = mp->element_size * mp->count;
|
|
mp->buffer = spdk_dma_malloc_socket(mp->buffer_size, mp->alignment,
|
|
NULL, socket_id);
|
|
if (!mp->buffer) {
|
|
free(mp);
|
|
return NULL;
|
|
}
|
|
|
|
buffer = mp->buffer;
|
|
for (i = 0; i < count; i++, buffer += mp->element_size) {
|
|
struct ftl_mempool_element *el = buffer;
|
|
assert(is_element_valid(mp, el));
|
|
SLIST_INSERT_HEAD(&mp->list, el, entry);
|
|
}
|
|
|
|
return mp;
|
|
}
|
|
|
|
void
|
|
ftl_mempool_destroy(struct ftl_mempool *mpool)
|
|
{
|
|
if (!mpool) {
|
|
return;
|
|
}
|
|
|
|
spdk_dma_free(mpool->buffer);
|
|
free(mpool);
|
|
}
|
|
|
|
static inline bool
|
|
ftl_mempool_is_initialized(struct ftl_mempool *mpool)
|
|
{
|
|
return mpool->inuse_buf == NULL;
|
|
}
|
|
|
|
void *
|
|
ftl_mempool_get(struct ftl_mempool *mpool)
|
|
{
|
|
struct ftl_mempool_element *el;
|
|
|
|
assert(ftl_mempool_is_initialized(mpool));
|
|
if (spdk_unlikely(SLIST_EMPTY(&mpool->list))) {
|
|
return NULL;
|
|
}
|
|
|
|
el = SLIST_FIRST(&mpool->list);
|
|
SLIST_REMOVE_HEAD(&mpool->list, entry);
|
|
|
|
return el;
|
|
}
|
|
|
|
void
|
|
ftl_mempool_put(struct ftl_mempool *mpool, void *element)
|
|
{
|
|
struct ftl_mempool_element *el = element;
|
|
|
|
assert(ftl_mempool_is_initialized(mpool));
|
|
assert(is_element_valid(mpool, element));
|
|
SLIST_INSERT_HEAD(&mpool->list, el, entry);
|
|
}
|
|
|
|
struct ftl_mempool *
|
|
ftl_mempool_create_ext(void *buffer, size_t count, size_t size, size_t alignment)
|
|
{
|
|
struct ftl_mempool *mp;
|
|
size_t inuse_buf_sz;
|
|
|
|
assert(buffer);
|
|
assert(count > 0);
|
|
assert(size > 0);
|
|
|
|
mp = calloc(1, sizeof(*mp));
|
|
if (!mp) {
|
|
goto error;
|
|
}
|
|
|
|
size = spdk_max(size, sizeof(struct ftl_mempool_element));
|
|
|
|
mp->count = count;
|
|
mp->element_size = element_size_aligned(size, alignment);
|
|
mp->alignment = alignment;
|
|
SLIST_INIT(&mp->list);
|
|
|
|
/* Calculate underlying inuse_bmp's buf size */
|
|
inuse_buf_sz = spdk_divide_round_up(mp->count, 8);
|
|
/* The bitmap size must be a multiple of word size (8b) - round up */
|
|
if (inuse_buf_sz & 7UL) {
|
|
inuse_buf_sz &= ~7UL;
|
|
inuse_buf_sz += 8;
|
|
}
|
|
|
|
mp->inuse_buf = calloc(1, inuse_buf_sz);
|
|
if (!mp->inuse_buf) {
|
|
goto error;
|
|
}
|
|
|
|
mp->inuse_bmp = ftl_bitmap_create(mp->inuse_buf, inuse_buf_sz);
|
|
if (!mp->inuse_bmp) {
|
|
goto error;
|
|
}
|
|
|
|
/* Map the buffer */
|
|
mp->buffer_size = mp->element_size * mp->count;
|
|
mp->buffer = buffer;
|
|
|
|
return mp;
|
|
|
|
error:
|
|
ftl_mempool_destroy_ext(mp);
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
ftl_mempool_destroy_ext(struct ftl_mempool *mpool)
|
|
{
|
|
if (!mpool) {
|
|
return;
|
|
}
|
|
|
|
if (mpool->inuse_bmp) {
|
|
ftl_bitmap_destroy(mpool->inuse_bmp);
|
|
}
|
|
free(mpool->inuse_buf);
|
|
free(mpool);
|
|
}
|
|
|
|
void
|
|
ftl_mempool_initialize_ext(struct ftl_mempool *mpool)
|
|
{
|
|
struct ftl_mempool_element *el;
|
|
void *buffer = mpool->buffer;
|
|
size_t i;
|
|
|
|
assert(!ftl_mempool_is_initialized(mpool));
|
|
|
|
for (i = 0; i < mpool->count; i++, buffer += mpool->element_size) {
|
|
if (ftl_bitmap_get(mpool->inuse_bmp, i)) {
|
|
continue;
|
|
}
|
|
el = buffer;
|
|
assert(is_element_valid(mpool, el));
|
|
SLIST_INSERT_HEAD(&mpool->list, el, entry);
|
|
}
|
|
|
|
ftl_bitmap_destroy(mpool->inuse_bmp);
|
|
mpool->inuse_bmp = NULL;
|
|
|
|
free(mpool->inuse_buf);
|
|
mpool->inuse_buf = NULL;
|
|
}
|
|
|
|
ftl_df_obj_id
|
|
ftl_mempool_get_df_obj_id(struct ftl_mempool *mpool, void *df_obj_ptr)
|
|
{
|
|
return ftl_df_get_obj_id(mpool->buffer, df_obj_ptr);
|
|
}
|
|
|
|
size_t
|
|
ftl_mempool_get_df_obj_index(struct ftl_mempool *mpool, void *df_obj_ptr)
|
|
{
|
|
return ftl_mempool_get_df_obj_id(mpool, df_obj_ptr) / mpool->element_size;
|
|
}
|
|
|
|
void *
|
|
ftl_mempool_get_df_ptr(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
|
|
{
|
|
return ftl_df_get_obj_ptr(mpool->buffer, df_obj_id);
|
|
}
|
|
|
|
void *
|
|
ftl_mempool_claim_df(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
|
|
{
|
|
struct ftl_mempool_element *el = ftl_df_get_obj_ptr(mpool->buffer, df_obj_id);
|
|
|
|
assert(!ftl_mempool_is_initialized(mpool));
|
|
assert(df_obj_id % mpool->element_size == 0);
|
|
assert(df_obj_id / mpool->element_size < mpool->count);
|
|
|
|
ftl_bitmap_set(mpool->inuse_bmp, df_obj_id / mpool->element_size);
|
|
return el;
|
|
}
|
|
|
|
void
|
|
ftl_mempool_release_df(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
|
|
{
|
|
assert(!ftl_mempool_is_initialized(mpool));
|
|
assert(df_obj_id % mpool->element_size == 0);
|
|
assert(df_obj_id / mpool->element_size < mpool->count);
|
|
|
|
ftl_bitmap_clear(mpool->inuse_bmp, df_obj_id / mpool->element_size);
|
|
}
|