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