Branch data Line data Source code
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 : 22 : init_core_thread(struct spdk_ftl_dev *dev)
40 : : {
41 : 22 : 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 [ + + ]: 22 : if (dev->conf.core_mask) {
48 [ - + ]: 7 : if (spdk_cpuset_parse(&cpumask, dev->conf.core_mask)) {
49 : 0 : return -EINVAL;
50 : : }
51 : 7 : dev->core_thread = spdk_thread_create("ftl_core_thread", &cpumask);
52 : : } else {
53 : 15 : dev->core_thread = spdk_get_thread();
54 : : }
55 : :
56 [ - + ]: 22 : if (dev->core_thread == NULL) {
57 [ # # ]: 0 : FTL_ERRLOG(dev, "Cannot create thread for mask %s\n", dev->conf.core_mask);
58 : 0 : return -ENOMEM;
59 : : }
60 : :
61 : 22 : return 0;
62 : : }
63 : :
64 : : static void
65 : 7 : exit_thread(void *ctx)
66 : : {
67 : 7 : struct spdk_thread *thread = ctx;
68 : :
69 : 7 : spdk_thread_exit(thread);
70 : 7 : }
71 : :
72 : : static void
73 : 22 : deinit_core_thread(struct spdk_ftl_dev *dev)
74 : : {
75 [ + - + + ]: 22 : if (dev->core_thread && dev->conf.core_mask) {
76 : 7 : spdk_thread_send_msg(dev->core_thread, exit_thread,
77 : 7 : dev->core_thread);
78 : 7 : dev->core_thread = NULL;
79 : : }
80 : 22 : }
81 : :
82 : : static void
83 : 22 : free_dev(struct spdk_ftl_dev *dev)
84 : : {
85 [ - + ]: 22 : if (!dev) {
86 : 0 : return;
87 : : }
88 : :
89 : 22 : deinit_core_thread(dev);
90 : 22 : spdk_ftl_conf_deinit(&dev->conf);
91 : 22 : ftl_properties_deinit(dev);
92 : 22 : free(dev);
93 : : }
94 : :
95 : : static struct spdk_ftl_dev *
96 : 22 : allocate_dev(const struct spdk_ftl_conf *conf, int *error)
97 : : {
98 : : int rc;
99 : 22 : struct spdk_ftl_dev *dev = calloc(1, sizeof(*dev));
100 : :
101 [ - + ]: 22 : if (!dev) {
102 [ # # ]: 0 : FTL_ERRLOG(dev, "Cannot allocate FTL device\n");
103 : 0 : *error = -ENOMEM;
104 : 0 : return NULL;
105 : : }
106 : :
107 : 22 : rc = ftl_properties_init(dev);
108 [ - + ]: 22 : if (rc) {
109 : 0 : *error = rc;
110 : 0 : goto error;
111 : : }
112 : :
113 : 22 : rc = ftl_conf_init_dev(dev, conf);
114 [ - + ]: 22 : if (rc) {
115 : 0 : *error = rc;
116 : 0 : goto error;
117 : : }
118 : :
119 : 22 : rc = init_core_thread(dev);
120 [ - + ]: 22 : if (rc) {
121 : 0 : *error = rc;
122 : 0 : goto error;
123 : : }
124 : :
125 : 22 : TAILQ_INIT(&dev->rd_sq);
126 : 22 : TAILQ_INIT(&dev->wr_sq);
127 : 22 : TAILQ_INIT(&dev->unmap_sq);
128 : 22 : TAILQ_INIT(&dev->ioch_queue);
129 : :
130 : 22 : ftl_writer_init(dev, &dev->writer_user, SPDK_FTL_LIMIT_HIGH, FTL_BAND_TYPE_COMPACTION);
131 : 22 : ftl_writer_init(dev, &dev->writer_gc, SPDK_FTL_LIMIT_CRIT, FTL_BAND_TYPE_GC);
132 : :
133 : 22 : return dev;
134 : 0 : error:
135 : 0 : free_dev(dev);
136 : 0 : return NULL;
137 : : }
138 : :
139 : : static void
140 : 22 : dev_init_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
141 : : {
142 : 22 : struct ftl_dev_init_ctx *ctx = _ctx;
143 : : int rc;
144 : :
145 [ - + ]: 22 : if (status) {
146 [ # # # # ]: 0 : if (dev->init_retry) {
147 [ # # ]: 0 : FTL_NOTICELOG(dev, "Startup retry\n");
148 : 0 : rc = spdk_ftl_dev_init(&dev->conf, ctx->cb_fn, ctx->cb_arg);
149 [ # # ]: 0 : if (!rc) {
150 : 0 : free_dev(dev);
151 : 0 : free(ctx);
152 : 0 : return;
153 : : }
154 [ # # ]: 0 : FTL_NOTICELOG(dev, "Startup retry failed: %d\n", rc);
155 : : }
156 : :
157 : 0 : free_dev(dev);
158 : 0 : dev = NULL;
159 : : }
160 : 22 : ctx->cb_fn(dev, ctx->cb_arg, status);
161 : 22 : free(ctx);
162 : : }
163 : :
164 : : int
165 : 22 : spdk_ftl_dev_init(const struct spdk_ftl_conf *conf, spdk_ftl_init_fn cb_fn, void *cb_arg)
166 : : {
167 : 22 : int rc = -1;
168 : : struct ftl_dev_init_ctx *ctx;
169 : 22 : struct spdk_ftl_dev *dev = NULL;
170 : :
171 : 22 : ctx = calloc(1, sizeof(*ctx));
172 [ - + ]: 22 : if (!ctx) {
173 : 0 : rc = -ENOMEM;
174 : 0 : goto error;
175 : : }
176 : 22 : ctx->cb_fn = cb_fn;
177 : 22 : ctx->cb_arg = cb_arg;
178 : :
179 : 22 : dev = allocate_dev(conf, &rc);
180 [ - + ]: 22 : if (!dev) {
181 : 0 : goto error;
182 : : }
183 : :
184 : 22 : rc = ftl_mngt_call_dev_startup(dev, dev_init_cb, ctx);
185 [ - + ]: 22 : if (rc) {
186 : 0 : goto error;
187 : : }
188 : :
189 : 22 : return 0;
190 : :
191 : 0 : error:
192 : 0 : free(ctx);
193 : 0 : free_dev(dev);
194 : 0 : return rc;
195 : : }
196 : :
197 : : static void
198 : 22 : dev_free_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
199 : : {
200 : 22 : struct ftl_dev_free_ctx *ctx = _ctx;
201 : :
202 [ + - ]: 22 : if (!status) {
203 : 22 : free_dev(dev);
204 : : }
205 : 22 : ctx->cb_fn(ctx->cb_arg, status);
206 : 22 : free(ctx);
207 : 22 : }
208 : :
209 : : int
210 : 22 : spdk_ftl_dev_free(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg)
211 : : {
212 : 22 : int rc = -1;
213 : : struct ftl_dev_free_ctx *ctx;
214 : :
215 : 22 : ctx = calloc(1, sizeof(*ctx));
216 [ - + ]: 22 : if (!ctx) {
217 : 0 : rc = -ENOMEM;
218 : 0 : goto error;
219 : : }
220 : 22 : ctx->cb_fn = cb_fn;
221 : 22 : ctx->cb_arg = cb_arg;
222 : :
223 : 22 : rc = ftl_mngt_call_dev_shutdown(dev, dev_free_cb, ctx);
224 [ - + ]: 22 : if (rc) {
225 : 0 : goto error;
226 : : }
227 : :
228 : 22 : return 0;
229 : :
230 : 0 : error:
231 : 0 : free(ctx);
232 : 0 : return rc;
233 : : }
234 : :
235 : 1858 : SPDK_LOG_REGISTER_COMPONENT(ftl_init)
|