Spdk/lib/ftl/utils/ftl_conf.c
Kozlowski Mateusz 0e33da4974 ftl: fast shutdown
Adds API for fast shutdown - the ability for FTL to skip most
of the metadata persists made during clean shutdown, and relying
on their representation in shared memory instead. This allows for
faster update of SPDK (or just FTL, assuming no metadata changes),
with downtime reduction from 2-5 seconds to 500-1000 ms (for
14TiB+800GiB base and cache drives).

Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: Kozlowski Mateusz <mateusz.kozlowski@intel.com>
Change-Id: I5999d31698a81512db8d5893eabee7b505c80d06
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/13348
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>
2022-08-30 14:48:50 +00:00

141 lines
2.7 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) Intel Corporation.
* All rights reserved.
*/
#include "spdk/ftl.h"
#include "ftl_conf.h"
#include "ftl_core.h"
static const struct spdk_ftl_conf g_default_conf = {
/* 2 free bands - compaction is blocked, gc only */
.limits[SPDK_FTL_LIMIT_CRIT] = 2,
/* 3 free bands */
.limits[SPDK_FTL_LIMIT_HIGH] = 3,
/* 4 free bands */
.limits[SPDK_FTL_LIMIT_LOW] = 4,
/* 5 free bands - gc starts running */
.limits[SPDK_FTL_LIMIT_START] = 5,
/* 20% spare blocks */
.overprovisioning = 20,
/* IO pool size per user thread (this should be adjusted to thread IO qdepth) */
.user_io_pool_size = 2048,
.nv_cache = {
.chunk_compaction_threshold = 80,
},
.fast_shutdown = true,
};
void
spdk_ftl_get_default_conf(struct spdk_ftl_conf *conf)
{
*conf = g_default_conf;
}
void
spdk_ftl_dev_get_conf(const struct spdk_ftl_dev *dev, struct spdk_ftl_conf *conf)
{
*conf = dev->conf;
}
int
spdk_ftl_conf_copy(struct spdk_ftl_conf *dst, const struct spdk_ftl_conf *src)
{
char *name = NULL;
char *core_mask = NULL;
char *base_bdev = NULL;
char *cache_bdev = NULL;
if (src->name) {
name = strdup(src->name);
if (!name) {
goto error;
}
}
if (src->core_mask) {
core_mask = strdup(src->core_mask);
if (!core_mask) {
goto error;
}
}
if (src->base_bdev) {
base_bdev = strdup(src->base_bdev);
if (!base_bdev) {
goto error;
}
}
if (src->cache_bdev) {
cache_bdev = strdup(src->cache_bdev);
if (!cache_bdev) {
goto error;
}
}
*dst = *src;
dst->name = name;
dst->core_mask = core_mask;
dst->base_bdev = base_bdev;
dst->cache_bdev = cache_bdev;
return 0;
error:
free(name);
free(core_mask);
free(base_bdev);
free(cache_bdev);
return -ENOMEM;
}
void
spdk_ftl_conf_deinit(struct spdk_ftl_conf *conf)
{
free(conf->name);
free(conf->core_mask);
free(conf->base_bdev);
free(conf->cache_bdev);
}
int
ftl_conf_init_dev(struct spdk_ftl_dev *dev, const struct spdk_ftl_conf *conf)
{
int rc;
if (!conf->name) {
FTL_ERRLOG(dev, "No FTL name in configuration\n");
return -EINVAL;
}
if (!conf->base_bdev) {
FTL_ERRLOG(dev, "No base device in configuration\n");
return -EINVAL;
}
if (!conf->cache_bdev) {
FTL_ERRLOG(dev, "No NV cache device in configuration\n");
return -EINVAL;
}
rc = spdk_ftl_conf_copy(&dev->conf, conf);
if (rc) {
return rc;
}
dev->limit = SPDK_FTL_LIMIT_MAX;
return 0;
}
bool
ftl_conf_is_valid(const struct spdk_ftl_conf *conf)
{
if (conf->overprovisioning >= 100) {
return false;
}
if (conf->overprovisioning == 0) {
return false;
}
if (conf->nv_cache.chunk_compaction_threshold == 0 ||
conf->nv_cache.chunk_compaction_threshold > 100) {
return false;
}
return true;
}