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