4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include "spdk/nvmf_spec.h"
35 #include "nvme_internal.h"
37 #define SPDK_NVME_DRIVER_NAME "spdk_nvme_driver"
39 struct nvme_driver
*g_spdk_nvme_driver
;
40 pid_t g_spdk_nvme_pid
;
42 int32_t spdk_nvme_retry_count
;
44 /* gross timeout of 180 seconds in milliseconds */
45 static int g_nvme_driver_timeout_ms
= 3 * 60 * 1000;
47 /* Per-process attached controller list */
48 static TAILQ_HEAD(, spdk_nvme_ctrlr
) g_nvme_attached_ctrlrs
=
49 TAILQ_HEAD_INITIALIZER(g_nvme_attached_ctrlrs
);
51 /* Returns true if ctrlr should be stored on the multi-process shared_attached_ctrlrs list */
53 nvme_ctrlr_shared(const struct spdk_nvme_ctrlr
*ctrlr
)
55 return ctrlr
->trid
.trtype
== SPDK_NVME_TRANSPORT_PCIE
;
59 nvme_ctrlr_connected(struct spdk_nvme_probe_ctx
*probe_ctx
,
60 struct spdk_nvme_ctrlr
*ctrlr
)
62 TAILQ_INSERT_TAIL(&probe_ctx
->init_ctrlrs
, ctrlr
, tailq
);
66 spdk_nvme_detach(struct spdk_nvme_ctrlr
*ctrlr
)
68 nvme_robust_mutex_lock(&g_spdk_nvme_driver
->lock
);
70 nvme_ctrlr_proc_put_ref(ctrlr
);
72 if (nvme_ctrlr_get_ref_count(ctrlr
) == 0) {
73 if (nvme_ctrlr_shared(ctrlr
)) {
74 TAILQ_REMOVE(&g_spdk_nvme_driver
->shared_attached_ctrlrs
, ctrlr
, tailq
);
76 TAILQ_REMOVE(&g_nvme_attached_ctrlrs
, ctrlr
, tailq
);
78 nvme_ctrlr_destruct(ctrlr
);
81 nvme_robust_mutex_unlock(&g_spdk_nvme_driver
->lock
);
86 nvme_completion_poll_cb(void *arg
, const struct spdk_nvme_cpl
*cpl
)
88 struct nvme_completion_poll_status
*status
= arg
;
91 * Copy status into the argument passed by the caller, so that
92 * the caller can check the status to determine if the
93 * the request passed or failed.
95 memcpy(&status
->cpl
, cpl
, sizeof(*cpl
));
100 * Poll qpair for completions until a command completes.
102 * \param qpair queue to poll
103 * \param status completion status
104 * \param robust_mutex optional robust mutex to lock while polling qpair
106 * \return 0 if command completed without error, negative errno on failure
108 * The command to wait upon must be submitted with nvme_completion_poll_cb as the callback
109 * and status as the callback argument.
112 spdk_nvme_wait_for_completion_robust_lock(
113 struct spdk_nvme_qpair
*qpair
,
114 struct nvme_completion_poll_status
*status
,
115 pthread_mutex_t
*robust_mutex
)
117 memset(&status
->cpl
, 0, sizeof(status
->cpl
));
118 status
->done
= false;
120 while (status
->done
== false) {
122 nvme_robust_mutex_lock(robust_mutex
);
125 spdk_nvme_qpair_process_completions(qpair
, 0);
128 nvme_robust_mutex_unlock(robust_mutex
);
132 return spdk_nvme_cpl_is_error(&status
->cpl
) ? -EIO
: 0;
136 spdk_nvme_wait_for_completion(struct spdk_nvme_qpair
*qpair
,
137 struct nvme_completion_poll_status
*status
)
139 return spdk_nvme_wait_for_completion_robust_lock(qpair
, status
, NULL
);
143 spdk_nvme_wait_for_completion_timeout(struct spdk_nvme_qpair
*qpair
,
144 struct nvme_completion_poll_status
*status
,
145 uint64_t timeout_in_secs
)
147 uint64_t timeout_tsc
= 0;
149 memset(&status
->cpl
, 0, sizeof(status
->cpl
));
150 status
->done
= false;
151 if (timeout_in_secs
) {
152 timeout_tsc
= spdk_get_ticks() + timeout_in_secs
* spdk_get_ticks_hz();
155 while (status
->done
== false) {
156 spdk_nvme_qpair_process_completions(qpair
, 0);
157 if (timeout_tsc
&& spdk_get_ticks() > timeout_tsc
) {
162 if (status
->done
== false) {
166 return spdk_nvme_cpl_is_error(&status
->cpl
) ? -EIO
: 0;
170 nvme_user_copy_cmd_complete(void *arg
, const struct spdk_nvme_cpl
*cpl
)
172 struct nvme_request
*req
= arg
;
173 enum spdk_nvme_data_transfer xfer
;
175 if (req
->user_buffer
&& req
->payload_size
) {
176 /* Copy back to the user buffer and free the contig buffer */
177 assert(nvme_payload_type(&req
->payload
) == NVME_PAYLOAD_TYPE_CONTIG
);
178 xfer
= spdk_nvme_opc_get_data_transfer(req
->cmd
.opc
);
179 if (xfer
== SPDK_NVME_DATA_CONTROLLER_TO_HOST
||
180 xfer
== SPDK_NVME_DATA_BIDIRECTIONAL
) {
181 assert(req
->pid
== getpid());
182 memcpy(req
->user_buffer
, req
->payload
.contig_or_cb_arg
, req
->payload_size
);
185 spdk_dma_free(req
->payload
.contig_or_cb_arg
);
188 /* Call the user's original callback now that the buffer has been copied */
189 req
->user_cb_fn(req
->user_cb_arg
, cpl
);
193 * Allocate a request as well as a DMA-capable buffer to copy to/from the user's buffer.
195 * This is intended for use in non-fast-path functions (admin commands, reservations, etc.)
196 * where the overhead of a copy is not a problem.
198 struct nvme_request
*
199 nvme_allocate_request_user_copy(struct spdk_nvme_qpair
*qpair
,
200 void *buffer
, uint32_t payload_size
, spdk_nvme_cmd_cb cb_fn
,
201 void *cb_arg
, bool host_to_controller
)
203 struct nvme_request
*req
;
204 void *dma_buffer
= NULL
;
206 if (buffer
&& payload_size
) {
207 dma_buffer
= spdk_zmalloc(payload_size
, 4096, NULL
,
208 SPDK_ENV_SOCKET_ID_ANY
, SPDK_MALLOC_DMA
);
213 if (host_to_controller
) {
214 memcpy(dma_buffer
, buffer
, payload_size
);
218 req
= nvme_allocate_request_contig(qpair
, dma_buffer
, payload_size
, nvme_user_copy_cmd_complete
,
221 spdk_free(dma_buffer
);
225 req
->user_cb_fn
= cb_fn
;
226 req
->user_cb_arg
= cb_arg
;
227 req
->user_buffer
= buffer
;
234 * Check if a request has exceeded the controller timeout.
236 * \param req request to check for timeout.
237 * \param cid command ID for command submitted by req (will be passed to timeout_cb_fn)
238 * \param active_proc per-process data for the controller associated with req
239 * \param now_tick current time from spdk_get_ticks()
240 * \return 0 if requests submitted more recently than req should still be checked for timeouts, or
241 * 1 if requests newer than req need not be checked.
243 * The request's timeout callback will be called if needed; the caller is only responsible for
244 * calling this function on each outstanding request.
247 nvme_request_check_timeout(struct nvme_request
*req
, uint16_t cid
,
248 struct spdk_nvme_ctrlr_process
*active_proc
,
251 struct spdk_nvme_qpair
*qpair
= req
->qpair
;
252 struct spdk_nvme_ctrlr
*ctrlr
= qpair
->ctrlr
;
254 assert(active_proc
->timeout_cb_fn
!= NULL
);
256 if (req
->timed_out
|| req
->submit_tick
== 0) {
260 if (req
->pid
!= g_spdk_nvme_pid
) {
264 if (nvme_qpair_is_admin_queue(qpair
) &&
265 req
->cmd
.opc
== SPDK_NVME_OPC_ASYNC_EVENT_REQUEST
) {
269 if (req
->submit_tick
+ active_proc
->timeout_ticks
> now_tick
) {
273 req
->timed_out
= true;
276 * We don't want to expose the admin queue to the user,
277 * so when we're timing out admin commands set the
280 active_proc
->timeout_cb_fn(active_proc
->timeout_cb_arg
, ctrlr
,
281 nvme_qpair_is_admin_queue(qpair
) ? NULL
: qpair
,
287 nvme_robust_mutex_init_shared(pthread_mutex_t
*mtx
)
292 pthread_mutex_init(mtx
, NULL
);
294 pthread_mutexattr_t attr
;
296 if (pthread_mutexattr_init(&attr
)) {
299 if (pthread_mutexattr_setpshared(&attr
, PTHREAD_PROCESS_SHARED
) ||
300 pthread_mutexattr_setrobust(&attr
, PTHREAD_MUTEX_ROBUST
) ||
301 pthread_mutex_init(mtx
, &attr
)) {
304 pthread_mutexattr_destroy(&attr
);
311 nvme_driver_init(void)
317 /* Each process needs its own pid. */
318 g_spdk_nvme_pid
= getpid();
321 * Only one thread from one process will do this driver init work.
322 * The primary process will reserve the shared memory and do the
324 * The secondary process will lookup the existing reserved memory.
326 if (spdk_process_is_primary()) {
327 /* The unique named memzone already reserved. */
328 if (g_spdk_nvme_driver
!= NULL
) {
331 g_spdk_nvme_driver
= spdk_memzone_reserve(SPDK_NVME_DRIVER_NAME
,
332 sizeof(struct nvme_driver
), socket_id
,
333 SPDK_MEMZONE_NO_IOVA_CONTIG
);
336 if (g_spdk_nvme_driver
== NULL
) {
337 SPDK_ERRLOG("primary process failed to reserve memory\n");
342 g_spdk_nvme_driver
= spdk_memzone_lookup(SPDK_NVME_DRIVER_NAME
);
344 /* The unique named memzone already reserved by the primary process. */
345 if (g_spdk_nvme_driver
!= NULL
) {
348 /* Wait the nvme driver to get initialized. */
349 while ((g_spdk_nvme_driver
->initialized
== false) &&
350 (ms_waited
< g_nvme_driver_timeout_ms
)) {
352 nvme_delay(1000); /* delay 1ms */
354 if (g_spdk_nvme_driver
->initialized
== false) {
355 SPDK_ERRLOG("timeout waiting for primary process to init\n");
360 SPDK_ERRLOG("primary process is not started yet\n");
369 * At this moment, only one thread from the primary process will do
370 * the g_spdk_nvme_driver initialization
372 assert(spdk_process_is_primary());
374 ret
= nvme_robust_mutex_init_shared(&g_spdk_nvme_driver
->lock
);
376 SPDK_ERRLOG("failed to initialize mutex\n");
377 spdk_memzone_free(SPDK_NVME_DRIVER_NAME
);
381 nvme_robust_mutex_lock(&g_spdk_nvme_driver
->lock
);
383 g_spdk_nvme_driver
->initialized
= false;
385 TAILQ_INIT(&g_spdk_nvme_driver
->shared_attached_ctrlrs
);
387 spdk_uuid_generate(&g_spdk_nvme_driver
->default_extended_host_id
);
389 nvme_robust_mutex_unlock(&g_spdk_nvme_driver
->lock
);
394 /* This function must only be called while holding g_spdk_nvme_driver->lock */
396 nvme_ctrlr_probe(const struct spdk_nvme_transport_id
*trid
,
397 struct spdk_nvme_probe_ctx
*probe_ctx
, void *devhandle
)
399 struct spdk_nvme_ctrlr
*ctrlr
;
400 struct spdk_nvme_ctrlr_opts opts
;
402 assert(trid
!= NULL
);
404 spdk_nvme_ctrlr_get_default_ctrlr_opts(&opts
, sizeof(opts
));
406 if (!probe_ctx
->probe_cb
|| probe_ctx
->probe_cb(probe_ctx
->cb_ctx
, trid
, &opts
)) {
407 ctrlr
= spdk_nvme_get_ctrlr_by_trid_unsafe(trid
);
409 /* This ctrlr already exists.
410 * Increase the ref count before calling attach_cb() as the user may
411 * call nvme_detach() immediately. */
412 nvme_ctrlr_proc_get_ref(ctrlr
);
414 if (probe_ctx
->attach_cb
) {
415 nvme_robust_mutex_unlock(&g_spdk_nvme_driver
->lock
);
416 probe_ctx
->attach_cb(probe_ctx
->cb_ctx
, &ctrlr
->trid
, ctrlr
, &ctrlr
->opts
);
417 nvme_robust_mutex_lock(&g_spdk_nvme_driver
->lock
);
422 ctrlr
= nvme_transport_ctrlr_construct(trid
, &opts
, devhandle
);
424 SPDK_ERRLOG("Failed to construct NVMe controller for SSD: %s\n", trid
->traddr
);
428 TAILQ_INSERT_TAIL(&probe_ctx
->init_ctrlrs
, ctrlr
, tailq
);
436 nvme_ctrlr_poll_internal(struct spdk_nvme_ctrlr
*ctrlr
,
437 struct spdk_nvme_probe_ctx
*probe_ctx
)
441 rc
= nvme_ctrlr_process_init(ctrlr
);
444 /* Controller failed to initialize. */
445 TAILQ_REMOVE(&probe_ctx
->init_ctrlrs
, ctrlr
, tailq
);
446 SPDK_ERRLOG("Failed to initialize SSD: %s\n", ctrlr
->trid
.traddr
);
447 nvme_ctrlr_destruct(ctrlr
);
451 if (ctrlr
->state
!= NVME_CTRLR_STATE_READY
) {
456 * Controller has been initialized.
457 * Move it to the attached_ctrlrs list.
459 TAILQ_REMOVE(&probe_ctx
->init_ctrlrs
, ctrlr
, tailq
);
461 nvme_robust_mutex_lock(&g_spdk_nvme_driver
->lock
);
462 if (nvme_ctrlr_shared(ctrlr
)) {
463 TAILQ_INSERT_TAIL(&g_spdk_nvme_driver
->shared_attached_ctrlrs
, ctrlr
, tailq
);
465 TAILQ_INSERT_TAIL(&g_nvme_attached_ctrlrs
, ctrlr
, tailq
);
469 * Increase the ref count before calling attach_cb() as the user may
470 * call nvme_detach() immediately.
472 nvme_ctrlr_proc_get_ref(ctrlr
);
473 nvme_robust_mutex_unlock(&g_spdk_nvme_driver
->lock
);
475 if (probe_ctx
->attach_cb
) {
476 probe_ctx
->attach_cb(probe_ctx
->cb_ctx
, &ctrlr
->trid
, ctrlr
, &ctrlr
->opts
);
484 nvme_init_controllers(struct spdk_nvme_probe_ctx
*probe_ctx
)
489 rc
= spdk_nvme_probe_poll_async(probe_ctx
);
498 /* This function must not be called while holding g_spdk_nvme_driver->lock */
499 static struct spdk_nvme_ctrlr
*
500 spdk_nvme_get_ctrlr_by_trid(const struct spdk_nvme_transport_id
*trid
)
502 struct spdk_nvme_ctrlr
*ctrlr
;
504 nvme_robust_mutex_lock(&g_spdk_nvme_driver
->lock
);
505 ctrlr
= spdk_nvme_get_ctrlr_by_trid_unsafe(trid
);
506 nvme_robust_mutex_unlock(&g_spdk_nvme_driver
->lock
);
511 /* This function must be called while holding g_spdk_nvme_driver->lock */
512 struct spdk_nvme_ctrlr
*
513 spdk_nvme_get_ctrlr_by_trid_unsafe(const struct spdk_nvme_transport_id
*trid
)
515 struct spdk_nvme_ctrlr
*ctrlr
;
517 /* Search per-process list */
518 TAILQ_FOREACH(ctrlr
, &g_nvme_attached_ctrlrs
, tailq
) {
519 if (spdk_nvme_transport_id_compare(&ctrlr
->trid
, trid
) == 0) {
524 /* Search multi-process shared list */
525 TAILQ_FOREACH(ctrlr
, &g_spdk_nvme_driver
->shared_attached_ctrlrs
, tailq
) {
526 if (spdk_nvme_transport_id_compare(&ctrlr
->trid
, trid
) == 0) {
534 /* This function must only be called while holding g_spdk_nvme_driver->lock */
536 spdk_nvme_probe_internal(struct spdk_nvme_probe_ctx
*probe_ctx
,
540 struct spdk_nvme_ctrlr
*ctrlr
;
542 if (!spdk_nvme_transport_available(probe_ctx
->trid
.trtype
)) {
543 SPDK_ERRLOG("NVMe trtype %u not available\n", probe_ctx
->trid
.trtype
);
547 nvme_robust_mutex_lock(&g_spdk_nvme_driver
->lock
);
549 rc
= nvme_transport_ctrlr_scan(probe_ctx
, direct_connect
);
551 SPDK_ERRLOG("NVMe ctrlr scan failed\n");
552 nvme_robust_mutex_unlock(&g_spdk_nvme_driver
->lock
);
557 * Probe controllers on the shared_attached_ctrlrs list
559 if (!spdk_process_is_primary() && (probe_ctx
->trid
.trtype
== SPDK_NVME_TRANSPORT_PCIE
)) {
560 TAILQ_FOREACH(ctrlr
, &g_spdk_nvme_driver
->shared_attached_ctrlrs
, tailq
) {
561 /* Do not attach other ctrlrs if user specify a valid trid */
562 if ((strlen(probe_ctx
->trid
.traddr
) != 0) &&
563 (spdk_nvme_transport_id_compare(&probe_ctx
->trid
, &ctrlr
->trid
))) {
567 /* Do not attach if we failed to initialize it in this process */
568 if (spdk_nvme_ctrlr_get_current_process(ctrlr
) == NULL
) {
572 nvme_ctrlr_proc_get_ref(ctrlr
);
575 * Unlock while calling attach_cb() so the user can call other functions
576 * that may take the driver lock, like nvme_detach().
578 if (probe_ctx
->attach_cb
) {
579 nvme_robust_mutex_unlock(&g_spdk_nvme_driver
->lock
);
580 probe_ctx
->attach_cb(probe_ctx
->cb_ctx
, &ctrlr
->trid
, ctrlr
, &ctrlr
->opts
);
581 nvme_robust_mutex_lock(&g_spdk_nvme_driver
->lock
);
586 nvme_robust_mutex_unlock(&g_spdk_nvme_driver
->lock
);
592 spdk_nvme_probe_ctx_init(struct spdk_nvme_probe_ctx
*probe_ctx
,
593 const struct spdk_nvme_transport_id
*trid
,
595 spdk_nvme_probe_cb probe_cb
,
596 spdk_nvme_attach_cb attach_cb
,
597 spdk_nvme_remove_cb remove_cb
)
599 probe_ctx
->trid
= *trid
;
600 probe_ctx
->cb_ctx
= cb_ctx
;
601 probe_ctx
->probe_cb
= probe_cb
;
602 probe_ctx
->attach_cb
= attach_cb
;
603 probe_ctx
->remove_cb
= remove_cb
;
604 TAILQ_INIT(&probe_ctx
->init_ctrlrs
);
608 spdk_nvme_probe(const struct spdk_nvme_transport_id
*trid
, void *cb_ctx
,
609 spdk_nvme_probe_cb probe_cb
, spdk_nvme_attach_cb attach_cb
,
610 spdk_nvme_remove_cb remove_cb
)
612 struct spdk_nvme_transport_id trid_pcie
;
613 struct spdk_nvme_probe_ctx
*probe_ctx
;
616 memset(&trid_pcie
, 0, sizeof(trid_pcie
));
617 trid_pcie
.trtype
= SPDK_NVME_TRANSPORT_PCIE
;
621 probe_ctx
= spdk_nvme_probe_async(trid
, cb_ctx
, probe_cb
,
622 attach_cb
, remove_cb
);
624 SPDK_ERRLOG("Create probe context failed\n");
629 * Keep going even if one or more nvme_attach() calls failed,
630 * but maintain the value of rc to signal errors when we return.
632 return nvme_init_controllers(probe_ctx
);
636 spdk_nvme_connect_probe_cb(void *cb_ctx
, const struct spdk_nvme_transport_id
*trid
,
637 struct spdk_nvme_ctrlr_opts
*opts
)
639 struct spdk_nvme_ctrlr_opts
*requested_opts
= cb_ctx
;
641 assert(requested_opts
);
642 memcpy(opts
, requested_opts
, sizeof(*opts
));
647 struct spdk_nvme_ctrlr
*
648 spdk_nvme_connect(const struct spdk_nvme_transport_id
*trid
,
649 const struct spdk_nvme_ctrlr_opts
*opts
, size_t opts_size
)
652 struct spdk_nvme_ctrlr
*ctrlr
= NULL
;
653 struct spdk_nvme_probe_ctx
*probe_ctx
;
656 SPDK_ERRLOG("No transport ID specified\n");
660 if (opts
&& (opts_size
!= sizeof(*opts
))) {
661 SPDK_ERRLOG("Invalid opts size\n");
665 probe_ctx
= spdk_nvme_connect_async(trid
, opts
, NULL
);
667 SPDK_ERRLOG("Create probe context failed\n");
671 rc
= nvme_init_controllers(probe_ctx
);
676 ctrlr
= spdk_nvme_get_ctrlr_by_trid(trid
);
682 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type
*trtype
, const char *str
)
684 if (trtype
== NULL
|| str
== NULL
) {
688 if (strcasecmp(str
, "PCIe") == 0) {
689 *trtype
= SPDK_NVME_TRANSPORT_PCIE
;
690 } else if (strcasecmp(str
, "RDMA") == 0) {
691 *trtype
= SPDK_NVME_TRANSPORT_RDMA
;
692 } else if (strcasecmp(str
, "FC") == 0) {
693 *trtype
= SPDK_NVME_TRANSPORT_FC
;
694 } else if (strcasecmp(str
, "TCP") == 0) {
695 *trtype
= SPDK_NVME_TRANSPORT_TCP
;
703 spdk_nvme_transport_id_trtype_str(enum spdk_nvme_transport_type trtype
)
706 case SPDK_NVME_TRANSPORT_PCIE
:
708 case SPDK_NVME_TRANSPORT_RDMA
:
710 case SPDK_NVME_TRANSPORT_FC
:
712 case SPDK_NVME_TRANSPORT_TCP
:
720 spdk_nvme_transport_id_parse_adrfam(enum spdk_nvmf_adrfam
*adrfam
, const char *str
)
722 if (adrfam
== NULL
|| str
== NULL
) {
726 if (strcasecmp(str
, "IPv4") == 0) {
727 *adrfam
= SPDK_NVMF_ADRFAM_IPV4
;
728 } else if (strcasecmp(str
, "IPv6") == 0) {
729 *adrfam
= SPDK_NVMF_ADRFAM_IPV6
;
730 } else if (strcasecmp(str
, "IB") == 0) {
731 *adrfam
= SPDK_NVMF_ADRFAM_IB
;
732 } else if (strcasecmp(str
, "FC") == 0) {
733 *adrfam
= SPDK_NVMF_ADRFAM_FC
;
741 spdk_nvme_transport_id_adrfam_str(enum spdk_nvmf_adrfam adrfam
)
744 case SPDK_NVMF_ADRFAM_IPV4
:
746 case SPDK_NVMF_ADRFAM_IPV6
:
748 case SPDK_NVMF_ADRFAM_IB
:
750 case SPDK_NVMF_ADRFAM_FC
:
758 parse_next_key(const char **str
, char *key
, char *val
, size_t key_buf_size
, size_t val_buf_size
)
761 const char *sep
, *sep1
;
762 const char *whitespace
= " \t\n";
763 size_t key_len
, val_len
;
765 *str
+= strspn(*str
, whitespace
);
767 sep
= strchr(*str
, ':');
769 sep
= strchr(*str
, '=');
771 SPDK_ERRLOG("Key without ':' or '=' separator\n");
775 sep1
= strchr(*str
, '=');
776 if ((sep1
!= NULL
) && (sep1
< sep
)) {
781 key_len
= sep
- *str
;
782 if (key_len
>= key_buf_size
) {
783 SPDK_ERRLOG("Key length %zu greater than maximum allowed %zu\n",
784 key_len
, key_buf_size
- 1);
788 memcpy(key
, *str
, key_len
);
791 *str
+= key_len
+ 1; /* Skip key: */
792 val_len
= strcspn(*str
, whitespace
);
794 SPDK_ERRLOG("Key without value\n");
798 if (val_len
>= val_buf_size
) {
799 SPDK_ERRLOG("Value length %zu greater than maximum allowed %zu\n",
800 val_len
, val_buf_size
- 1);
804 memcpy(val
, *str
, val_len
);
813 spdk_nvme_transport_id_parse(struct spdk_nvme_transport_id
*trid
, const char *str
)
819 if (trid
== NULL
|| str
== NULL
) {
823 while (*str
!= '\0') {
825 val_len
= parse_next_key(&str
, key
, val
, sizeof(key
), sizeof(val
));
828 SPDK_ERRLOG("Failed to parse transport ID\n");
832 if (strcasecmp(key
, "trtype") == 0) {
833 if (spdk_nvme_transport_id_parse_trtype(&trid
->trtype
, val
) != 0) {
834 SPDK_ERRLOG("Unknown trtype '%s'\n", val
);
837 } else if (strcasecmp(key
, "adrfam") == 0) {
838 if (spdk_nvme_transport_id_parse_adrfam(&trid
->adrfam
, val
) != 0) {
839 SPDK_ERRLOG("Unknown adrfam '%s'\n", val
);
842 } else if (strcasecmp(key
, "traddr") == 0) {
843 if (val_len
> SPDK_NVMF_TRADDR_MAX_LEN
) {
844 SPDK_ERRLOG("traddr length %zu greater than maximum allowed %u\n",
845 val_len
, SPDK_NVMF_TRADDR_MAX_LEN
);
848 memcpy(trid
->traddr
, val
, val_len
+ 1);
849 } else if (strcasecmp(key
, "trsvcid") == 0) {
850 if (val_len
> SPDK_NVMF_TRSVCID_MAX_LEN
) {
851 SPDK_ERRLOG("trsvcid length %zu greater than maximum allowed %u\n",
852 val_len
, SPDK_NVMF_TRSVCID_MAX_LEN
);
855 memcpy(trid
->trsvcid
, val
, val_len
+ 1);
856 } else if (strcasecmp(key
, "subnqn") == 0) {
857 if (val_len
> SPDK_NVMF_NQN_MAX_LEN
) {
858 SPDK_ERRLOG("subnqn length %zu greater than maximum allowed %u\n",
859 val_len
, SPDK_NVMF_NQN_MAX_LEN
);
862 memcpy(trid
->subnqn
, val
, val_len
+ 1);
863 } else if (strcasecmp(key
, "hostaddr") == 0) {
865 } else if (strcasecmp(key
, "hostsvcid") == 0) {
867 } else if (strcasecmp(key
, "ns") == 0) {
869 * Special case. The namespace id parameter may
870 * optionally be passed in the transport id string
871 * for an SPDK application (e.g. nvme/perf)
872 * and additionally parsed therein to limit
873 * targeting a specific namespace. For this
874 * scenario, just silently ignore this key
875 * rather than letting it default to logging
876 * it as an invalid key.
880 SPDK_ERRLOG("Unknown transport ID key '%s'\n", key
);
888 spdk_nvme_host_id_parse(struct spdk_nvme_host_id
*hostid
, const char *str
)
891 size_t key_size
= 32;
892 size_t val_size
= 1024;
897 if (hostid
== NULL
|| str
== NULL
) {
901 while (*str
!= '\0') {
903 val_len
= parse_next_key(&str
, key
, val
, key_size
, val_size
);
906 SPDK_ERRLOG("Failed to parse host ID\n");
910 /* Ignore the rest of the options from the transport ID. */
911 if (strcasecmp(key
, "trtype") == 0) {
913 } else if (strcasecmp(key
, "adrfam") == 0) {
915 } else if (strcasecmp(key
, "traddr") == 0) {
917 } else if (strcasecmp(key
, "trsvcid") == 0) {
919 } else if (strcasecmp(key
, "subnqn") == 0) {
921 } else if (strcasecmp(key
, "ns") == 0) {
923 } else if (strcasecmp(key
, "hostaddr") == 0) {
924 if (val_len
> SPDK_NVMF_TRADDR_MAX_LEN
) {
925 SPDK_ERRLOG("hostaddr length %zu greater than maximum allowed %u\n",
926 val_len
, SPDK_NVMF_TRADDR_MAX_LEN
);
929 memcpy(hostid
->hostaddr
, val
, val_len
+ 1);
931 } else if (strcasecmp(key
, "hostsvcid") == 0) {
932 if (val_len
> SPDK_NVMF_TRSVCID_MAX_LEN
) {
933 SPDK_ERRLOG("trsvcid length %zu greater than maximum allowed %u\n",
934 val_len
, SPDK_NVMF_TRSVCID_MAX_LEN
);
937 memcpy(hostid
->hostsvcid
, val
, val_len
+ 1);
939 SPDK_ERRLOG("Unknown transport ID key '%s'\n", key
);
947 cmp_int(int a
, int b
)
953 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id
*trid1
,
954 const struct spdk_nvme_transport_id
*trid2
)
958 cmp
= cmp_int(trid1
->trtype
, trid2
->trtype
);
963 if (trid1
->trtype
== SPDK_NVME_TRANSPORT_PCIE
) {
964 struct spdk_pci_addr pci_addr1
;
965 struct spdk_pci_addr pci_addr2
;
967 /* Normalize PCI addresses before comparing */
968 if (spdk_pci_addr_parse(&pci_addr1
, trid1
->traddr
) < 0 ||
969 spdk_pci_addr_parse(&pci_addr2
, trid2
->traddr
) < 0) {
973 /* PCIe transport ID only uses trtype and traddr */
974 return spdk_pci_addr_compare(&pci_addr1
, &pci_addr2
);
977 cmp
= strcasecmp(trid1
->traddr
, trid2
->traddr
);
982 cmp
= cmp_int(trid1
->adrfam
, trid2
->adrfam
);
987 cmp
= strcasecmp(trid1
->trsvcid
, trid2
->trsvcid
);
992 cmp
= strcmp(trid1
->subnqn
, trid2
->subnqn
);
1001 spdk_nvme_prchk_flags_parse(uint32_t *prchk_flags
, const char *str
)
1007 if (prchk_flags
== NULL
|| str
== NULL
) {
1011 while (*str
!= '\0') {
1012 val_len
= parse_next_key(&str
, key
, val
, sizeof(key
), sizeof(val
));
1015 SPDK_ERRLOG("Failed to parse prchk\n");
1019 if (strcasecmp(key
, "prchk") == 0) {
1020 if (strcasestr(val
, "reftag") != NULL
) {
1021 *prchk_flags
|= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG
;
1023 if (strcasestr(val
, "guard") != NULL
) {
1024 *prchk_flags
|= SPDK_NVME_IO_FLAGS_PRCHK_GUARD
;
1027 SPDK_ERRLOG("Unknown key '%s'\n", key
);
1036 spdk_nvme_prchk_flags_str(uint32_t prchk_flags
)
1038 if (prchk_flags
& SPDK_NVME_IO_FLAGS_PRCHK_REFTAG
) {
1039 if (prchk_flags
& SPDK_NVME_IO_FLAGS_PRCHK_GUARD
) {
1040 return "prchk:reftag|guard";
1042 return "prchk:reftag";
1045 if (prchk_flags
& SPDK_NVME_IO_FLAGS_PRCHK_GUARD
) {
1046 return "prchk:guard";
1053 struct spdk_nvme_probe_ctx
*
1054 spdk_nvme_probe_async(const struct spdk_nvme_transport_id
*trid
,
1056 spdk_nvme_probe_cb probe_cb
,
1057 spdk_nvme_attach_cb attach_cb
,
1058 spdk_nvme_remove_cb remove_cb
)
1061 struct spdk_nvme_probe_ctx
*probe_ctx
;
1063 rc
= nvme_driver_init();
1068 probe_ctx
= calloc(1, sizeof(*probe_ctx
));
1073 spdk_nvme_probe_ctx_init(probe_ctx
, trid
, cb_ctx
, probe_cb
, attach_cb
, remove_cb
);
1074 rc
= spdk_nvme_probe_internal(probe_ctx
, false);
1084 spdk_nvme_probe_poll_async(struct spdk_nvme_probe_ctx
*probe_ctx
)
1087 struct spdk_nvme_ctrlr
*ctrlr
, *ctrlr_tmp
;
1089 if (!spdk_process_is_primary() && probe_ctx
->trid
.trtype
== SPDK_NVME_TRANSPORT_PCIE
) {
1094 TAILQ_FOREACH_SAFE(ctrlr
, &probe_ctx
->init_ctrlrs
, tailq
, ctrlr_tmp
) {
1095 rc
= nvme_ctrlr_poll_internal(ctrlr
, probe_ctx
);
1102 if (rc
!= 0 || TAILQ_EMPTY(&probe_ctx
->init_ctrlrs
)) {
1103 nvme_robust_mutex_lock(&g_spdk_nvme_driver
->lock
);
1104 g_spdk_nvme_driver
->initialized
= true;
1105 nvme_robust_mutex_unlock(&g_spdk_nvme_driver
->lock
);
1113 struct spdk_nvme_probe_ctx
*
1114 spdk_nvme_connect_async(const struct spdk_nvme_transport_id
*trid
,
1115 const struct spdk_nvme_ctrlr_opts
*opts
,
1116 spdk_nvme_attach_cb attach_cb
)
1119 spdk_nvme_probe_cb probe_cb
= NULL
;
1120 struct spdk_nvme_probe_ctx
*probe_ctx
;
1122 rc
= nvme_driver_init();
1127 probe_ctx
= calloc(1, sizeof(*probe_ctx
));
1133 probe_cb
= spdk_nvme_connect_probe_cb
;
1136 spdk_nvme_probe_ctx_init(probe_ctx
, trid
, (void *)opts
, probe_cb
, attach_cb
, NULL
);
1137 rc
= spdk_nvme_probe_internal(probe_ctx
, true);
1146 SPDK_LOG_REGISTER_COMPONENT("nvme", SPDK_LOG_NVME
)