xref: /spdk/lib/ftl/ftl_init.c (revision 95d6c9fac17572b107042103439aafd696d60b0e)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2018 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/stdinc.h"
7 #include "spdk/nvme.h"
8 #include "spdk/thread.h"
9 #include "spdk/string.h"
10 #include "spdk/likely.h"
11 #include "spdk/ftl.h"
12 #include "spdk/bdev_module.h"
13 #include "spdk/config.h"
14 
15 #include "ftl_core.h"
16 #include "ftl_io.h"
17 #include "ftl_band.h"
18 #include "ftl_debug.h"
19 #include "ftl_nv_cache.h"
20 #include "ftl_writer.h"
21 #include "ftl_utils.h"
22 #include "mngt/ftl_mngt.h"
23 
24 struct ftl_dev_init_ctx {
25 	spdk_ftl_init_fn		cb_fn;
26 	/* Callback's argument */
27 	void				*cb_arg;
28 };
29 
30 struct ftl_dev_free_ctx {
31 	spdk_ftl_fn			cb_fn;
32 	/* Callback's argument */
33 	void				*cb_arg;
34 };
35 
36 static int
37 init_core_thread(struct spdk_ftl_dev *dev)
38 {
39 	struct spdk_cpuset cpumask = {};
40 
41 	/*
42 	 * If core mask is provided create core thread on first cpu that match with the mask,
43 	 * otherwise use current user thread
44 	 */
45 	if (dev->conf.core_mask) {
46 		if (spdk_cpuset_parse(&cpumask, dev->conf.core_mask)) {
47 			return -EINVAL;
48 		}
49 		dev->core_thread = spdk_thread_create("ftl_core_thread", &cpumask);
50 	} else {
51 		dev->core_thread = spdk_get_thread();
52 	}
53 
54 	if (dev->core_thread == NULL) {
55 		FTL_ERRLOG(dev, "Cannot create thread for mask %s\n", dev->conf.core_mask);
56 		return -ENOMEM;
57 	}
58 
59 	return 0;
60 }
61 
62 static void
63 exit_thread(void *ctx)
64 {
65 	struct spdk_thread *thread = ctx;
66 
67 	spdk_thread_exit(thread);
68 }
69 
70 static void
71 deinit_core_thread(struct spdk_ftl_dev *dev)
72 {
73 	if (dev->core_thread && dev->conf.core_mask) {
74 		spdk_thread_send_msg(dev->core_thread, exit_thread,
75 				     dev->core_thread);
76 		dev->core_thread = NULL;
77 	}
78 }
79 
80 static void
81 free_dev(struct spdk_ftl_dev *dev)
82 {
83 	if (!dev) {
84 		return;
85 	}
86 
87 	deinit_core_thread(dev);
88 	spdk_ftl_conf_deinit(&dev->conf);
89 	ftl_properties_deinit(dev);
90 	free(dev);
91 }
92 
93 static struct spdk_ftl_dev *
94 allocate_dev(const struct spdk_ftl_conf *conf, int *error)
95 {
96 	int rc;
97 	struct spdk_ftl_dev *dev = calloc(1, sizeof(*dev));
98 
99 	if (!dev) {
100 		FTL_ERRLOG(dev, "Cannot allocate FTL device\n");
101 		*error = -ENOMEM;
102 		return NULL;
103 	}
104 
105 	rc = ftl_properties_init(dev);
106 	if (rc) {
107 		*error = rc;
108 		goto error;
109 	}
110 
111 	rc = ftl_conf_init_dev(dev, conf);
112 	if (rc) {
113 		*error = rc;
114 		goto error;
115 	}
116 
117 	rc = init_core_thread(dev);
118 	if (rc) {
119 		*error = rc;
120 		goto error;
121 	}
122 
123 	TAILQ_INIT(&dev->rd_sq);
124 	TAILQ_INIT(&dev->wr_sq);
125 	TAILQ_INIT(&dev->trim_sq);
126 	TAILQ_INIT(&dev->ioch_queue);
127 
128 	ftl_writer_init(dev, &dev->writer_user, SPDK_FTL_LIMIT_HIGH, FTL_BAND_TYPE_COMPACTION);
129 	ftl_writer_init(dev, &dev->writer_gc, SPDK_FTL_LIMIT_CRIT, FTL_BAND_TYPE_GC);
130 
131 	return dev;
132 error:
133 	free_dev(dev);
134 	return NULL;
135 }
136 
137 static void
138 dev_init_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
139 {
140 	struct ftl_dev_init_ctx *ctx = _ctx;
141 	int rc;
142 
143 	if (status) {
144 		if (dev->init_retry) {
145 			FTL_NOTICELOG(dev, "Startup retry\n");
146 			rc = spdk_ftl_dev_init(&dev->conf, ctx->cb_fn, ctx->cb_arg);
147 			if (!rc) {
148 				free_dev(dev);
149 				free(ctx);
150 				return;
151 			}
152 			FTL_NOTICELOG(dev, "Startup retry failed: %d\n", rc);
153 		}
154 
155 		free_dev(dev);
156 		dev = NULL;
157 	}
158 	ctx->cb_fn(dev, ctx->cb_arg, status);
159 	free(ctx);
160 }
161 
162 int
163 spdk_ftl_dev_init(const struct spdk_ftl_conf *conf, spdk_ftl_init_fn cb_fn, void *cb_arg)
164 {
165 	int rc = -1;
166 	struct ftl_dev_init_ctx *ctx;
167 	struct spdk_ftl_dev *dev = NULL;
168 
169 	ctx = calloc(1, sizeof(*ctx));
170 	if (!ctx) {
171 		rc = -ENOMEM;
172 		goto error;
173 	}
174 	ctx->cb_fn = cb_fn;
175 	ctx->cb_arg = cb_arg;
176 
177 	dev = allocate_dev(conf, &rc);
178 	if (!dev) {
179 		goto error;
180 	}
181 
182 	rc = ftl_mngt_call_dev_startup(dev, dev_init_cb, ctx);
183 	if (rc) {
184 		goto error;
185 	}
186 
187 	return 0;
188 
189 error:
190 	free(ctx);
191 	free_dev(dev);
192 	return rc;
193 }
194 
195 static void
196 dev_free_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
197 {
198 	struct ftl_dev_free_ctx *ctx = _ctx;
199 
200 	if (!status) {
201 		free_dev(dev);
202 	}
203 	ctx->cb_fn(ctx->cb_arg, status);
204 	free(ctx);
205 }
206 
207 int
208 spdk_ftl_dev_free(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg)
209 {
210 	int rc = -1;
211 	struct ftl_dev_free_ctx *ctx;
212 
213 	ctx = calloc(1, sizeof(*ctx));
214 	if (!ctx) {
215 		rc = -ENOMEM;
216 		goto error;
217 	}
218 	ctx->cb_fn = cb_fn;
219 	ctx->cb_arg = cb_arg;
220 
221 	rc = ftl_mngt_call_dev_shutdown(dev, dev_free_cb, ctx);
222 	if (rc) {
223 		goto error;
224 	}
225 
226 	return 0;
227 
228 error:
229 	free(ctx);
230 	return rc;
231 }
232 
233 SPDK_LOG_REGISTER_COMPONENT(ftl_init)
234