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