]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/nvme/nvme.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / lib / nvme / nvme.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation. All rights reserved.
5 * Copyright (c) 2020 Mellanox Technologies LTD. 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/nvmf_spec.h"
35 #include "spdk/string.h"
36 #include "nvme_internal.h"
37 #include "nvme_io_msg.h"
38 #include "nvme_uevent.h"
39
40 #define SPDK_NVME_DRIVER_NAME "spdk_nvme_driver"
41
42 struct nvme_driver *g_spdk_nvme_driver;
43 pid_t g_spdk_nvme_pid;
44
45 /* gross timeout of 180 seconds in milliseconds */
46 static int g_nvme_driver_timeout_ms = 3 * 60 * 1000;
47
48 /* Per-process attached controller list */
49 static TAILQ_HEAD(, spdk_nvme_ctrlr) g_nvme_attached_ctrlrs =
50 TAILQ_HEAD_INITIALIZER(g_nvme_attached_ctrlrs);
51
52 /* Returns true if ctrlr should be stored on the multi-process shared_attached_ctrlrs list */
53 static bool
54 nvme_ctrlr_shared(const struct spdk_nvme_ctrlr *ctrlr)
55 {
56 return ctrlr->trid.trtype == SPDK_NVME_TRANSPORT_PCIE;
57 }
58
59 void
60 nvme_ctrlr_connected(struct spdk_nvme_probe_ctx *probe_ctx,
61 struct spdk_nvme_ctrlr *ctrlr)
62 {
63 TAILQ_INSERT_TAIL(&probe_ctx->init_ctrlrs, ctrlr, tailq);
64 }
65
66 int
67 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
68 {
69 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
70
71 nvme_ctrlr_proc_put_ref(ctrlr);
72
73 if (nvme_ctrlr_get_ref_count(ctrlr) == 0) {
74 nvme_io_msg_ctrlr_detach(ctrlr);
75 if (nvme_ctrlr_shared(ctrlr)) {
76 TAILQ_REMOVE(&g_spdk_nvme_driver->shared_attached_ctrlrs, ctrlr, tailq);
77 } else {
78 TAILQ_REMOVE(&g_nvme_attached_ctrlrs, ctrlr, tailq);
79 }
80 nvme_ctrlr_destruct(ctrlr);
81 }
82
83 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
84 return 0;
85 }
86
87 void
88 nvme_completion_poll_cb(void *arg, const struct spdk_nvme_cpl *cpl)
89 {
90 struct nvme_completion_poll_status *status = arg;
91
92 if (status->timed_out) {
93 /* There is no routine waiting for the completion of this request, free allocated memory */
94 free(status);
95 return;
96 }
97
98 /*
99 * Copy status into the argument passed by the caller, so that
100 * the caller can check the status to determine if the
101 * the request passed or failed.
102 */
103 memcpy(&status->cpl, cpl, sizeof(*cpl));
104 status->done = true;
105 }
106
107 /**
108 * Poll qpair for completions until a command completes.
109 *
110 * \param qpair queue to poll
111 * \param status completion status. The user must fill this structure with zeroes before calling
112 * this function
113 * \param robust_mutex optional robust mutex to lock while polling qpair
114 *
115 * \return 0 if command completed without error,
116 * -EIO if command completed with error,
117 * -ECANCELED if command is not completed due to transport/device error
118 *
119 * The command to wait upon must be submitted with nvme_completion_poll_cb as the callback
120 * and status as the callback argument.
121 */
122 int
123 nvme_wait_for_completion_robust_lock(
124 struct spdk_nvme_qpair *qpair,
125 struct nvme_completion_poll_status *status,
126 pthread_mutex_t *robust_mutex)
127 {
128 int rc;
129
130 while (status->done == false) {
131 if (robust_mutex) {
132 nvme_robust_mutex_lock(robust_mutex);
133 }
134
135 rc = spdk_nvme_qpair_process_completions(qpair, 0);
136
137 if (robust_mutex) {
138 nvme_robust_mutex_unlock(robust_mutex);
139 }
140
141 if (rc < 0) {
142 status->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
143 status->cpl.status.sc = SPDK_NVME_SC_ABORTED_SQ_DELETION;
144 if (status->done == false) {
145 status->timed_out = true;
146 }
147 return -ECANCELED;
148 }
149 }
150
151 return spdk_nvme_cpl_is_error(&status->cpl) ? -EIO : 0;
152 }
153
154 int
155 nvme_wait_for_completion(struct spdk_nvme_qpair *qpair,
156 struct nvme_completion_poll_status *status)
157 {
158 return nvme_wait_for_completion_robust_lock(qpair, status, NULL);
159 }
160
161 /**
162 * Poll qpair for completions until a command completes.
163 *
164 * \param qpair queue to poll
165 * \param status completion status. The user must fill this structure with zeroes before calling
166 * this function
167 * \param timeout_in_secs optional timeout
168 *
169 * \return 0 if command completed without error,
170 * -EIO if command completed with error,
171 * -ECANCELED if command is not completed due to transport/device error or time expired
172 *
173 * The command to wait upon must be submitted with nvme_completion_poll_cb as the callback
174 * and status as the callback argument.
175 */
176 int
177 nvme_wait_for_completion_timeout(struct spdk_nvme_qpair *qpair,
178 struct nvme_completion_poll_status *status,
179 uint64_t timeout_in_secs)
180 {
181 uint64_t timeout_tsc = 0;
182 int rc = 0;
183
184 if (timeout_in_secs) {
185 timeout_tsc = spdk_get_ticks() + timeout_in_secs * spdk_get_ticks_hz();
186 }
187
188 while (status->done == false) {
189 rc = spdk_nvme_qpair_process_completions(qpair, 0);
190
191 if (rc < 0) {
192 status->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
193 status->cpl.status.sc = SPDK_NVME_SC_ABORTED_SQ_DELETION;
194 break;
195 }
196 if (timeout_tsc && spdk_get_ticks() > timeout_tsc) {
197 break;
198 }
199 }
200
201 if (status->done == false || rc < 0) {
202 if (status->done == false) {
203 status->timed_out = true;
204 }
205 return -ECANCELED;
206 }
207
208 return spdk_nvme_cpl_is_error(&status->cpl) ? -EIO : 0;
209 }
210
211 static void
212 nvme_user_copy_cmd_complete(void *arg, const struct spdk_nvme_cpl *cpl)
213 {
214 struct nvme_request *req = arg;
215 enum spdk_nvme_data_transfer xfer;
216
217 if (req->user_buffer && req->payload_size) {
218 /* Copy back to the user buffer and free the contig buffer */
219 assert(nvme_payload_type(&req->payload) == NVME_PAYLOAD_TYPE_CONTIG);
220 xfer = spdk_nvme_opc_get_data_transfer(req->cmd.opc);
221 if (xfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST ||
222 xfer == SPDK_NVME_DATA_BIDIRECTIONAL) {
223 assert(req->pid == getpid());
224 memcpy(req->user_buffer, req->payload.contig_or_cb_arg, req->payload_size);
225 }
226
227 spdk_free(req->payload.contig_or_cb_arg);
228 }
229
230 /* Call the user's original callback now that the buffer has been copied */
231 req->user_cb_fn(req->user_cb_arg, cpl);
232 }
233
234 /**
235 * Allocate a request as well as a DMA-capable buffer to copy to/from the user's buffer.
236 *
237 * This is intended for use in non-fast-path functions (admin commands, reservations, etc.)
238 * where the overhead of a copy is not a problem.
239 */
240 struct nvme_request *
241 nvme_allocate_request_user_copy(struct spdk_nvme_qpair *qpair,
242 void *buffer, uint32_t payload_size, spdk_nvme_cmd_cb cb_fn,
243 void *cb_arg, bool host_to_controller)
244 {
245 struct nvme_request *req;
246 void *dma_buffer = NULL;
247
248 if (buffer && payload_size) {
249 dma_buffer = spdk_zmalloc(payload_size, 4096, NULL,
250 SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_DMA);
251 if (!dma_buffer) {
252 return NULL;
253 }
254
255 if (host_to_controller) {
256 memcpy(dma_buffer, buffer, payload_size);
257 }
258 }
259
260 req = nvme_allocate_request_contig(qpair, dma_buffer, payload_size, nvme_user_copy_cmd_complete,
261 NULL);
262 if (!req) {
263 spdk_free(dma_buffer);
264 return NULL;
265 }
266
267 req->user_cb_fn = cb_fn;
268 req->user_cb_arg = cb_arg;
269 req->user_buffer = buffer;
270 req->cb_arg = req;
271
272 return req;
273 }
274
275 /**
276 * Check if a request has exceeded the controller timeout.
277 *
278 * \param req request to check for timeout.
279 * \param cid command ID for command submitted by req (will be passed to timeout_cb_fn)
280 * \param active_proc per-process data for the controller associated with req
281 * \param now_tick current time from spdk_get_ticks()
282 * \return 0 if requests submitted more recently than req should still be checked for timeouts, or
283 * 1 if requests newer than req need not be checked.
284 *
285 * The request's timeout callback will be called if needed; the caller is only responsible for
286 * calling this function on each outstanding request.
287 */
288 int
289 nvme_request_check_timeout(struct nvme_request *req, uint16_t cid,
290 struct spdk_nvme_ctrlr_process *active_proc,
291 uint64_t now_tick)
292 {
293 struct spdk_nvme_qpair *qpair = req->qpair;
294 struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
295
296 assert(active_proc->timeout_cb_fn != NULL);
297
298 if (req->timed_out || req->submit_tick == 0) {
299 return 0;
300 }
301
302 if (req->pid != g_spdk_nvme_pid) {
303 return 0;
304 }
305
306 if (nvme_qpair_is_admin_queue(qpair) &&
307 req->cmd.opc == SPDK_NVME_OPC_ASYNC_EVENT_REQUEST) {
308 return 0;
309 }
310
311 if (req->submit_tick + active_proc->timeout_ticks > now_tick) {
312 return 1;
313 }
314
315 req->timed_out = true;
316
317 /*
318 * We don't want to expose the admin queue to the user,
319 * so when we're timing out admin commands set the
320 * qpair to NULL.
321 */
322 active_proc->timeout_cb_fn(active_proc->timeout_cb_arg, ctrlr,
323 nvme_qpair_is_admin_queue(qpair) ? NULL : qpair,
324 cid);
325 return 0;
326 }
327
328 int
329 nvme_robust_mutex_init_shared(pthread_mutex_t *mtx)
330 {
331 int rc = 0;
332
333 #ifdef __FreeBSD__
334 pthread_mutex_init(mtx, NULL);
335 #else
336 pthread_mutexattr_t attr;
337
338 if (pthread_mutexattr_init(&attr)) {
339 return -1;
340 }
341 if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED) ||
342 pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST) ||
343 pthread_mutex_init(mtx, &attr)) {
344 rc = -1;
345 }
346 pthread_mutexattr_destroy(&attr);
347 #endif
348
349 return rc;
350 }
351
352 int
353 nvme_driver_init(void)
354 {
355 static pthread_mutex_t g_init_mutex = PTHREAD_MUTEX_INITIALIZER;
356 int ret = 0;
357 /* Any socket ID */
358 int socket_id = -1;
359
360 /* Use a special process-private mutex to ensure the global
361 * nvme driver object (g_spdk_nvme_driver) gets initialized by
362 * only one thread. Once that object is established and its
363 * mutex is initialized, we can unlock this mutex and use that
364 * one instead.
365 */
366 pthread_mutex_lock(&g_init_mutex);
367
368 /* Each process needs its own pid. */
369 g_spdk_nvme_pid = getpid();
370
371 /*
372 * Only one thread from one process will do this driver init work.
373 * The primary process will reserve the shared memory and do the
374 * initialization.
375 * The secondary process will lookup the existing reserved memory.
376 */
377 if (spdk_process_is_primary()) {
378 /* The unique named memzone already reserved. */
379 if (g_spdk_nvme_driver != NULL) {
380 pthread_mutex_unlock(&g_init_mutex);
381 return 0;
382 } else {
383 g_spdk_nvme_driver = spdk_memzone_reserve(SPDK_NVME_DRIVER_NAME,
384 sizeof(struct nvme_driver), socket_id,
385 SPDK_MEMZONE_NO_IOVA_CONTIG);
386 }
387
388 if (g_spdk_nvme_driver == NULL) {
389 SPDK_ERRLOG("primary process failed to reserve memory\n");
390 pthread_mutex_unlock(&g_init_mutex);
391 return -1;
392 }
393 } else {
394 g_spdk_nvme_driver = spdk_memzone_lookup(SPDK_NVME_DRIVER_NAME);
395
396 /* The unique named memzone already reserved by the primary process. */
397 if (g_spdk_nvme_driver != NULL) {
398 int ms_waited = 0;
399
400 /* Wait the nvme driver to get initialized. */
401 while ((g_spdk_nvme_driver->initialized == false) &&
402 (ms_waited < g_nvme_driver_timeout_ms)) {
403 ms_waited++;
404 nvme_delay(1000); /* delay 1ms */
405 }
406 if (g_spdk_nvme_driver->initialized == false) {
407 SPDK_ERRLOG("timeout waiting for primary process to init\n");
408 pthread_mutex_unlock(&g_init_mutex);
409 return -1;
410 }
411 } else {
412 SPDK_ERRLOG("primary process is not started yet\n");
413 pthread_mutex_unlock(&g_init_mutex);
414 return -1;
415 }
416
417 pthread_mutex_unlock(&g_init_mutex);
418 return 0;
419 }
420
421 /*
422 * At this moment, only one thread from the primary process will do
423 * the g_spdk_nvme_driver initialization
424 */
425 assert(spdk_process_is_primary());
426
427 ret = nvme_robust_mutex_init_shared(&g_spdk_nvme_driver->lock);
428 if (ret != 0) {
429 SPDK_ERRLOG("failed to initialize mutex\n");
430 spdk_memzone_free(SPDK_NVME_DRIVER_NAME);
431 pthread_mutex_unlock(&g_init_mutex);
432 return ret;
433 }
434
435 /* The lock in the shared g_spdk_nvme_driver object is now ready to
436 * be used - so we can unlock the g_init_mutex here.
437 */
438 pthread_mutex_unlock(&g_init_mutex);
439 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
440
441 g_spdk_nvme_driver->initialized = false;
442 g_spdk_nvme_driver->hotplug_fd = nvme_uevent_connect();
443 if (g_spdk_nvme_driver->hotplug_fd < 0) {
444 SPDK_DEBUGLOG(SPDK_LOG_NVME, "Failed to open uevent netlink socket\n");
445 }
446
447 TAILQ_INIT(&g_spdk_nvme_driver->shared_attached_ctrlrs);
448
449 spdk_uuid_generate(&g_spdk_nvme_driver->default_extended_host_id);
450
451 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
452
453 return ret;
454 }
455
456 /* This function must only be called while holding g_spdk_nvme_driver->lock */
457 int
458 nvme_ctrlr_probe(const struct spdk_nvme_transport_id *trid,
459 struct spdk_nvme_probe_ctx *probe_ctx, void *devhandle)
460 {
461 struct spdk_nvme_ctrlr *ctrlr;
462 struct spdk_nvme_ctrlr_opts opts;
463
464 assert(trid != NULL);
465
466 spdk_nvme_ctrlr_get_default_ctrlr_opts(&opts, sizeof(opts));
467
468 if (!probe_ctx->probe_cb || probe_ctx->probe_cb(probe_ctx->cb_ctx, trid, &opts)) {
469 ctrlr = nvme_get_ctrlr_by_trid_unsafe(trid);
470 if (ctrlr) {
471 /* This ctrlr already exists.
472 * Increase the ref count before calling attach_cb() as the user may
473 * call nvme_detach() immediately. */
474 nvme_ctrlr_proc_get_ref(ctrlr);
475
476 if (probe_ctx->attach_cb) {
477 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
478 probe_ctx->attach_cb(probe_ctx->cb_ctx, &ctrlr->trid, ctrlr, &ctrlr->opts);
479 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
480 }
481 return 0;
482 }
483
484 ctrlr = nvme_transport_ctrlr_construct(trid, &opts, devhandle);
485 if (ctrlr == NULL) {
486 SPDK_ERRLOG("Failed to construct NVMe controller for SSD: %s\n", trid->traddr);
487 return -1;
488 }
489 ctrlr->remove_cb = probe_ctx->remove_cb;
490 ctrlr->cb_ctx = probe_ctx->cb_ctx;
491
492 if (ctrlr->quirks & NVME_QUIRK_MINIMUM_IO_QUEUE_SIZE &&
493 ctrlr->opts.io_queue_size == DEFAULT_IO_QUEUE_SIZE) {
494 /* If the user specifically set an IO queue size different than the
495 * default, use that value. Otherwise overwrite with the quirked value.
496 * This allows this quirk to be overridden when necessary.
497 * However, cap.mqes still needs to be respected.
498 */
499 ctrlr->opts.io_queue_size = spdk_min(DEFAULT_IO_QUEUE_SIZE_FOR_QUIRK, ctrlr->cap.bits.mqes + 1u);
500 }
501
502 nvme_qpair_set_state(ctrlr->adminq, NVME_QPAIR_ENABLED);
503 TAILQ_INSERT_TAIL(&probe_ctx->init_ctrlrs, ctrlr, tailq);
504 return 0;
505 }
506
507 return 1;
508 }
509
510 static int
511 nvme_ctrlr_poll_internal(struct spdk_nvme_ctrlr *ctrlr,
512 struct spdk_nvme_probe_ctx *probe_ctx)
513 {
514 int rc = 0;
515
516 rc = nvme_ctrlr_process_init(ctrlr);
517
518 if (rc) {
519 /* Controller failed to initialize. */
520 TAILQ_REMOVE(&probe_ctx->init_ctrlrs, ctrlr, tailq);
521 SPDK_ERRLOG("Failed to initialize SSD: %s\n", ctrlr->trid.traddr);
522 nvme_ctrlr_fail(ctrlr, false);
523 nvme_ctrlr_destruct(ctrlr);
524 return rc;
525 }
526
527 if (ctrlr->state != NVME_CTRLR_STATE_READY) {
528 return 0;
529 }
530
531 STAILQ_INIT(&ctrlr->io_producers);
532
533 /*
534 * Controller has been initialized.
535 * Move it to the attached_ctrlrs list.
536 */
537 TAILQ_REMOVE(&probe_ctx->init_ctrlrs, ctrlr, tailq);
538
539 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
540 if (nvme_ctrlr_shared(ctrlr)) {
541 TAILQ_INSERT_TAIL(&g_spdk_nvme_driver->shared_attached_ctrlrs, ctrlr, tailq);
542 } else {
543 TAILQ_INSERT_TAIL(&g_nvme_attached_ctrlrs, ctrlr, tailq);
544 }
545
546 /*
547 * Increase the ref count before calling attach_cb() as the user may
548 * call nvme_detach() immediately.
549 */
550 nvme_ctrlr_proc_get_ref(ctrlr);
551 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
552
553 if (probe_ctx->attach_cb) {
554 probe_ctx->attach_cb(probe_ctx->cb_ctx, &ctrlr->trid, ctrlr, &ctrlr->opts);
555 return 0;
556 }
557
558 return 0;
559 }
560
561 static int
562 nvme_init_controllers(struct spdk_nvme_probe_ctx *probe_ctx)
563 {
564 int rc = 0;
565
566 while (true) {
567 rc = spdk_nvme_probe_poll_async(probe_ctx);
568 if (rc != -EAGAIN) {
569 return rc;
570 }
571 }
572
573 return rc;
574 }
575
576 /* This function must not be called while holding g_spdk_nvme_driver->lock */
577 static struct spdk_nvme_ctrlr *
578 nvme_get_ctrlr_by_trid(const struct spdk_nvme_transport_id *trid)
579 {
580 struct spdk_nvme_ctrlr *ctrlr;
581
582 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
583 ctrlr = nvme_get_ctrlr_by_trid_unsafe(trid);
584 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
585
586 return ctrlr;
587 }
588
589 /* This function must be called while holding g_spdk_nvme_driver->lock */
590 struct spdk_nvme_ctrlr *
591 nvme_get_ctrlr_by_trid_unsafe(const struct spdk_nvme_transport_id *trid)
592 {
593 struct spdk_nvme_ctrlr *ctrlr;
594
595 /* Search per-process list */
596 TAILQ_FOREACH(ctrlr, &g_nvme_attached_ctrlrs, tailq) {
597 if (spdk_nvme_transport_id_compare(&ctrlr->trid, trid) == 0) {
598 return ctrlr;
599 }
600 }
601
602 /* Search multi-process shared list */
603 TAILQ_FOREACH(ctrlr, &g_spdk_nvme_driver->shared_attached_ctrlrs, tailq) {
604 if (spdk_nvme_transport_id_compare(&ctrlr->trid, trid) == 0) {
605 return ctrlr;
606 }
607 }
608
609 return NULL;
610 }
611
612 /* This function must only be called while holding g_spdk_nvme_driver->lock */
613 static int
614 nvme_probe_internal(struct spdk_nvme_probe_ctx *probe_ctx,
615 bool direct_connect)
616 {
617 int rc;
618 struct spdk_nvme_ctrlr *ctrlr, *ctrlr_tmp;
619
620 spdk_nvme_trid_populate_transport(&probe_ctx->trid, probe_ctx->trid.trtype);
621 if (!spdk_nvme_transport_available_by_name(probe_ctx->trid.trstring)) {
622 SPDK_ERRLOG("NVMe trtype %u not available\n", probe_ctx->trid.trtype);
623 return -1;
624 }
625
626 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
627
628 rc = nvme_transport_ctrlr_scan(probe_ctx, direct_connect);
629 if (rc != 0) {
630 SPDK_ERRLOG("NVMe ctrlr scan failed\n");
631 TAILQ_FOREACH_SAFE(ctrlr, &probe_ctx->init_ctrlrs, tailq, ctrlr_tmp) {
632 TAILQ_REMOVE(&probe_ctx->init_ctrlrs, ctrlr, tailq);
633 nvme_transport_ctrlr_destruct(ctrlr);
634 }
635 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
636 return -1;
637 }
638
639 /*
640 * Probe controllers on the shared_attached_ctrlrs list
641 */
642 if (!spdk_process_is_primary() && (probe_ctx->trid.trtype == SPDK_NVME_TRANSPORT_PCIE)) {
643 TAILQ_FOREACH(ctrlr, &g_spdk_nvme_driver->shared_attached_ctrlrs, tailq) {
644 /* Do not attach other ctrlrs if user specify a valid trid */
645 if ((strlen(probe_ctx->trid.traddr) != 0) &&
646 (spdk_nvme_transport_id_compare(&probe_ctx->trid, &ctrlr->trid))) {
647 continue;
648 }
649
650 /* Do not attach if we failed to initialize it in this process */
651 if (nvme_ctrlr_get_current_process(ctrlr) == NULL) {
652 continue;
653 }
654
655 nvme_ctrlr_proc_get_ref(ctrlr);
656
657 /*
658 * Unlock while calling attach_cb() so the user can call other functions
659 * that may take the driver lock, like nvme_detach().
660 */
661 if (probe_ctx->attach_cb) {
662 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
663 probe_ctx->attach_cb(probe_ctx->cb_ctx, &ctrlr->trid, ctrlr, &ctrlr->opts);
664 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
665 }
666 }
667 }
668
669 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
670
671 return 0;
672 }
673
674 static void
675 nvme_probe_ctx_init(struct spdk_nvme_probe_ctx *probe_ctx,
676 const struct spdk_nvme_transport_id *trid,
677 void *cb_ctx,
678 spdk_nvme_probe_cb probe_cb,
679 spdk_nvme_attach_cb attach_cb,
680 spdk_nvme_remove_cb remove_cb)
681 {
682 probe_ctx->trid = *trid;
683 probe_ctx->cb_ctx = cb_ctx;
684 probe_ctx->probe_cb = probe_cb;
685 probe_ctx->attach_cb = attach_cb;
686 probe_ctx->remove_cb = remove_cb;
687 TAILQ_INIT(&probe_ctx->init_ctrlrs);
688 }
689
690 int
691 spdk_nvme_probe(const struct spdk_nvme_transport_id *trid, void *cb_ctx,
692 spdk_nvme_probe_cb probe_cb, spdk_nvme_attach_cb attach_cb,
693 spdk_nvme_remove_cb remove_cb)
694 {
695 struct spdk_nvme_transport_id trid_pcie;
696 struct spdk_nvme_probe_ctx *probe_ctx;
697
698 if (trid == NULL) {
699 memset(&trid_pcie, 0, sizeof(trid_pcie));
700 spdk_nvme_trid_populate_transport(&trid_pcie, SPDK_NVME_TRANSPORT_PCIE);
701 trid = &trid_pcie;
702 }
703
704 probe_ctx = spdk_nvme_probe_async(trid, cb_ctx, probe_cb,
705 attach_cb, remove_cb);
706 if (!probe_ctx) {
707 SPDK_ERRLOG("Create probe context failed\n");
708 return -1;
709 }
710
711 /*
712 * Keep going even if one or more nvme_attach() calls failed,
713 * but maintain the value of rc to signal errors when we return.
714 */
715 return nvme_init_controllers(probe_ctx);
716 }
717
718 static bool
719 nvme_connect_probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
720 struct spdk_nvme_ctrlr_opts *opts)
721 {
722 struct spdk_nvme_ctrlr_opts *requested_opts = cb_ctx;
723
724 assert(requested_opts);
725 memcpy(opts, requested_opts, sizeof(*opts));
726
727 return true;
728 }
729
730 static void
731 nvme_ctrlr_opts_init(struct spdk_nvme_ctrlr_opts *opts,
732 const struct spdk_nvme_ctrlr_opts *opts_user,
733 size_t opts_size_user)
734 {
735 assert(opts);
736 assert(opts_user);
737
738 spdk_nvme_ctrlr_get_default_ctrlr_opts(opts, opts_size_user);
739
740 #define FIELD_OK(field) \
741 offsetof(struct spdk_nvme_ctrlr_opts, field) + sizeof(opts->field) <= (opts->opts_size)
742
743 if (FIELD_OK(num_io_queues)) {
744 opts->num_io_queues = opts_user->num_io_queues;
745 }
746
747 if (FIELD_OK(use_cmb_sqs)) {
748 opts->use_cmb_sqs = opts_user->use_cmb_sqs;
749 }
750
751 if (FIELD_OK(no_shn_notification)) {
752 opts->no_shn_notification = opts_user->no_shn_notification;
753 }
754
755 if (FIELD_OK(arb_mechanism)) {
756 opts->arb_mechanism = opts_user->arb_mechanism;
757 }
758
759 if (FIELD_OK(arbitration_burst)) {
760 opts->arbitration_burst = opts_user->arbitration_burst;
761 }
762
763 if (FIELD_OK(low_priority_weight)) {
764 opts->low_priority_weight = opts_user->low_priority_weight;
765 }
766
767 if (FIELD_OK(medium_priority_weight)) {
768 opts->medium_priority_weight = opts_user->medium_priority_weight;
769 }
770
771 if (FIELD_OK(high_priority_weight)) {
772 opts->high_priority_weight = opts_user->high_priority_weight;
773 }
774
775 if (FIELD_OK(keep_alive_timeout_ms)) {
776 opts->keep_alive_timeout_ms = opts_user->keep_alive_timeout_ms;
777 }
778
779 if (FIELD_OK(transport_retry_count)) {
780 opts->transport_retry_count = opts_user->transport_retry_count;
781 }
782
783 if (FIELD_OK(io_queue_size)) {
784 opts->io_queue_size = opts_user->io_queue_size;
785 }
786
787 if (FIELD_OK(hostnqn)) {
788 memcpy(opts->hostnqn, opts_user->hostnqn, sizeof(opts_user->hostnqn));
789 }
790
791 if (FIELD_OK(io_queue_requests)) {
792 opts->io_queue_requests = opts_user->io_queue_requests;
793 }
794
795 if (FIELD_OK(src_addr)) {
796 memcpy(opts->src_addr, opts_user->src_addr, sizeof(opts_user->src_addr));
797 }
798
799 if (FIELD_OK(src_svcid)) {
800 memcpy(opts->src_svcid, opts_user->src_svcid, sizeof(opts_user->src_svcid));
801 }
802
803 if (FIELD_OK(host_id)) {
804 memcpy(opts->host_id, opts_user->host_id, sizeof(opts_user->host_id));
805 }
806 if (FIELD_OK(extended_host_id)) {
807 memcpy(opts->extended_host_id, opts_user->extended_host_id,
808 sizeof(opts_user->extended_host_id));
809 }
810
811 if (FIELD_OK(command_set)) {
812 opts->command_set = opts_user->command_set;
813 }
814
815 if (FIELD_OK(admin_timeout_ms)) {
816 opts->admin_timeout_ms = opts_user->admin_timeout_ms;
817 }
818
819 if (FIELD_OK(header_digest)) {
820 opts->header_digest = opts_user->header_digest;
821 }
822
823 if (FIELD_OK(data_digest)) {
824 opts->data_digest = opts_user->data_digest;
825 }
826
827 if (FIELD_OK(disable_error_logging)) {
828 opts->disable_error_logging = opts_user->disable_error_logging;
829 }
830
831 if (FIELD_OK(transport_ack_timeout)) {
832 opts->transport_ack_timeout = opts_user->transport_ack_timeout;
833 }
834
835 if (FIELD_OK(admin_queue_size)) {
836 opts->admin_queue_size = opts_user->admin_queue_size;
837 }
838 #undef FIELD_OK
839 }
840
841 struct spdk_nvme_ctrlr *
842 spdk_nvme_connect(const struct spdk_nvme_transport_id *trid,
843 const struct spdk_nvme_ctrlr_opts *opts, size_t opts_size)
844 {
845 int rc;
846 struct spdk_nvme_ctrlr *ctrlr = NULL;
847 struct spdk_nvme_probe_ctx *probe_ctx;
848 struct spdk_nvme_ctrlr_opts *opts_local_p = NULL;
849 struct spdk_nvme_ctrlr_opts opts_local;
850
851 if (trid == NULL) {
852 SPDK_ERRLOG("No transport ID specified\n");
853 return NULL;
854 }
855
856 if (opts) {
857 opts_local_p = &opts_local;
858 nvme_ctrlr_opts_init(opts_local_p, opts, opts_size);
859 }
860
861 probe_ctx = spdk_nvme_connect_async(trid, opts_local_p, NULL);
862 if (!probe_ctx) {
863 SPDK_ERRLOG("Create probe context failed\n");
864 return NULL;
865 }
866
867 rc = nvme_init_controllers(probe_ctx);
868 if (rc != 0) {
869 return NULL;
870 }
871
872 ctrlr = nvme_get_ctrlr_by_trid(trid);
873
874 return ctrlr;
875 }
876
877 void
878 spdk_nvme_trid_populate_transport(struct spdk_nvme_transport_id *trid,
879 enum spdk_nvme_transport_type trtype)
880 {
881 const char *trstring = "";
882
883 trid->trtype = trtype;
884 switch (trtype) {
885 case SPDK_NVME_TRANSPORT_FC:
886 trstring = SPDK_NVME_TRANSPORT_NAME_FC;
887 break;
888 case SPDK_NVME_TRANSPORT_PCIE:
889 trstring = SPDK_NVME_TRANSPORT_NAME_PCIE;
890 break;
891 case SPDK_NVME_TRANSPORT_RDMA:
892 trstring = SPDK_NVME_TRANSPORT_NAME_RDMA;
893 break;
894 case SPDK_NVME_TRANSPORT_TCP:
895 trstring = SPDK_NVME_TRANSPORT_NAME_TCP;
896 break;
897 case SPDK_NVME_TRANSPORT_CUSTOM:
898 default:
899 SPDK_ERRLOG("don't use this for custom transports\n");
900 assert(0);
901 return;
902 }
903 snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", trstring);
904 }
905
906 int
907 spdk_nvme_transport_id_populate_trstring(struct spdk_nvme_transport_id *trid, const char *trstring)
908 {
909 int len, i, rc;
910
911 if (trstring == NULL) {
912 return -EINVAL;
913 }
914
915 len = strnlen(trstring, SPDK_NVMF_TRSTRING_MAX_LEN);
916 if (len == SPDK_NVMF_TRSTRING_MAX_LEN) {
917 return -EINVAL;
918 }
919
920 rc = snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", trstring);
921 if (rc < 0) {
922 return rc;
923 }
924
925 /* cast official trstring to uppercase version of input. */
926 for (i = 0; i < len; i++) {
927 trid->trstring[i] = toupper(trid->trstring[i]);
928 }
929 return 0;
930 }
931
932 int
933 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
934 {
935 if (trtype == NULL || str == NULL) {
936 return -EINVAL;
937 }
938
939 if (strcasecmp(str, "PCIe") == 0) {
940 *trtype = SPDK_NVME_TRANSPORT_PCIE;
941 } else if (strcasecmp(str, "RDMA") == 0) {
942 *trtype = SPDK_NVME_TRANSPORT_RDMA;
943 } else if (strcasecmp(str, "FC") == 0) {
944 *trtype = SPDK_NVME_TRANSPORT_FC;
945 } else if (strcasecmp(str, "TCP") == 0) {
946 *trtype = SPDK_NVME_TRANSPORT_TCP;
947 } else {
948 *trtype = SPDK_NVME_TRANSPORT_CUSTOM;
949 }
950 return 0;
951 }
952
953 const char *
954 spdk_nvme_transport_id_trtype_str(enum spdk_nvme_transport_type trtype)
955 {
956 switch (trtype) {
957 case SPDK_NVME_TRANSPORT_PCIE:
958 return "PCIe";
959 case SPDK_NVME_TRANSPORT_RDMA:
960 return "RDMA";
961 case SPDK_NVME_TRANSPORT_FC:
962 return "FC";
963 case SPDK_NVME_TRANSPORT_TCP:
964 return "TCP";
965 case SPDK_NVME_TRANSPORT_CUSTOM:
966 return "CUSTOM";
967 default:
968 return NULL;
969 }
970 }
971
972 int
973 spdk_nvme_transport_id_parse_adrfam(enum spdk_nvmf_adrfam *adrfam, const char *str)
974 {
975 if (adrfam == NULL || str == NULL) {
976 return -EINVAL;
977 }
978
979 if (strcasecmp(str, "IPv4") == 0) {
980 *adrfam = SPDK_NVMF_ADRFAM_IPV4;
981 } else if (strcasecmp(str, "IPv6") == 0) {
982 *adrfam = SPDK_NVMF_ADRFAM_IPV6;
983 } else if (strcasecmp(str, "IB") == 0) {
984 *adrfam = SPDK_NVMF_ADRFAM_IB;
985 } else if (strcasecmp(str, "FC") == 0) {
986 *adrfam = SPDK_NVMF_ADRFAM_FC;
987 } else {
988 return -ENOENT;
989 }
990 return 0;
991 }
992
993 const char *
994 spdk_nvme_transport_id_adrfam_str(enum spdk_nvmf_adrfam adrfam)
995 {
996 switch (adrfam) {
997 case SPDK_NVMF_ADRFAM_IPV4:
998 return "IPv4";
999 case SPDK_NVMF_ADRFAM_IPV6:
1000 return "IPv6";
1001 case SPDK_NVMF_ADRFAM_IB:
1002 return "IB";
1003 case SPDK_NVMF_ADRFAM_FC:
1004 return "FC";
1005 default:
1006 return NULL;
1007 }
1008 }
1009
1010 static size_t
1011 parse_next_key(const char **str, char *key, char *val, size_t key_buf_size, size_t val_buf_size)
1012 {
1013
1014 const char *sep, *sep1;
1015 const char *whitespace = " \t\n";
1016 size_t key_len, val_len;
1017
1018 *str += strspn(*str, whitespace);
1019
1020 sep = strchr(*str, ':');
1021 if (!sep) {
1022 sep = strchr(*str, '=');
1023 if (!sep) {
1024 SPDK_ERRLOG("Key without ':' or '=' separator\n");
1025 return 0;
1026 }
1027 } else {
1028 sep1 = strchr(*str, '=');
1029 if ((sep1 != NULL) && (sep1 < sep)) {
1030 sep = sep1;
1031 }
1032 }
1033
1034 key_len = sep - *str;
1035 if (key_len >= key_buf_size) {
1036 SPDK_ERRLOG("Key length %zu greater than maximum allowed %zu\n",
1037 key_len, key_buf_size - 1);
1038 return 0;
1039 }
1040
1041 memcpy(key, *str, key_len);
1042 key[key_len] = '\0';
1043
1044 *str += key_len + 1; /* Skip key: */
1045 val_len = strcspn(*str, whitespace);
1046 if (val_len == 0) {
1047 SPDK_ERRLOG("Key without value\n");
1048 return 0;
1049 }
1050
1051 if (val_len >= val_buf_size) {
1052 SPDK_ERRLOG("Value length %zu greater than maximum allowed %zu\n",
1053 val_len, val_buf_size - 1);
1054 return 0;
1055 }
1056
1057 memcpy(val, *str, val_len);
1058 val[val_len] = '\0';
1059
1060 *str += val_len;
1061
1062 return val_len;
1063 }
1064
1065 int
1066 spdk_nvme_transport_id_parse(struct spdk_nvme_transport_id *trid, const char *str)
1067 {
1068 size_t val_len;
1069 char key[32];
1070 char val[1024];
1071
1072 if (trid == NULL || str == NULL) {
1073 return -EINVAL;
1074 }
1075
1076 while (*str != '\0') {
1077
1078 val_len = parse_next_key(&str, key, val, sizeof(key), sizeof(val));
1079
1080 if (val_len == 0) {
1081 SPDK_ERRLOG("Failed to parse transport ID\n");
1082 return -EINVAL;
1083 }
1084
1085 if (strcasecmp(key, "trtype") == 0) {
1086 if (spdk_nvme_transport_id_populate_trstring(trid, val) != 0) {
1087 SPDK_ERRLOG("invalid transport '%s'\n", val);
1088 return -EINVAL;
1089 }
1090 if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, val) != 0) {
1091 SPDK_ERRLOG("Unknown trtype '%s'\n", val);
1092 return -EINVAL;
1093 }
1094 } else if (strcasecmp(key, "adrfam") == 0) {
1095 if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, val) != 0) {
1096 SPDK_ERRLOG("Unknown adrfam '%s'\n", val);
1097 return -EINVAL;
1098 }
1099 } else if (strcasecmp(key, "traddr") == 0) {
1100 if (val_len > SPDK_NVMF_TRADDR_MAX_LEN) {
1101 SPDK_ERRLOG("traddr length %zu greater than maximum allowed %u\n",
1102 val_len, SPDK_NVMF_TRADDR_MAX_LEN);
1103 return -EINVAL;
1104 }
1105 memcpy(trid->traddr, val, val_len + 1);
1106 } else if (strcasecmp(key, "trsvcid") == 0) {
1107 if (val_len > SPDK_NVMF_TRSVCID_MAX_LEN) {
1108 SPDK_ERRLOG("trsvcid length %zu greater than maximum allowed %u\n",
1109 val_len, SPDK_NVMF_TRSVCID_MAX_LEN);
1110 return -EINVAL;
1111 }
1112 memcpy(trid->trsvcid, val, val_len + 1);
1113 } else if (strcasecmp(key, "priority") == 0) {
1114 if (val_len > SPDK_NVMF_PRIORITY_MAX_LEN) {
1115 SPDK_ERRLOG("priority length %zu greater than maximum allowed %u\n",
1116 val_len, SPDK_NVMF_PRIORITY_MAX_LEN);
1117 return -EINVAL;
1118 }
1119 trid->priority = spdk_strtol(val, 10);
1120 } else if (strcasecmp(key, "subnqn") == 0) {
1121 if (val_len > SPDK_NVMF_NQN_MAX_LEN) {
1122 SPDK_ERRLOG("subnqn length %zu greater than maximum allowed %u\n",
1123 val_len, SPDK_NVMF_NQN_MAX_LEN);
1124 return -EINVAL;
1125 }
1126 memcpy(trid->subnqn, val, val_len + 1);
1127 } else if (strcasecmp(key, "hostaddr") == 0) {
1128 continue;
1129 } else if (strcasecmp(key, "hostsvcid") == 0) {
1130 continue;
1131 } else if (strcasecmp(key, "ns") == 0) {
1132 /*
1133 * Special case. The namespace id parameter may
1134 * optionally be passed in the transport id string
1135 * for an SPDK application (e.g. nvme/perf)
1136 * and additionally parsed therein to limit
1137 * targeting a specific namespace. For this
1138 * scenario, just silently ignore this key
1139 * rather than letting it default to logging
1140 * it as an invalid key.
1141 */
1142 continue;
1143 } else if (strcasecmp(key, "alt_traddr") == 0) {
1144 /*
1145 * Used by applications for enabling transport ID failover.
1146 * Please see the case above for more information on custom parameters.
1147 */
1148 continue;
1149 } else {
1150 SPDK_ERRLOG("Unknown transport ID key '%s'\n", key);
1151 }
1152 }
1153
1154 return 0;
1155 }
1156
1157 int
1158 spdk_nvme_host_id_parse(struct spdk_nvme_host_id *hostid, const char *str)
1159 {
1160
1161 size_t key_size = 32;
1162 size_t val_size = 1024;
1163 size_t val_len;
1164 char key[key_size];
1165 char val[val_size];
1166
1167 if (hostid == NULL || str == NULL) {
1168 return -EINVAL;
1169 }
1170
1171 while (*str != '\0') {
1172
1173 val_len = parse_next_key(&str, key, val, key_size, val_size);
1174
1175 if (val_len == 0) {
1176 SPDK_ERRLOG("Failed to parse host ID\n");
1177 return val_len;
1178 }
1179
1180 /* Ignore the rest of the options from the transport ID. */
1181 if (strcasecmp(key, "trtype") == 0) {
1182 continue;
1183 } else if (strcasecmp(key, "adrfam") == 0) {
1184 continue;
1185 } else if (strcasecmp(key, "traddr") == 0) {
1186 continue;
1187 } else if (strcasecmp(key, "trsvcid") == 0) {
1188 continue;
1189 } else if (strcasecmp(key, "subnqn") == 0) {
1190 continue;
1191 } else if (strcasecmp(key, "priority") == 0) {
1192 continue;
1193 } else if (strcasecmp(key, "ns") == 0) {
1194 continue;
1195 } else if (strcasecmp(key, "hostaddr") == 0) {
1196 if (val_len > SPDK_NVMF_TRADDR_MAX_LEN) {
1197 SPDK_ERRLOG("hostaddr length %zu greater than maximum allowed %u\n",
1198 val_len, SPDK_NVMF_TRADDR_MAX_LEN);
1199 return -EINVAL;
1200 }
1201 memcpy(hostid->hostaddr, val, val_len + 1);
1202
1203 } else if (strcasecmp(key, "hostsvcid") == 0) {
1204 if (val_len > SPDK_NVMF_TRSVCID_MAX_LEN) {
1205 SPDK_ERRLOG("trsvcid length %zu greater than maximum allowed %u\n",
1206 val_len, SPDK_NVMF_TRSVCID_MAX_LEN);
1207 return -EINVAL;
1208 }
1209 memcpy(hostid->hostsvcid, val, val_len + 1);
1210 } else {
1211 SPDK_ERRLOG("Unknown transport ID key '%s'\n", key);
1212 }
1213 }
1214
1215 return 0;
1216 }
1217
1218 static int
1219 cmp_int(int a, int b)
1220 {
1221 return a - b;
1222 }
1223
1224 int
1225 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
1226 const struct spdk_nvme_transport_id *trid2)
1227 {
1228 int cmp;
1229
1230 if (trid1->trtype == SPDK_NVME_TRANSPORT_CUSTOM) {
1231 cmp = strcasecmp(trid1->trstring, trid2->trstring);
1232 } else {
1233 cmp = cmp_int(trid1->trtype, trid2->trtype);
1234 }
1235
1236 if (cmp) {
1237 return cmp;
1238 }
1239
1240 if (trid1->trtype == SPDK_NVME_TRANSPORT_PCIE) {
1241 struct spdk_pci_addr pci_addr1 = {};
1242 struct spdk_pci_addr pci_addr2 = {};
1243
1244 /* Normalize PCI addresses before comparing */
1245 if (spdk_pci_addr_parse(&pci_addr1, trid1->traddr) < 0 ||
1246 spdk_pci_addr_parse(&pci_addr2, trid2->traddr) < 0) {
1247 return -1;
1248 }
1249
1250 /* PCIe transport ID only uses trtype and traddr */
1251 return spdk_pci_addr_compare(&pci_addr1, &pci_addr2);
1252 }
1253
1254 cmp = strcasecmp(trid1->traddr, trid2->traddr);
1255 if (cmp) {
1256 return cmp;
1257 }
1258
1259 cmp = cmp_int(trid1->adrfam, trid2->adrfam);
1260 if (cmp) {
1261 return cmp;
1262 }
1263
1264 cmp = strcasecmp(trid1->trsvcid, trid2->trsvcid);
1265 if (cmp) {
1266 return cmp;
1267 }
1268
1269 cmp = strcmp(trid1->subnqn, trid2->subnqn);
1270 if (cmp) {
1271 return cmp;
1272 }
1273
1274 return 0;
1275 }
1276
1277 int
1278 spdk_nvme_prchk_flags_parse(uint32_t *prchk_flags, const char *str)
1279 {
1280 size_t val_len;
1281 char key[32];
1282 char val[1024];
1283
1284 if (prchk_flags == NULL || str == NULL) {
1285 return -EINVAL;
1286 }
1287
1288 while (*str != '\0') {
1289 val_len = parse_next_key(&str, key, val, sizeof(key), sizeof(val));
1290
1291 if (val_len == 0) {
1292 SPDK_ERRLOG("Failed to parse prchk\n");
1293 return -EINVAL;
1294 }
1295
1296 if (strcasecmp(key, "prchk") == 0) {
1297 if (strcasestr(val, "reftag") != NULL) {
1298 *prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG;
1299 }
1300 if (strcasestr(val, "guard") != NULL) {
1301 *prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD;
1302 }
1303 } else {
1304 SPDK_ERRLOG("Unknown key '%s'\n", key);
1305 return -EINVAL;
1306 }
1307 }
1308
1309 return 0;
1310 }
1311
1312 const char *
1313 spdk_nvme_prchk_flags_str(uint32_t prchk_flags)
1314 {
1315 if (prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_REFTAG) {
1316 if (prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_GUARD) {
1317 return "prchk:reftag|guard";
1318 } else {
1319 return "prchk:reftag";
1320 }
1321 } else {
1322 if (prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_GUARD) {
1323 return "prchk:guard";
1324 } else {
1325 return NULL;
1326 }
1327 }
1328 }
1329
1330 struct spdk_nvme_probe_ctx *
1331 spdk_nvme_probe_async(const struct spdk_nvme_transport_id *trid,
1332 void *cb_ctx,
1333 spdk_nvme_probe_cb probe_cb,
1334 spdk_nvme_attach_cb attach_cb,
1335 spdk_nvme_remove_cb remove_cb)
1336 {
1337 int rc;
1338 struct spdk_nvme_probe_ctx *probe_ctx;
1339
1340 rc = nvme_driver_init();
1341 if (rc != 0) {
1342 return NULL;
1343 }
1344
1345 probe_ctx = calloc(1, sizeof(*probe_ctx));
1346 if (!probe_ctx) {
1347 return NULL;
1348 }
1349
1350 nvme_probe_ctx_init(probe_ctx, trid, cb_ctx, probe_cb, attach_cb, remove_cb);
1351 rc = nvme_probe_internal(probe_ctx, false);
1352 if (rc != 0) {
1353 free(probe_ctx);
1354 return NULL;
1355 }
1356
1357 return probe_ctx;
1358 }
1359
1360 int
1361 spdk_nvme_probe_poll_async(struct spdk_nvme_probe_ctx *probe_ctx)
1362 {
1363 int rc = 0;
1364 struct spdk_nvme_ctrlr *ctrlr, *ctrlr_tmp;
1365
1366 if (!spdk_process_is_primary() && probe_ctx->trid.trtype == SPDK_NVME_TRANSPORT_PCIE) {
1367 free(probe_ctx);
1368 return 0;
1369 }
1370
1371 TAILQ_FOREACH_SAFE(ctrlr, &probe_ctx->init_ctrlrs, tailq, ctrlr_tmp) {
1372 rc = nvme_ctrlr_poll_internal(ctrlr, probe_ctx);
1373 if (rc != 0) {
1374 rc = -EIO;
1375 break;
1376 }
1377 }
1378
1379 if (rc != 0 || TAILQ_EMPTY(&probe_ctx->init_ctrlrs)) {
1380 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
1381 g_spdk_nvme_driver->initialized = true;
1382 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
1383 free(probe_ctx);
1384 return rc;
1385 }
1386
1387 return -EAGAIN;
1388 }
1389
1390 struct spdk_nvme_probe_ctx *
1391 spdk_nvme_connect_async(const struct spdk_nvme_transport_id *trid,
1392 const struct spdk_nvme_ctrlr_opts *opts,
1393 spdk_nvme_attach_cb attach_cb)
1394 {
1395 int rc;
1396 spdk_nvme_probe_cb probe_cb = NULL;
1397 struct spdk_nvme_probe_ctx *probe_ctx;
1398
1399 rc = nvme_driver_init();
1400 if (rc != 0) {
1401 return NULL;
1402 }
1403
1404 probe_ctx = calloc(1, sizeof(*probe_ctx));
1405 if (!probe_ctx) {
1406 return NULL;
1407 }
1408
1409 if (opts) {
1410 probe_cb = nvme_connect_probe_cb;
1411 }
1412
1413 nvme_probe_ctx_init(probe_ctx, trid, (void *)opts, probe_cb, attach_cb, NULL);
1414 rc = nvme_probe_internal(probe_ctx, true);
1415 if (rc != 0) {
1416 free(probe_ctx);
1417 return NULL;
1418 }
1419
1420 return probe_ctx;
1421 }
1422
1423 SPDK_LOG_REGISTER_COMPONENT("nvme", SPDK_LOG_NVME)