xref: /spdk/lib/nvmf/nvmf.c (revision eb8b1e20a9c8a6bc79f32fde8693d2791a74c34d)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #include "spdk/conf.h"
37 #include "spdk/io_channel.h"
38 #include "spdk/nvmf.h"
39 #include "spdk/trace.h"
40 
41 #include "spdk_internal/log.h"
42 
43 #include "nvmf_internal.h"
44 #include "transport.h"
45 
46 SPDK_LOG_REGISTER_TRACE_FLAG("nvmf", SPDK_TRACE_NVMF)
47 
48 #define MAX_SUBSYSTEMS 4
49 
50 #define SPDK_NVMF_DEFAULT_MAX_QUEUE_DEPTH 128
51 #define SPDK_NVMF_DEFAULT_MAX_QPAIRS_PER_CTRLR 64
52 #define SPDK_NVMF_DEFAULT_IN_CAPSULE_DATA_SIZE 4096
53 #define SPDK_NVMF_DEFAULT_MAX_IO_SIZE 131072
54 
55 void
56 spdk_nvmf_tgt_opts_init(struct spdk_nvmf_tgt_opts *opts)
57 {
58 	opts->max_queue_depth = SPDK_NVMF_DEFAULT_MAX_QUEUE_DEPTH;
59 	opts->max_qpairs_per_ctrlr = SPDK_NVMF_DEFAULT_MAX_QPAIRS_PER_CTRLR;
60 	opts->in_capsule_data_size = SPDK_NVMF_DEFAULT_IN_CAPSULE_DATA_SIZE;
61 	opts->max_io_size = SPDK_NVMF_DEFAULT_MAX_IO_SIZE;
62 }
63 
64 struct spdk_nvmf_tgt *
65 spdk_nvmf_tgt_create(struct spdk_nvmf_tgt_opts *opts)
66 {
67 	struct spdk_nvmf_tgt *tgt;
68 
69 	tgt = calloc(1, sizeof(*tgt));
70 	if (!tgt) {
71 		return NULL;
72 	}
73 
74 	if (!opts) {
75 		spdk_nvmf_tgt_opts_init(&tgt->opts);
76 	} else {
77 		tgt->opts = *opts;
78 	}
79 
80 	tgt->master_thread = spdk_get_thread();
81 	if (!tgt->master_thread) {
82 		free(tgt);
83 		SPDK_ERRLOG("Call spdk_allocate_thread() prior to calling spdk_nvmf_tgt_create()\n");
84 		return NULL;
85 	}
86 
87 	tgt->discovery_genctr = 0;
88 	tgt->discovery_log_page = NULL;
89 	tgt->discovery_log_page_size = 0;
90 	TAILQ_INIT(&tgt->subsystems);
91 	TAILQ_INIT(&tgt->transports);
92 
93 	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Max Queue Pairs Per Controller: %d\n",
94 		      tgt->opts.max_qpairs_per_ctrlr);
95 	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Max Queue Depth: %d\n", tgt->opts.max_queue_depth);
96 	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Max In Capsule Data: %d bytes\n",
97 		      tgt->opts.in_capsule_data_size);
98 	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Max I/O Size: %d bytes\n", tgt->opts.max_io_size);
99 
100 	return tgt;
101 }
102 
103 void
104 spdk_nvmf_tgt_destroy(struct spdk_nvmf_tgt *tgt)
105 {
106 	struct spdk_nvmf_transport *transport, *transport_tmp;
107 
108 	TAILQ_FOREACH_SAFE(transport, &tgt->transports, link, transport_tmp) {
109 		TAILQ_REMOVE(&tgt->transports, transport, link);
110 		spdk_nvmf_transport_destroy(transport);
111 	}
112 
113 	if (tgt->discovery_log_page) {
114 		free(tgt->discovery_log_page);
115 	}
116 	free(tgt);
117 }
118 
119 int
120 spdk_nvmf_tgt_listen(struct spdk_nvmf_tgt *tgt,
121 		     struct spdk_nvme_transport_id *trid)
122 {
123 	struct spdk_nvmf_transport *transport;
124 	int rc;
125 
126 	transport = spdk_nvmf_tgt_get_transport(tgt, trid->trtype);
127 	if (!transport) {
128 		transport = spdk_nvmf_transport_create(tgt, trid->trtype);
129 		if (!transport) {
130 			SPDK_ERRLOG("Transport initialization failed\n");
131 			return -EINVAL;
132 		}
133 		TAILQ_INSERT_TAIL(&tgt->transports, transport, link);
134 	}
135 
136 
137 	rc = spdk_nvmf_transport_listen(transport, trid);
138 	if (rc < 0) {
139 		SPDK_ERRLOG("Unable to listen on address '%s'\n", trid->traddr);
140 		return -EINVAL;
141 	}
142 
143 	tgt->discovery_genctr++;
144 
145 	return 0;
146 }
147 
148 struct spdk_nvmf_subsystem *
149 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
150 {
151 	struct spdk_nvmf_subsystem	*subsystem;
152 
153 	if (!subnqn) {
154 		return NULL;
155 	}
156 
157 	TAILQ_FOREACH(subsystem, &tgt->subsystems, entries) {
158 		if (strcmp(subnqn, subsystem->subnqn) == 0) {
159 			return subsystem;
160 		}
161 	}
162 
163 	return NULL;
164 }
165 
166 struct spdk_nvmf_transport *
167 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, enum spdk_nvme_transport_type type)
168 {
169 	struct spdk_nvmf_transport *transport;
170 
171 	TAILQ_FOREACH(transport, &tgt->transports, link) {
172 		if (transport->ops->type == type) {
173 			return transport;
174 		}
175 	}
176 
177 	return NULL;
178 }
179 
180 void
181 spdk_nvmf_tgt_accept(struct spdk_nvmf_tgt *tgt)
182 {
183 	struct spdk_nvmf_transport *transport, *tmp;
184 
185 	TAILQ_FOREACH_SAFE(transport, &tgt->transports, link, tmp) {
186 		spdk_nvmf_transport_accept(transport);
187 	}
188 }
189 
190 struct spdk_nvmf_poll_group *
191 spdk_nvmf_poll_group_create(struct spdk_nvmf_tgt *tgt)
192 {
193 	struct spdk_nvmf_poll_group *group;
194 	struct spdk_nvmf_transport *transport;
195 	struct spdk_nvmf_transport_poll_group *tgroup;
196 
197 	group = calloc(1, sizeof(*group));
198 	if (!group) {
199 		return NULL;
200 	}
201 
202 	TAILQ_INIT(&group->tgroups);
203 
204 	TAILQ_FOREACH(transport, &tgt->transports, link) {
205 		tgroup = spdk_nvmf_transport_poll_group_create(transport);
206 		if (!tgroup) {
207 			SPDK_ERRLOG("Unable to create poll group for transport\n");
208 			continue;
209 		}
210 
211 		TAILQ_INSERT_TAIL(&group->tgroups, tgroup, link);
212 	}
213 
214 	return group;
215 }
216 
217 void
218 spdk_nvmf_poll_group_destroy(struct spdk_nvmf_poll_group *group)
219 {
220 	struct spdk_nvmf_transport_poll_group *tgroup, *tmp;
221 
222 	TAILQ_FOREACH_SAFE(tgroup, &group->tgroups, link, tmp) {
223 		TAILQ_REMOVE(&group->tgroups, tgroup, link);
224 		spdk_nvmf_transport_poll_group_destroy(tgroup);
225 	}
226 
227 	free(group);
228 }
229 
230 int
231 spdk_nvmf_poll_group_add(struct spdk_nvmf_poll_group *group,
232 			 struct spdk_nvmf_qpair *qpair)
233 {
234 	int rc = -1;
235 	struct spdk_nvmf_transport_poll_group *tgroup;
236 
237 	TAILQ_FOREACH(tgroup, &group->tgroups, link) {
238 		if (tgroup->transport == qpair->transport) {
239 			rc = spdk_nvmf_transport_poll_group_add(tgroup, qpair);
240 			break;
241 		}
242 	}
243 
244 	return rc;
245 }
246 
247 int
248 spdk_nvmf_poll_group_remove(struct spdk_nvmf_poll_group *group,
249 			    struct spdk_nvmf_qpair *qpair)
250 {
251 	int rc = -1;
252 	struct spdk_nvmf_transport_poll_group *tgroup;
253 
254 	TAILQ_FOREACH(tgroup, &group->tgroups, link) {
255 		if (tgroup->transport == qpair->transport) {
256 			rc = spdk_nvmf_transport_poll_group_remove(tgroup, qpair);
257 			break;
258 		}
259 	}
260 
261 	return rc;
262 }
263 
264 int
265 spdk_nvmf_poll_group_poll(struct spdk_nvmf_poll_group *group)
266 {
267 	int rc;
268 	int count = 0;
269 	struct spdk_nvmf_transport_poll_group *tgroup;
270 
271 	TAILQ_FOREACH(tgroup, &group->tgroups, link) {
272 		rc = spdk_nvmf_transport_poll_group_poll(tgroup);
273 		if (rc < 0) {
274 			return rc;
275 		}
276 		count += rc;
277 		break;
278 	}
279 
280 	return count;
281 }
282 
283 SPDK_TRACE_REGISTER_FN(nvmf_trace)
284 {
285 	spdk_trace_register_object(OBJECT_NVMF_IO, 'r');
286 	spdk_trace_register_description("NVMF_IO_START", "", TRACE_NVMF_IO_START,
287 					OWNER_NONE, OBJECT_NVMF_IO, 1, 0, 0, "");
288 	spdk_trace_register_description("NVMF_RDMA_READ_START", "", TRACE_RDMA_READ_START,
289 					OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, "");
290 	spdk_trace_register_description("NVMF_RDMA_WRITE_START", "", TRACE_RDMA_WRITE_START,
291 					OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, "");
292 	spdk_trace_register_description("NVMF_RDMA_READ_COMPLETE", "", TRACE_RDMA_READ_COMPLETE,
293 					OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, "");
294 	spdk_trace_register_description("NVMF_RDMA_WRITE_COMPLETE", "", TRACE_RDMA_WRITE_COMPLETE,
295 					OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, "");
296 	spdk_trace_register_description("NVMF_LIB_READ_START", "", TRACE_NVMF_LIB_READ_START,
297 					OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, "");
298 	spdk_trace_register_description("NVMF_LIB_WRITE_START", "", TRACE_NVMF_LIB_WRITE_START,
299 					OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, "");
300 	spdk_trace_register_description("NVMF_LIB_COMPLETE", "", TRACE_NVMF_LIB_COMPLETE,
301 					OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, "");
302 	spdk_trace_register_description("NVMF_IO_COMPLETION_DONE", "", TRACE_NVMF_IO_COMPLETE,
303 					OWNER_NONE, OBJECT_NVMF_IO, 0, 0, 0, "");
304 }
305