xref: /spdk/lib/ftl/ftl_init.c (revision fa09c9ac9b0ce66dcacb64b02aae778014b6c2b3)
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_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 	free(dev);
90 }
91 
92 static struct spdk_ftl_dev *
93 allocate_dev(const struct spdk_ftl_conf *conf, int *error)
94 {
95 	int rc;
96 	struct spdk_ftl_dev *dev = calloc(1, sizeof(*dev));
97 
98 	if (!dev) {
99 		FTL_ERRLOG(dev, "Cannot allocate FTL device\n");
100 		*error = -ENOMEM;
101 		return NULL;
102 	}
103 
104 	rc = ftl_conf_init_dev(dev, conf);
105 	if (rc) {
106 		*error = rc;
107 		goto error;
108 	}
109 
110 	rc = init_core_thread(dev);
111 	if (rc) {
112 		*error = rc;
113 		goto error;
114 	}
115 
116 	TAILQ_INIT(&dev->rd_sq);
117 	TAILQ_INIT(&dev->wr_sq);
118 	TAILQ_INIT(&dev->ioch_queue);
119 
120 	return dev;
121 error:
122 	free_dev(dev);
123 	return NULL;
124 }
125 
126 static void
127 dev_init_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
128 {
129 	struct ftl_dev_init_ctx *ctx = _ctx;
130 
131 	if (status) {
132 		free_dev(dev);
133 		dev = NULL;
134 	}
135 	ctx->cb_fn(dev, ctx->cb_arg, status);
136 	free(ctx);
137 }
138 
139 int
140 spdk_ftl_dev_init(const struct spdk_ftl_conf *conf, spdk_ftl_init_fn cb_fn, void *cb_arg)
141 {
142 	int rc = -1;
143 	struct ftl_dev_init_ctx *ctx;
144 	struct spdk_ftl_dev *dev = NULL;
145 
146 	ctx = calloc(1, sizeof(*ctx));
147 	if (!ctx) {
148 		rc = -ENOMEM;
149 		goto error;
150 	}
151 	ctx->cb_fn = cb_fn;
152 	ctx->cb_arg = cb_arg;
153 
154 	dev = allocate_dev(conf, &rc);
155 	if (!dev) {
156 		goto error;
157 	}
158 
159 	rc = ftl_mngt_call_dev_startup(dev, dev_init_cb, ctx);
160 	if (rc) {
161 		goto error;
162 	}
163 
164 	return 0;
165 
166 error:
167 	free(ctx);
168 	free_dev(dev);
169 	return rc;
170 }
171 
172 static void
173 dev_free_cb(struct spdk_ftl_dev *dev, void *_ctx, int status)
174 {
175 	struct ftl_dev_free_ctx *ctx = _ctx;
176 
177 	if (!status) {
178 		free_dev(dev);
179 	}
180 	ctx->cb_fn(ctx->cb_arg, status);
181 	free(ctx);
182 }
183 
184 int
185 spdk_ftl_dev_free(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg)
186 {
187 	int rc = -1;
188 	struct ftl_dev_free_ctx *ctx;
189 
190 	ctx = calloc(1, sizeof(*ctx));
191 	if (!ctx) {
192 		rc = -ENOMEM;
193 		goto error;
194 	}
195 	ctx->cb_fn = cb_fn;
196 	ctx->cb_arg = cb_arg;
197 
198 	rc = ftl_mngt_call_dev_shutdown(dev, dev_free_cb, ctx);
199 	if (rc) {
200 		goto error;
201 	}
202 
203 	return 0;
204 
205 error:
206 	free(ctx);
207 	return rc;
208 }
209 
210 SPDK_LOG_REGISTER_COMPONENT(ftl_init)
211