1310836b9SArtur Paszkiewicz /* SPDX-License-Identifier: BSD-3-Clause
2a6dbe372Spaul luse * Copyright (C) 2022 Intel Corporation.
3310836b9SArtur Paszkiewicz * All rights reserved.
4310836b9SArtur Paszkiewicz */
5a6dbe372Spaul luse
6310836b9SArtur Paszkiewicz #include "spdk/ftl.h"
7310836b9SArtur Paszkiewicz
8310836b9SArtur Paszkiewicz #include "ftl_conf.h"
9310836b9SArtur Paszkiewicz #include "ftl_core.h"
10217332a9SMateusz Kozlowski #include "ftl_utils.h"
11310836b9SArtur Paszkiewicz
12e49ccfc8SArtur Paszkiewicz static const struct spdk_ftl_conf g_default_conf = {
130f99700dSArtur Paszkiewicz /* 2 free bands - compaction is blocked, gc only */
140f99700dSArtur Paszkiewicz .limits[SPDK_FTL_LIMIT_CRIT] = 2,
150f99700dSArtur Paszkiewicz /* 3 free bands */
160f99700dSArtur Paszkiewicz .limits[SPDK_FTL_LIMIT_HIGH] = 3,
170f99700dSArtur Paszkiewicz /* 4 free bands */
180f99700dSArtur Paszkiewicz .limits[SPDK_FTL_LIMIT_LOW] = 4,
190f99700dSArtur Paszkiewicz /* 5 free bands - gc starts running */
200f99700dSArtur Paszkiewicz .limits[SPDK_FTL_LIMIT_START] = 5,
21e49ccfc8SArtur Paszkiewicz /* 20% spare blocks */
22e49ccfc8SArtur Paszkiewicz .overprovisioning = 20,
23e7e5bc07SKozlowski Mateusz /* 2GiB of DRAM for l2p cache */
24e7e5bc07SKozlowski Mateusz .l2p_dram_limit = 2048,
25e49ccfc8SArtur Paszkiewicz /* IO pool size per user thread (this should be adjusted to thread IO qdepth) */
26e49ccfc8SArtur Paszkiewicz .user_io_pool_size = 2048,
2771f20c9aSKozlowski Mateusz .nv_cache = {
2871f20c9aSKozlowski Mateusz .chunk_compaction_threshold = 80,
2963b2fecbSArtur Paszkiewicz .chunk_free_target = 5,
3071f20c9aSKozlowski Mateusz },
310e33da49SKozlowski Mateusz .fast_shutdown = true,
32e49ccfc8SArtur Paszkiewicz };
33e49ccfc8SArtur Paszkiewicz
34e49ccfc8SArtur Paszkiewicz void
spdk_ftl_get_default_conf(struct spdk_ftl_conf * conf,size_t conf_size)35d1dd6ca8SArtur Paszkiewicz spdk_ftl_get_default_conf(struct spdk_ftl_conf *conf, size_t conf_size)
36e49ccfc8SArtur Paszkiewicz {
37d1dd6ca8SArtur Paszkiewicz assert(conf_size > 0);
38d1dd6ca8SArtur Paszkiewicz assert(conf_size <= sizeof(struct spdk_ftl_conf));
39d1dd6ca8SArtur Paszkiewicz
40d1dd6ca8SArtur Paszkiewicz memcpy(conf, &g_default_conf, conf_size);
41d1dd6ca8SArtur Paszkiewicz conf->conf_size = conf_size;
42e49ccfc8SArtur Paszkiewicz }
43e49ccfc8SArtur Paszkiewicz
44d974bad6SArtur Paszkiewicz void
spdk_ftl_dev_get_conf(const struct spdk_ftl_dev * dev,struct spdk_ftl_conf * conf,size_t conf_size)45d1dd6ca8SArtur Paszkiewicz spdk_ftl_dev_get_conf(const struct spdk_ftl_dev *dev, struct spdk_ftl_conf *conf, size_t conf_size)
46d974bad6SArtur Paszkiewicz {
47d1dd6ca8SArtur Paszkiewicz assert(conf_size > 0);
48d1dd6ca8SArtur Paszkiewicz assert(conf_size <= sizeof(struct spdk_ftl_conf));
49d1dd6ca8SArtur Paszkiewicz
50d1dd6ca8SArtur Paszkiewicz memcpy(conf, &dev->conf, conf_size);
51d1dd6ca8SArtur Paszkiewicz conf->conf_size = conf_size;
52d974bad6SArtur Paszkiewicz }
53d974bad6SArtur Paszkiewicz
54310836b9SArtur Paszkiewicz int
spdk_ftl_conf_copy(struct spdk_ftl_conf * dst,const struct spdk_ftl_conf * src)55c682c789SArtur Paszkiewicz spdk_ftl_conf_copy(struct spdk_ftl_conf *dst, const struct spdk_ftl_conf *src)
56310836b9SArtur Paszkiewicz {
57e49ccfc8SArtur Paszkiewicz char *name = NULL;
58310836b9SArtur Paszkiewicz char *core_mask = NULL;
59310836b9SArtur Paszkiewicz char *base_bdev = NULL;
60310836b9SArtur Paszkiewicz char *cache_bdev = NULL;
61310836b9SArtur Paszkiewicz
62d1dd6ca8SArtur Paszkiewicz if (!src->conf_size || src->conf_size > sizeof(struct spdk_ftl_conf)) {
63d1dd6ca8SArtur Paszkiewicz return -EINVAL;
64d1dd6ca8SArtur Paszkiewicz }
65d1dd6ca8SArtur Paszkiewicz
66e49ccfc8SArtur Paszkiewicz if (src->name) {
67e49ccfc8SArtur Paszkiewicz name = strdup(src->name);
68e49ccfc8SArtur Paszkiewicz if (!name) {
69e49ccfc8SArtur Paszkiewicz goto error;
70e49ccfc8SArtur Paszkiewicz }
71e49ccfc8SArtur Paszkiewicz }
72310836b9SArtur Paszkiewicz if (src->core_mask) {
73310836b9SArtur Paszkiewicz core_mask = strdup(src->core_mask);
74310836b9SArtur Paszkiewicz if (!core_mask) {
75310836b9SArtur Paszkiewicz goto error;
76310836b9SArtur Paszkiewicz }
77310836b9SArtur Paszkiewicz }
78310836b9SArtur Paszkiewicz if (src->base_bdev) {
79310836b9SArtur Paszkiewicz base_bdev = strdup(src->base_bdev);
80310836b9SArtur Paszkiewicz if (!base_bdev) {
81310836b9SArtur Paszkiewicz goto error;
82310836b9SArtur Paszkiewicz }
83310836b9SArtur Paszkiewicz }
84310836b9SArtur Paszkiewicz if (src->cache_bdev) {
85310836b9SArtur Paszkiewicz cache_bdev = strdup(src->cache_bdev);
86310836b9SArtur Paszkiewicz if (!cache_bdev) {
87310836b9SArtur Paszkiewicz goto error;
88310836b9SArtur Paszkiewicz }
89310836b9SArtur Paszkiewicz }
90310836b9SArtur Paszkiewicz
91d1dd6ca8SArtur Paszkiewicz memcpy(dst, src, src->conf_size);
92d1dd6ca8SArtur Paszkiewicz
93e49ccfc8SArtur Paszkiewicz dst->name = name;
94310836b9SArtur Paszkiewicz dst->core_mask = core_mask;
95310836b9SArtur Paszkiewicz dst->base_bdev = base_bdev;
96310836b9SArtur Paszkiewicz dst->cache_bdev = cache_bdev;
97310836b9SArtur Paszkiewicz return 0;
98310836b9SArtur Paszkiewicz error:
99e49ccfc8SArtur Paszkiewicz free(name);
100310836b9SArtur Paszkiewicz free(core_mask);
101310836b9SArtur Paszkiewicz free(base_bdev);
102310836b9SArtur Paszkiewicz free(cache_bdev);
103310836b9SArtur Paszkiewicz return -ENOMEM;
104310836b9SArtur Paszkiewicz }
105310836b9SArtur Paszkiewicz
106310836b9SArtur Paszkiewicz void
spdk_ftl_conf_deinit(struct spdk_ftl_conf * conf)107c682c789SArtur Paszkiewicz spdk_ftl_conf_deinit(struct spdk_ftl_conf *conf)
108310836b9SArtur Paszkiewicz {
109e49ccfc8SArtur Paszkiewicz free(conf->name);
110310836b9SArtur Paszkiewicz free(conf->core_mask);
111310836b9SArtur Paszkiewicz free(conf->base_bdev);
112310836b9SArtur Paszkiewicz free(conf->cache_bdev);
113310836b9SArtur Paszkiewicz }
114e49ccfc8SArtur Paszkiewicz
115e49ccfc8SArtur Paszkiewicz int
ftl_conf_init_dev(struct spdk_ftl_dev * dev,const struct spdk_ftl_conf * conf)116e49ccfc8SArtur Paszkiewicz ftl_conf_init_dev(struct spdk_ftl_dev *dev, const struct spdk_ftl_conf *conf)
117e49ccfc8SArtur Paszkiewicz {
118e49ccfc8SArtur Paszkiewicz int rc;
119e49ccfc8SArtur Paszkiewicz
120d1dd6ca8SArtur Paszkiewicz if (!conf->conf_size) {
121d1dd6ca8SArtur Paszkiewicz FTL_ERRLOG(dev, "FTL configuration is uninitialized\n");
122d1dd6ca8SArtur Paszkiewicz return -EINVAL;
123d1dd6ca8SArtur Paszkiewicz }
124d1dd6ca8SArtur Paszkiewicz
125e49ccfc8SArtur Paszkiewicz if (!conf->name) {
126e49ccfc8SArtur Paszkiewicz FTL_ERRLOG(dev, "No FTL name in configuration\n");
127e49ccfc8SArtur Paszkiewicz return -EINVAL;
128e49ccfc8SArtur Paszkiewicz }
129e49ccfc8SArtur Paszkiewicz if (!conf->base_bdev) {
130e49ccfc8SArtur Paszkiewicz FTL_ERRLOG(dev, "No base device in configuration\n");
131e49ccfc8SArtur Paszkiewicz return -EINVAL;
132e49ccfc8SArtur Paszkiewicz }
133e49ccfc8SArtur Paszkiewicz if (!conf->cache_bdev) {
134e49ccfc8SArtur Paszkiewicz FTL_ERRLOG(dev, "No NV cache device in configuration\n");
135e49ccfc8SArtur Paszkiewicz return -EINVAL;
136e49ccfc8SArtur Paszkiewicz }
137e49ccfc8SArtur Paszkiewicz
138c682c789SArtur Paszkiewicz rc = spdk_ftl_conf_copy(&dev->conf, conf);
139e49ccfc8SArtur Paszkiewicz if (rc) {
140e49ccfc8SArtur Paszkiewicz return rc;
141e49ccfc8SArtur Paszkiewicz }
142e49ccfc8SArtur Paszkiewicz
1430f99700dSArtur Paszkiewicz dev->limit = SPDK_FTL_LIMIT_MAX;
144217332a9SMateusz Kozlowski
145217332a9SMateusz Kozlowski ftl_property_register_bool_rw(dev, "prep_upgrade_on_shutdown", &dev->conf.prep_upgrade_on_shutdown,
146217332a9SMateusz Kozlowski "", "During shutdown, FTL executes all actions which "
147*ebcb0d71SMateusz Kozlowski "are needed for upgrade to a new version", false);
148*ebcb0d71SMateusz Kozlowski
149*ebcb0d71SMateusz Kozlowski ftl_property_register_bool_rw(dev, "verbose_mode", &dev->conf.verbose_mode,
150*ebcb0d71SMateusz Kozlowski "", "In verbose mode, user is able to get access to additional "
151*ebcb0d71SMateusz Kozlowski "advanced FTL properties", false);
152217332a9SMateusz Kozlowski
153e49ccfc8SArtur Paszkiewicz return 0;
154e49ccfc8SArtur Paszkiewicz }
155b872e29fSKozlowski Mateusz
156b872e29fSKozlowski Mateusz bool
ftl_conf_is_valid(const struct spdk_ftl_conf * conf)157b872e29fSKozlowski Mateusz ftl_conf_is_valid(const struct spdk_ftl_conf *conf)
158b872e29fSKozlowski Mateusz {
159b872e29fSKozlowski Mateusz if (conf->overprovisioning >= 100) {
160b872e29fSKozlowski Mateusz return false;
161b872e29fSKozlowski Mateusz }
162b872e29fSKozlowski Mateusz if (conf->overprovisioning == 0) {
163b872e29fSKozlowski Mateusz return false;
164b872e29fSKozlowski Mateusz }
165b872e29fSKozlowski Mateusz
16671f20c9aSKozlowski Mateusz if (conf->nv_cache.chunk_compaction_threshold == 0 ||
16771f20c9aSKozlowski Mateusz conf->nv_cache.chunk_compaction_threshold > 100) {
16871f20c9aSKozlowski Mateusz return false;
16971f20c9aSKozlowski Mateusz }
17071f20c9aSKozlowski Mateusz
17163b2fecbSArtur Paszkiewicz if (conf->nv_cache.chunk_free_target == 0 || conf->nv_cache.chunk_free_target > 100) {
17263b2fecbSArtur Paszkiewicz return false;
17363b2fecbSArtur Paszkiewicz }
17463b2fecbSArtur Paszkiewicz
175a7f4a2dbSKozlowski Mateusz if (conf->l2p_dram_limit == 0) {
176a7f4a2dbSKozlowski Mateusz return false;
177a7f4a2dbSKozlowski Mateusz }
178a7f4a2dbSKozlowski Mateusz
179b872e29fSKozlowski Mateusz return true;
180b872e29fSKozlowski Mateusz }
181