1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2022 Intel Corporation.
3 * All rights reserved.
4 */
5
6 #include "spdk/ftl.h"
7
8 #include "ftl_conf.h"
9 #include "ftl_core.h"
10 #include "ftl_utils.h"
11
12 static const struct spdk_ftl_conf g_default_conf = {
13 /* 2 free bands - compaction is blocked, gc only */
14 .limits[SPDK_FTL_LIMIT_CRIT] = 2,
15 /* 3 free bands */
16 .limits[SPDK_FTL_LIMIT_HIGH] = 3,
17 /* 4 free bands */
18 .limits[SPDK_FTL_LIMIT_LOW] = 4,
19 /* 5 free bands - gc starts running */
20 .limits[SPDK_FTL_LIMIT_START] = 5,
21 /* 20% spare blocks */
22 .overprovisioning = 20,
23 /* 2GiB of DRAM for l2p cache */
24 .l2p_dram_limit = 2048,
25 /* IO pool size per user thread (this should be adjusted to thread IO qdepth) */
26 .user_io_pool_size = 2048,
27 .nv_cache = {
28 .chunk_compaction_threshold = 80,
29 .chunk_free_target = 5,
30 },
31 .fast_shutdown = true,
32 };
33
34 void
spdk_ftl_get_default_conf(struct spdk_ftl_conf * conf,size_t conf_size)35 spdk_ftl_get_default_conf(struct spdk_ftl_conf *conf, size_t conf_size)
36 {
37 assert(conf_size > 0);
38 assert(conf_size <= sizeof(struct spdk_ftl_conf));
39
40 memcpy(conf, &g_default_conf, conf_size);
41 conf->conf_size = conf_size;
42 }
43
44 void
spdk_ftl_dev_get_conf(const struct spdk_ftl_dev * dev,struct spdk_ftl_conf * conf,size_t conf_size)45 spdk_ftl_dev_get_conf(const struct spdk_ftl_dev *dev, struct spdk_ftl_conf *conf, size_t conf_size)
46 {
47 assert(conf_size > 0);
48 assert(conf_size <= sizeof(struct spdk_ftl_conf));
49
50 memcpy(conf, &dev->conf, conf_size);
51 conf->conf_size = conf_size;
52 }
53
54 int
spdk_ftl_conf_copy(struct spdk_ftl_conf * dst,const struct spdk_ftl_conf * src)55 spdk_ftl_conf_copy(struct spdk_ftl_conf *dst, const struct spdk_ftl_conf *src)
56 {
57 char *name = NULL;
58 char *core_mask = NULL;
59 char *base_bdev = NULL;
60 char *cache_bdev = NULL;
61
62 if (!src->conf_size || src->conf_size > sizeof(struct spdk_ftl_conf)) {
63 return -EINVAL;
64 }
65
66 if (src->name) {
67 name = strdup(src->name);
68 if (!name) {
69 goto error;
70 }
71 }
72 if (src->core_mask) {
73 core_mask = strdup(src->core_mask);
74 if (!core_mask) {
75 goto error;
76 }
77 }
78 if (src->base_bdev) {
79 base_bdev = strdup(src->base_bdev);
80 if (!base_bdev) {
81 goto error;
82 }
83 }
84 if (src->cache_bdev) {
85 cache_bdev = strdup(src->cache_bdev);
86 if (!cache_bdev) {
87 goto error;
88 }
89 }
90
91 memcpy(dst, src, src->conf_size);
92
93 dst->name = name;
94 dst->core_mask = core_mask;
95 dst->base_bdev = base_bdev;
96 dst->cache_bdev = cache_bdev;
97 return 0;
98 error:
99 free(name);
100 free(core_mask);
101 free(base_bdev);
102 free(cache_bdev);
103 return -ENOMEM;
104 }
105
106 void
spdk_ftl_conf_deinit(struct spdk_ftl_conf * conf)107 spdk_ftl_conf_deinit(struct spdk_ftl_conf *conf)
108 {
109 free(conf->name);
110 free(conf->core_mask);
111 free(conf->base_bdev);
112 free(conf->cache_bdev);
113 }
114
115 int
ftl_conf_init_dev(struct spdk_ftl_dev * dev,const struct spdk_ftl_conf * conf)116 ftl_conf_init_dev(struct spdk_ftl_dev *dev, const struct spdk_ftl_conf *conf)
117 {
118 int rc;
119
120 if (!conf->conf_size) {
121 FTL_ERRLOG(dev, "FTL configuration is uninitialized\n");
122 return -EINVAL;
123 }
124
125 if (!conf->name) {
126 FTL_ERRLOG(dev, "No FTL name in configuration\n");
127 return -EINVAL;
128 }
129 if (!conf->base_bdev) {
130 FTL_ERRLOG(dev, "No base device in configuration\n");
131 return -EINVAL;
132 }
133 if (!conf->cache_bdev) {
134 FTL_ERRLOG(dev, "No NV cache device in configuration\n");
135 return -EINVAL;
136 }
137
138 rc = spdk_ftl_conf_copy(&dev->conf, conf);
139 if (rc) {
140 return rc;
141 }
142
143 dev->limit = SPDK_FTL_LIMIT_MAX;
144
145 ftl_property_register_bool_rw(dev, "prep_upgrade_on_shutdown", &dev->conf.prep_upgrade_on_shutdown,
146 "", "During shutdown, FTL executes all actions which "
147 "are needed for upgrade to a new version", false);
148
149 ftl_property_register_bool_rw(dev, "verbose_mode", &dev->conf.verbose_mode,
150 "", "In verbose mode, user is able to get access to additional "
151 "advanced FTL properties", false);
152
153 return 0;
154 }
155
156 bool
ftl_conf_is_valid(const struct spdk_ftl_conf * conf)157 ftl_conf_is_valid(const struct spdk_ftl_conf *conf)
158 {
159 if (conf->overprovisioning >= 100) {
160 return false;
161 }
162 if (conf->overprovisioning == 0) {
163 return false;
164 }
165
166 if (conf->nv_cache.chunk_compaction_threshold == 0 ||
167 conf->nv_cache.chunk_compaction_threshold > 100) {
168 return false;
169 }
170
171 if (conf->nv_cache.chunk_free_target == 0 || conf->nv_cache.chunk_free_target > 100) {
172 return false;
173 }
174
175 if (conf->l2p_dram_limit == 0) {
176 return false;
177 }
178
179 return true;
180 }
181