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