]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/spdk/ocf/src/metadata/metadata_raw.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / ocf / src / metadata / metadata_raw.c
diff --git a/ceph/src/spdk/ocf/src/metadata/metadata_raw.c b/ceph/src/spdk/ocf/src/metadata/metadata_raw.c
new file mode 100644 (file)
index 0000000..cee7eeb
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+ * Copyright(c) 2012-2018 Intel Corporation
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+#include "metadata.h"
+#include "metadata_hash.h"
+#include "metadata_raw.h"
+#include "metadata_io.h"
+#include "metadata_raw_atomic.h"
+#include "../ocf_def_priv.h"
+
+#define OCF_METADATA_RAW_DEBUG 0
+
+#if 1 == OCF_METADATA_RAW_DEBUG
+#define OCF_DEBUG_TRACE(cache) \
+       ocf_cache_log(log_info, "[Metadata][Raw] %s\n", __func__)
+
+#define OCF_DEBUG_MSG(cache, msg) \
+       ocf_cache_log(cache, log_info, "[Metadata][Raw] %s - %s\n", \
+                       __func__, msg)
+
+#define OCF_DEBUG_PARAM(cache, format, ...) \
+       ocf_cache_log(cache, log_info, "[Metadata][Raw] %s - "format"\n", \
+                       __func__, ##__VA_ARGS__)
+#else
+#define OCF_DEBUG_TRACE(cache)
+#define OCF_DEBUG_MSG(cache, msg)
+#define OCF_DEBUG_PARAM(cache, format, ...)
+#endif
+
+/*******************************************************************************
+ * Common RAW Implementation
+ ******************************************************************************/
+/*
+ * Check if page is valid for specified RAW descriptor
+ */
+static bool _raw_ssd_page_is_valid(struct ocf_metadata_raw *raw, uint32_t page)
+{
+       ENV_BUG_ON(page < raw->ssd_pages_offset);
+       ENV_BUG_ON(page >= (raw->ssd_pages_offset + raw->ssd_pages));
+
+       return true;
+}
+
+/*******************************************************************************
+ * RAW RAM Implementation
+ ******************************************************************************/
+#define _RAW_RAM_ADDR(raw, line) \
+       (raw->mem_pool + (((uint64_t)raw->entry_size * (line))))
+
+#define _RAW_RAM_PAGE(raw, line) \
+               ((line) / raw->entries_in_page)
+
+#define _RAW_RAM_PAGE_SSD(raw, line) \
+               (raw->ssd_pages_offset + _RAW_RAM_PAGE(raw, line))
+
+#define _RAW_RAM_ADDR_PAGE(raw, line) \
+               (_RAW_RAM_ADDR(raw, \
+               _RAW_RAM_PAGE(raw, line) * raw->entries_in_page))
+
+#define _RAW_RAM_GET(raw, line, data) \
+               env_memcpy(data, raw->entry_size, _RAW_RAM_ADDR(raw, (line)), \
+               raw->entry_size)
+
+#define _RAW_RAM_SET(raw, line, data) \
+               env_memcpy(_RAW_RAM_ADDR(raw, line), raw->entry_size, \
+               data, raw->entry_size)
+
+
+
+/*
+ * RAM Implementation - De-Initialize
+ */
+static int _raw_ram_deinit(ocf_cache_t cache,
+               struct ocf_metadata_raw *raw)
+{
+       OCF_DEBUG_TRACE(cache);
+
+       if (raw->mem_pool) {
+               env_secure_free(raw->mem_pool, raw->mem_pool_limit);
+               raw->mem_pool = NULL;
+       }
+
+       return 0;
+}
+
+/*
+ * RAM Implementation - Initialize
+ */
+static int _raw_ram_init(ocf_cache_t cache,
+               struct ocf_metadata_raw *raw)
+{
+       size_t mem_pool_size;
+
+       OCF_DEBUG_TRACE(cache);
+
+       /* Allocate memory pool for entries */
+       mem_pool_size = raw->ssd_pages;
+       mem_pool_size *= PAGE_SIZE;
+       raw->mem_pool_limit = mem_pool_size;
+       raw->mem_pool = env_secure_alloc(mem_pool_size);
+       if (!raw->mem_pool)
+               return -ENOMEM;
+       ENV_BUG_ON(env_memset(raw->mem_pool, mem_pool_size, 0));
+
+       return 0;
+}
+
+/*
+ * RAM Implementation - Size of
+ */
+static size_t _raw_ram_size_of(ocf_cache_t cache, struct ocf_metadata_raw *raw)
+{
+       size_t size;
+
+       size = raw->ssd_pages;
+       size *= PAGE_SIZE;
+
+       return size;
+}
+
+/*
+ * RAM Implementation - Size on SSD
+ */
+static uint32_t _raw_ram_size_on_ssd(struct ocf_metadata_raw *raw)
+{
+       const size_t alignment = 128 * KiB / PAGE_SIZE;
+
+       return OCF_DIV_ROUND_UP(raw->ssd_pages, alignment) * alignment;
+}
+
+/*
+ * RAM Implementation - Checksum
+ */
+static uint32_t _raw_ram_checksum(ocf_cache_t cache,
+               struct ocf_metadata_raw *raw)
+{
+       uint64_t i;
+       uint32_t step = 0;
+       uint32_t crc = 0;
+
+       for (i = 0; i < raw->ssd_pages; i++) {
+               crc = env_crc32(crc, raw->mem_pool + PAGE_SIZE * i, PAGE_SIZE);
+               OCF_COND_RESCHED(step, 10000);
+       }
+
+       return crc;
+}
+
+/*
+ * RAM Implementation - Get entry
+ */
+static int _raw_ram_get(ocf_cache_t cache,
+               struct ocf_metadata_raw *raw, ocf_cache_line_t line,
+               void *data, uint32_t size)
+{
+       ENV_BUG_ON(!_raw_is_valid(raw, line, size));
+
+       return _RAW_RAM_GET(raw, line, data);
+}
+
+/*
+ * RAM Implementation - Read only entry access
+ */
+static const void *_raw_ram_rd_access(ocf_cache_t cache,
+               struct ocf_metadata_raw *raw, ocf_cache_line_t line,
+               uint32_t size)
+{
+       ENV_BUG_ON(!_raw_is_valid(raw, line, size));
+
+       return _RAW_RAM_ADDR(raw, line);
+}
+
+/*
+ * RAM Implementation - Read only entry access
+ */
+static void *_raw_ram_wr_access(ocf_cache_t cache,
+               struct ocf_metadata_raw *raw, ocf_cache_line_t line,
+               uint32_t size)
+{
+       ENV_BUG_ON(!_raw_is_valid(raw, line, size));
+
+       return _RAW_RAM_ADDR(raw, line);
+}
+
+/*
+ * RAM Implementation - Set Entry
+ */
+static int _raw_ram_set(ocf_cache_t cache,
+               struct ocf_metadata_raw *raw, ocf_cache_line_t line,
+               void *data, uint32_t size)
+{
+       ENV_BUG_ON(!_raw_is_valid(raw, line, size));
+
+       return _RAW_RAM_SET(raw, line, data);
+}
+
+struct _raw_ram_load_all_context {
+       struct ocf_metadata_raw *raw;
+       ocf_metadata_end_t cmpl;
+       void *priv;
+};
+
+/*
+ * RAM Implementation - Load all IO callback
+ */
+static int _raw_ram_load_all_drain(ocf_cache_t cache,
+               ctx_data_t *data, uint32_t page, void *priv)
+{
+       struct _raw_ram_load_all_context *context = priv;
+       struct ocf_metadata_raw *raw = context->raw;
+       uint32_t size = raw->entry_size * raw->entries_in_page;
+       ocf_cache_line_t line;
+       uint32_t raw_page;
+
+       ENV_BUG_ON(!_raw_ssd_page_is_valid(raw, page));
+       ENV_BUG_ON(size > PAGE_SIZE);
+
+       raw_page = page - raw->ssd_pages_offset;
+       line = raw_page * raw->entries_in_page;
+
+       OCF_DEBUG_PARAM(cache, "Line = %u, Page = %u", line, raw_page);
+
+       ctx_data_rd_check(cache->owner, _RAW_RAM_ADDR(raw, line), data, size);
+       ctx_data_seek(cache->owner, data, ctx_data_seek_current,
+                       PAGE_SIZE - size);
+
+       return 0;
+}
+
+static void _raw_ram_load_all_complete(ocf_cache_t cache,
+               void *priv, int error)
+{
+       struct _raw_ram_load_all_context *context = priv;
+
+       context->cmpl(context->priv, error);
+       env_vfree(context);
+}
+
+/*
+ * RAM Implementation - Load all metadata elements from SSD
+ */
+static void _raw_ram_load_all(ocf_cache_t cache, struct ocf_metadata_raw *raw,
+               ocf_metadata_end_t cmpl, void *priv)
+{
+       struct _raw_ram_load_all_context *context;
+       int result;
+
+       OCF_DEBUG_TRACE(cache);
+
+       context = env_vmalloc(sizeof(*context));
+       if (!context) {
+               cmpl(priv, -OCF_ERR_NO_MEM);
+               return;
+       }
+
+       context->raw = raw;
+       context->cmpl = cmpl;
+       context->priv = priv;
+
+       result = metadata_io_read_i_asynch(cache, cache->mngt_queue, context,
+                       raw->ssd_pages_offset, raw->ssd_pages,
+                       _raw_ram_load_all_drain, _raw_ram_load_all_complete);
+       if (result)
+               _raw_ram_load_all_complete(cache, context, result);
+}
+
+struct _raw_ram_flush_all_context {
+       struct ocf_metadata_raw *raw;
+       ocf_metadata_end_t cmpl;
+       void *priv;
+};
+
+/*
+ * RAM Implementation - Flush IO callback - Fill page
+ */
+static int _raw_ram_flush_all_fill(ocf_cache_t cache,
+               ctx_data_t *data, uint32_t page, void *priv)
+{
+       struct _raw_ram_flush_all_context *context = priv;
+       struct ocf_metadata_raw *raw = context->raw;
+       uint32_t size = raw->entry_size * raw->entries_in_page;
+       ocf_cache_line_t line;
+       uint32_t raw_page;
+
+       ENV_BUG_ON(!_raw_ssd_page_is_valid(raw, page));
+       ENV_BUG_ON(size > PAGE_SIZE);
+
+       raw_page = page - raw->ssd_pages_offset;
+       line = raw_page * raw->entries_in_page;
+
+       OCF_DEBUG_PARAM(cache, "Line = %u, Page = %u", line, raw_page);
+
+       ctx_data_wr_check(cache->owner, data, _RAW_RAM_ADDR(raw, line), size);
+       ctx_data_zero_check(cache->owner, data, PAGE_SIZE - size);
+
+       return 0;
+}
+
+static void _raw_ram_flush_all_complete(ocf_cache_t cache,
+               void *priv, int error)
+{
+       struct _raw_ram_flush_all_context *context = priv;
+
+       context->cmpl(context->priv, error);
+       env_vfree(context);
+}
+
+/*
+ * RAM Implementation - Flush all elements
+ */
+static void _raw_ram_flush_all(ocf_cache_t cache, struct ocf_metadata_raw *raw,
+               ocf_metadata_end_t cmpl, void *priv)
+{
+       struct _raw_ram_flush_all_context *context;
+       int result;
+
+       OCF_DEBUG_TRACE(cache);
+
+       context = env_vmalloc(sizeof(*context));
+       if (!context) {
+               cmpl(priv, -OCF_ERR_NO_MEM);
+               return;
+       }
+
+       context->raw = raw;
+       context->cmpl = cmpl;
+       context->priv = priv;
+
+       result = metadata_io_write_i_asynch(cache, cache->mngt_queue, context,
+                       raw->ssd_pages_offset, raw->ssd_pages,
+                       _raw_ram_flush_all_fill, _raw_ram_flush_all_complete);
+       if (result)
+               _raw_ram_flush_all_complete(cache, context, result);
+}
+
+/*
+ * RAM RAM Implementation - Mark to Flush
+ */
+static void _raw_ram_flush_mark(ocf_cache_t cache,
+               struct ocf_request *req, uint32_t map_idx, int to_state,
+               uint8_t start, uint8_t stop)
+{
+       if (to_state == DIRTY || to_state == CLEAN) {
+               req->map[map_idx].flush = true;
+               req->info.flush_metadata = true;
+       }
+}
+
+/*******************************************************************************
+ * RAM RAM Implementation - Do Flush Asynchronously
+ ******************************************************************************/
+struct _raw_ram_flush_ctx {
+       struct ocf_metadata_raw *raw;
+       struct ocf_request *req;
+       ocf_req_end_t complete;
+       env_atomic flush_req_cnt;
+       int error;
+};
+
+static void _raw_ram_flush_do_asynch_io_complete(ocf_cache_t cache,
+               void *context, int error)
+{
+       struct _raw_ram_flush_ctx *ctx = context;
+
+       if (error) {
+               ctx->error = error;
+               ocf_metadata_error(cache);
+       }
+
+       if (env_atomic_dec_return(&ctx->flush_req_cnt))
+               return;
+
+       OCF_DEBUG_MSG(cache, "Asynchronous flushing complete");
+
+       /* Call metadata flush completed call back */
+       ctx->req->error |= ctx->error;
+       ctx->complete(ctx->req, ctx->error);
+
+       env_free(ctx);
+}
+
+/*
+ * RAM Implementation - Flush IO callback - Fill page
+ */
+static int _raw_ram_flush_do_asynch_fill(ocf_cache_t cache,
+               ctx_data_t *data, uint32_t page, void *context)
+{
+       ocf_cache_line_t line;
+       uint32_t raw_page;
+       struct _raw_ram_flush_ctx *ctx = context;
+       struct ocf_metadata_raw *raw = NULL;
+       uint64_t size;
+
+       ENV_BUG_ON(!ctx);
+
+       raw = ctx->raw;
+       ENV_BUG_ON(!raw);
+
+       size = raw->entry_size * raw->entries_in_page;
+       ENV_BUG_ON(size > PAGE_SIZE);
+
+       raw_page = page - raw->ssd_pages_offset;
+       line = raw_page * raw->entries_in_page;
+
+       OCF_DEBUG_PARAM(cache, "Line = %u, Page = %u", line, raw_page);
+
+       ctx_data_wr_check(cache->owner, data, _RAW_RAM_ADDR(raw, line), size);
+       ctx_data_zero_check(cache->owner, data, PAGE_SIZE - size);
+
+       return 0;
+}
+
+/*
+ * RAM RAM Implementation - Do Flush
+ */
+
+int _raw_ram_flush_do_page_cmp(const void *item1, const void *item2)
+{
+       uint32_t *page1 = (uint32_t *)item1;
+       uint32_t *page2 = (uint32_t *)item2;
+
+       if (*page1 > *page2)
+               return 1;
+
+       if (*page1 < *page2)
+               return -1;
+
+       return 0;
+}
+
+static void __raw_ram_flush_do_asynch_add_pages(struct ocf_request *req,
+               uint32_t *pages_tab, struct ocf_metadata_raw *raw,
+               int *pages_to_flush) {
+       int i, j = 0;
+       int line_no = req->core_line_count;
+       struct ocf_map_info *map;
+
+       for (i = 0; i < line_no; i++) {
+               map = &req->map[i];
+               if (map->flush) {
+                       pages_tab[j] = _RAW_RAM_PAGE(raw, map->coll_idx);
+                       j++;
+               }
+       }
+
+       *pages_to_flush = j;
+}
+
+static int _raw_ram_flush_do_asynch(ocf_cache_t cache,
+               struct ocf_request *req, struct ocf_metadata_raw *raw,
+               ocf_req_end_t complete)
+{
+       int result = 0, i;
+       uint32_t __pages_tab[MAX_STACK_TAB_SIZE];
+       uint32_t *pages_tab;
+       int line_no = req->core_line_count;
+       int pages_to_flush;
+       uint32_t start_page = 0;
+       uint32_t count = 0;
+       struct _raw_ram_flush_ctx *ctx;
+
+       ENV_BUG_ON(!complete);
+
+       OCF_DEBUG_TRACE(cache);
+
+       if (!req->info.flush_metadata) {
+               /* Nothing to flush call flush callback */
+               complete(req, 0);
+               return 0;
+       }
+
+       ctx = env_zalloc(sizeof(*ctx), ENV_MEM_NOIO);
+       if (!ctx) {
+               complete(req, -ENOMEM);
+               return -ENOMEM;
+       }
+
+       ctx->req = req;
+       ctx->complete = complete;
+       ctx->raw = raw;
+       env_atomic_set(&ctx->flush_req_cnt, 1);
+
+       if (line_no <= MAX_STACK_TAB_SIZE) {
+               pages_tab = __pages_tab;
+       } else {
+               pages_tab = env_zalloc(sizeof(*pages_tab) * line_no, ENV_MEM_NOIO);
+               if (!pages_tab) {
+                       env_free(ctx);
+                       complete(req, -ENOMEM);
+                       return -ENOMEM;
+               }
+       }
+
+       /* While sorting in progress keep request remaining equal to 1,
+        * to prevent freeing of asynchronous context
+        */
+
+       __raw_ram_flush_do_asynch_add_pages(req, pages_tab, raw,
+                       &pages_to_flush);
+
+       env_sort(pages_tab, pages_to_flush, sizeof(*pages_tab),
+                       _raw_ram_flush_do_page_cmp, NULL);
+
+       i = 0;
+       while (i < pages_to_flush) {
+               start_page = pages_tab[i];
+               count = 1;
+
+               while (true) {
+                       if ((i + 1) >= pages_to_flush)
+                               break;
+
+                       if (pages_tab[i] == pages_tab[i + 1]) {
+                               i++;
+                               continue;
+                       }
+
+                       if ((pages_tab[i] + 1) != pages_tab[i + 1])
+                               break;
+
+                       i++;
+                       count++;
+               }
+
+
+               env_atomic_inc(&ctx->flush_req_cnt);
+
+               result  |= metadata_io_write_i_asynch(cache, req->io_queue, ctx,
+                               raw->ssd_pages_offset + start_page, count,
+                               _raw_ram_flush_do_asynch_fill,
+                               _raw_ram_flush_do_asynch_io_complete);
+
+               if (result)
+                       break;
+
+               i++;
+       }
+
+       _raw_ram_flush_do_asynch_io_complete(cache, ctx, result);
+
+       if (line_no > MAX_STACK_TAB_SIZE)
+               env_free(pages_tab);
+
+       return result;
+}
+
+/*******************************************************************************
+ * RAW Interfaces definitions
+ ******************************************************************************/
+#include "metadata_raw_dynamic.h"
+#include "metadata_raw_volatile.h"
+
+static const struct raw_iface IRAW[metadata_raw_type_max] = {
+       [metadata_raw_type_ram] = {
+               .init                   = _raw_ram_init,
+               .deinit                 = _raw_ram_deinit,
+               .size_of                = _raw_ram_size_of,
+               .size_on_ssd            = _raw_ram_size_on_ssd,
+               .checksum               = _raw_ram_checksum,
+               .get                    = _raw_ram_get,
+               .set                    = _raw_ram_set,
+               .rd_access              = _raw_ram_rd_access,
+               .wr_access              = _raw_ram_wr_access,
+               .load_all               = _raw_ram_load_all,
+               .flush_all              = _raw_ram_flush_all,
+               .flush_mark             = _raw_ram_flush_mark,
+               .flush_do_asynch        = _raw_ram_flush_do_asynch,
+       },
+       [metadata_raw_type_dynamic] = {
+               .init                   = raw_dynamic_init,
+               .deinit                 = raw_dynamic_deinit,
+               .size_of                = raw_dynamic_size_of,
+               .size_on_ssd            = raw_dynamic_size_on_ssd,
+               .checksum               = raw_dynamic_checksum,
+               .get                    = raw_dynamic_get,
+               .set                    = raw_dynamic_set,
+               .rd_access              = raw_dynamic_rd_access,
+               .wr_access              = raw_dynamic_wr_access,
+               .load_all               = raw_dynamic_load_all,
+               .flush_all              = raw_dynamic_flush_all,
+               .flush_mark             = raw_dynamic_flush_mark,
+               .flush_do_asynch        = raw_dynamic_flush_do_asynch,
+       },
+       [metadata_raw_type_volatile] = {
+               .init                   = _raw_ram_init,
+               .deinit                 = _raw_ram_deinit,
+               .size_of                = _raw_ram_size_of,
+               .size_on_ssd            = raw_volatile_size_on_ssd,
+               .checksum               = raw_volatile_checksum,
+               .get                    = _raw_ram_get,
+               .set                    = _raw_ram_set,
+               .rd_access              = _raw_ram_rd_access,
+               .wr_access              = _raw_ram_wr_access,
+               .load_all               = raw_volatile_load_all,
+               .flush_all              = raw_volatile_flush_all,
+               .flush_mark             = raw_volatile_flush_mark,
+               .flush_do_asynch        = raw_volatile_flush_do_asynch,
+       },
+       [metadata_raw_type_atomic] = {
+               .init                   = _raw_ram_init,
+               .deinit                 = _raw_ram_deinit,
+               .size_of                = _raw_ram_size_of,
+               .size_on_ssd            = _raw_ram_size_on_ssd,
+               .checksum               = _raw_ram_checksum,
+               .get                    = _raw_ram_get,
+               .set                    = _raw_ram_set,
+               .rd_access              = _raw_ram_rd_access,
+               .wr_access              = _raw_ram_wr_access,
+               .load_all               = _raw_ram_load_all,
+               .flush_all              = _raw_ram_flush_all,
+               .flush_mark             = raw_atomic_flush_mark,
+               .flush_do_asynch        = raw_atomic_flush_do_asynch,
+       },
+};
+
+/*******************************************************************************
+ * RAW Top interface implementation
+ ******************************************************************************/
+
+int ocf_metadata_raw_init(ocf_cache_t cache,
+               struct ocf_metadata_raw *raw)
+{
+       ENV_BUG_ON(raw->raw_type < metadata_raw_type_min);
+       ENV_BUG_ON(raw->raw_type >= metadata_raw_type_max);
+
+       raw->iface = &(IRAW[raw->raw_type]);
+       return raw->iface->init(cache, raw);
+}
+
+int ocf_metadata_raw_deinit(ocf_cache_t cache,
+               struct ocf_metadata_raw *raw)
+{
+       int result;
+
+       if (!raw->iface)
+               return 0;
+
+       result = raw->iface->deinit(cache, raw);
+       raw->iface = NULL;
+
+       return result;
+}
+
+size_t ocf_metadata_raw_size_on_ssd(struct ocf_metadata_raw* raw)
+{
+       ENV_BUG_ON(raw->raw_type < metadata_raw_type_min);
+       ENV_BUG_ON(raw->raw_type >= metadata_raw_type_max);
+
+       return IRAW[raw->raw_type].size_on_ssd(raw);
+}