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