Spdk/lib/ftl/utils/ftl_mempool.c
paul luse a6dbe3721e update Intel copyright notices
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
2022-11-10 08:28:53 +00:00

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);
}