xref: /spdk/lib/ftl/ftl_init.c (revision c4acef02aa135112a727d8c233c770b1c99cd954)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (c) 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_zone.h"
15 #include "spdk/bdev_module.h"
16 #include "spdk/config.h"
17 
18 #include "ftl_core.h"
19 #include "ftl_io.h"
20 #include "ftl_debug.h"
21 #include "ftl_nv_cache.h"
22 #include "ftl_utils.h"
23 #include "mngt/ftl_mngt.h"
24 
25 struct ftl_dev_init_ctx {
26 	spdk_ftl_init_fn		cb_fn;
27 	/* Callback's argument */
28 	void				*cb_arg;
29 };
30 
31 struct ftl_dev_free_ctx {
32 	spdk_ftl_fn			cb_fn;
33 	/* Callback's argument */
34 	void				*cb_arg;
35 };
36 
37 static int
38 init_core_thread(struct spdk_ftl_dev *dev)
39 {
40 	struct spdk_cpuset cpumask = {};
41 
42 	/*
43 	 * If core mask is provided create core thread on first cpu that match with the mask,
44 	 * otherwise use current user thread
45 	 */
46 	if (dev->conf.core_mask) {
47 		if (spdk_cpuset_parse(&cpumask, dev->conf.core_mask)) {
48 			return -EINVAL;
49 		}
50 		dev->core_thread = spdk_thread_create("ftl_core_thread", &cpumask);
51 	} else {
52 		dev->core_thread = spdk_get_thread();
53 	}
54 
55 	if (dev->core_thread == NULL) {
56 		FTL_ERRLOG(dev, "Cannot create thread for mask %s\n", dev->conf.core_mask);
57 		return -ENOMEM;
58 	}
59 
60 	return 0;
61 }
62 
63 static void
64 exit_thread(void *ctx)
65 {
66 	struct spdk_thread *thread = ctx;
67 
68 	spdk_thread_exit(thread);
69 }
70 
71 static void
72 deinit_core_thread(struct spdk_ftl_dev *dev)
73 {
74 	if (dev->core_thread && dev->conf.core_mask) {
75 		spdk_thread_send_msg(dev->core_thread, exit_thread,
76 				     dev->core_thread);
77 		dev->core_thread = NULL;
78 	}
79 }
80 
81 static void
82 free_dev(struct spdk_ftl_dev *dev)
83 {
84 	if (!dev) {
85 		return;
86 	}
87 
88 	deinit_core_thread(dev);
89 	spdk_ftl_conf_deinit(&dev->conf);
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_conf_init_dev(dev, conf);
106 	if (rc) {
107 		*error = rc;
108 		goto error;
109 	}
110 
111 	rc = init_core_thread(dev);
112 	if (rc) {
113 		*error = rc;
114 		goto error;
115 	}
116 
117 	TAILQ_INIT(&dev->rd_sq);
118 	TAILQ_INIT(&dev->wr_sq);
119 	TAILQ_INIT(&dev->ioch_queue);
120 
121 	return dev;
122 error:
123 	free_dev(dev);
124 	return NULL;
125 }
126 
127 static void
128 dev_init_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
129 {
130 	struct ftl_dev_init_ctx *ctx = _ctx;
131 
132 	if (status) {
133 		free_dev(dev);
134 		dev = NULL;
135 	}
136 	ctx->cb_fn(dev, ctx->cb_arg, status);
137 	free(ctx);
138 }
139 
140 int
141 spdk_ftl_dev_init(const struct spdk_ftl_conf *conf, spdk_ftl_init_fn cb_fn, void *cb_arg)
142 {
143 	int rc = -1;
144 	struct ftl_dev_init_ctx *ctx;
145 	struct spdk_ftl_dev *dev = NULL;
146 
147 	ctx = calloc(1, sizeof(*ctx));
148 	if (!ctx) {
149 		rc = -ENOMEM;
150 		goto error;
151 	}
152 	ctx->cb_fn = cb_fn;
153 	ctx->cb_arg = cb_arg;
154 
155 	dev = allocate_dev(conf, &rc);
156 	if (!dev) {
157 		goto error;
158 	}
159 
160 	rc = ftl_mngt_call_dev_startup(dev, dev_init_cb, ctx);
161 	if (rc) {
162 		goto error;
163 	}
164 
165 	return 0;
166 
167 error:
168 	free(ctx);
169 	free_dev(dev);
170 	return rc;
171 }
172 
173 static void
174 dev_free_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
175 {
176 	struct ftl_dev_free_ctx *ctx = _ctx;
177 
178 	if (!status) {
179 		free_dev(dev);
180 	}
181 	ctx->cb_fn(ctx->cb_arg, status);
182 	free(ctx);
183 }
184 
185 int
186 spdk_ftl_dev_free(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg)
187 {
188 	int rc = -1;
189 	struct ftl_dev_free_ctx *ctx;
190 
191 	ctx = calloc(1, sizeof(*ctx));
192 	if (!ctx) {
193 		rc = -ENOMEM;
194 		goto error;
195 	}
196 	ctx->cb_fn = cb_fn;
197 	ctx->cb_arg = cb_arg;
198 
199 	rc = ftl_mngt_call_dev_shutdown(dev, dev_free_cb, ctx);
200 	if (rc) {
201 		goto error;
202 	}
203 
204 	return 0;
205 
206 error:
207 	free(ctx);
208 	return rc;
209 }
210 
211 SPDK_LOG_REGISTER_COMPONENT(ftl_init)
212