LCOV - code coverage report
Current view: top level - spdk/lib/nvme - nvme.c (source / functions) Hit Total Coverage
Test: Combined Lines: 790 888 89.0 %
Date: 2024-11-20 18:30:26 Functions: 54 55 98.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1133 2751 41.2 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2015 Intel Corporation. All rights reserved.
       3                 :            :  *   Copyright (c) 2020 Mellanox Technologies LTD. All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/config.h"
       7                 :            : #include "spdk/nvmf_spec.h"
       8                 :            : #include "spdk/string.h"
       9                 :            : #include "spdk/env.h"
      10                 :            : #include "nvme_internal.h"
      11                 :            : #include "nvme_io_msg.h"
      12                 :            : 
      13                 :            : #define SPDK_NVME_DRIVER_NAME "spdk_nvme_driver"
      14                 :            : 
      15                 :            : struct nvme_driver      *g_spdk_nvme_driver;
      16                 :            : pid_t                   g_spdk_nvme_pid;
      17                 :            : 
      18                 :            : /* gross timeout of 180 seconds in milliseconds */
      19                 :            : static int g_nvme_driver_timeout_ms = 3 * 60 * 1000;
      20                 :            : 
      21                 :            : /* Per-process attached controller list */
      22                 :            : static TAILQ_HEAD(, spdk_nvme_ctrlr) g_nvme_attached_ctrlrs =
      23                 :            :         TAILQ_HEAD_INITIALIZER(g_nvme_attached_ctrlrs);
      24                 :            : 
      25                 :            : /* Returns true if ctrlr should be stored on the multi-process shared_attached_ctrlrs list */
      26                 :            : static bool
      27                 :       6273 : nvme_ctrlr_shared(const struct spdk_nvme_ctrlr *ctrlr)
      28                 :            : {
      29   [ +  -  +  -  :       6273 :         return ctrlr->trid.trtype == SPDK_NVME_TRANSPORT_PCIE;
                   +  - ]
      30                 :            : }
      31                 :            : 
      32                 :            : void
      33                 :         41 : nvme_ctrlr_connected(struct spdk_nvme_probe_ctx *probe_ctx,
      34                 :            :                      struct spdk_nvme_ctrlr *ctrlr)
      35                 :            : {
      36   [ #  #  #  #  :         41 :         TAILQ_INSERT_TAIL(&probe_ctx->init_ctrlrs, ctrlr, tailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
      37                 :         41 : }
      38                 :            : 
      39                 :            : static void
      40                 :       3150 : nvme_ctrlr_detach_async_finish(struct spdk_nvme_ctrlr *ctrlr)
      41                 :            : {
      42         [ +  - ]:       3150 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
      43         [ +  + ]:       3150 :         if (nvme_ctrlr_shared(ctrlr)) {
      44   [ +  +  +  -  :        739 :                 TAILQ_REMOVE(&g_spdk_nvme_driver->shared_attached_ctrlrs, ctrlr, tailq);
          +  -  +  -  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
      45                 :         37 :         } else {
      46   [ +  +  +  -  :       2411 :                 TAILQ_REMOVE(&g_nvme_attached_ctrlrs, ctrlr, tailq);
          +  -  +  -  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
      47                 :            :         }
      48         [ +  - ]:       3150 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
      49                 :       3150 : }
      50                 :            : 
      51                 :            : static int
      52                 :       3379 : nvme_ctrlr_detach_async(struct spdk_nvme_ctrlr *ctrlr,
      53                 :            :                         struct nvme_ctrlr_detach_ctx **_ctx)
      54                 :            : {
      55                 :            :         struct nvme_ctrlr_detach_ctx *ctx;
      56                 :            :         int ref_count;
      57                 :            : 
      58         [ +  - ]:       3379 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
      59                 :            : 
      60                 :       3379 :         ref_count = nvme_ctrlr_get_ref_count(ctrlr);
      61   [ +  +  #  # ]:       3379 :         assert(ref_count > 0);
      62                 :            : 
      63         [ +  + ]:       3379 :         if (ref_count == 1) {
      64                 :            :                 /* This is the last reference to the controller, so we need to
      65                 :            :                  * allocate a context to destruct it.
      66                 :            :                  */
      67                 :       3150 :                 ctx = calloc(1, sizeof(*ctx));
      68         [ +  + ]:       3150 :                 if (ctx == NULL) {
      69         [ #  # ]:          0 :                         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
      70                 :            : 
      71                 :          0 :                         return -ENOMEM;
      72                 :            :                 }
      73   [ +  -  +  - ]:       3150 :                 ctx->ctrlr = ctrlr;
      74   [ +  -  +  - ]:       3150 :                 ctx->cb_fn = nvme_ctrlr_detach_async_finish;
      75                 :            : 
      76                 :       3150 :                 nvme_ctrlr_proc_put_ref(ctrlr);
      77                 :            : 
      78                 :       3150 :                 nvme_io_msg_ctrlr_detach(ctrlr);
      79                 :            : 
      80                 :       3150 :                 nvme_ctrlr_destruct_async(ctrlr, ctx);
      81                 :            : 
      82         [ +  - ]:       3150 :                 *_ctx = ctx;
      83                 :        885 :         } else {
      84                 :        229 :                 nvme_ctrlr_proc_put_ref(ctrlr);
      85                 :            :         }
      86                 :            : 
      87         [ +  - ]:       3379 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
      88                 :            : 
      89                 :       3379 :         return 0;
      90                 :        886 : }
      91                 :            : 
      92                 :            : static int
      93                 :   18148667 : nvme_ctrlr_detach_poll_async(struct nvme_ctrlr_detach_ctx *ctx)
      94                 :            : {
      95                 :            :         int rc;
      96                 :            : 
      97   [ +  -  +  - ]:   18148667 :         rc = nvme_ctrlr_destruct_poll_async(ctx->ctrlr, ctx);
      98         [ +  + ]:   18148667 :         if (rc == -EAGAIN) {
      99                 :   18145517 :                 return -EAGAIN;
     100                 :            :         }
     101                 :            : 
     102                 :       3150 :         free(ctx);
     103                 :            : 
     104                 :       3150 :         return rc;
     105                 :    1188031 : }
     106                 :            : 
     107                 :            : int
     108                 :        416 : spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr)
     109                 :            : {
     110                 :        416 :         struct nvme_ctrlr_detach_ctx *ctx = NULL;
     111                 :            :         int rc;
     112                 :            : 
     113                 :        416 :         rc = nvme_ctrlr_detach_async(ctrlr, &ctx);
     114         [ -  + ]:        416 :         if (rc != 0) {
     115                 :          0 :                 return rc;
     116         [ +  + ]:        416 :         } else if (ctx == NULL) {
     117                 :            :                 /* ctrlr was detached from the caller process but any other process
     118                 :            :                  * still attaches it.
     119                 :            :                  */
     120                 :          4 :                 return 0;
     121                 :            :         }
     122                 :            : 
     123                 :         39 :         while (1) {
     124                 :       2966 :                 rc = nvme_ctrlr_detach_poll_async(ctx);
     125         [ +  + ]:       2966 :                 if (rc != -EAGAIN) {
     126                 :        412 :                         break;
     127                 :            :                 }
     128                 :       2554 :                 nvme_delay(1000);
     129                 :            :         }
     130                 :            : 
     131                 :        412 :         return 0;
     132                 :         12 : }
     133                 :            : 
     134                 :            : int
     135                 :       2963 : spdk_nvme_detach_async(struct spdk_nvme_ctrlr *ctrlr,
     136                 :            :                        struct spdk_nvme_detach_ctx **_detach_ctx)
     137                 :            : {
     138                 :            :         struct spdk_nvme_detach_ctx *detach_ctx;
     139                 :       2963 :         struct nvme_ctrlr_detach_ctx *ctx = NULL;
     140                 :            :         int rc;
     141                 :            : 
     142   [ +  -  -  + ]:       2963 :         if (ctrlr == NULL || _detach_ctx == NULL) {
     143                 :          0 :                 return -EINVAL;
     144                 :            :         }
     145                 :            : 
     146                 :            :         /* Use a context header to poll detachment for multiple controllers.
     147                 :            :          * Allocate an new one if not allocated yet, or use the passed one otherwise.
     148                 :            :          */
     149         [ +  - ]:       2963 :         detach_ctx = *_detach_ctx;
     150         [ +  + ]:       2963 :         if (detach_ctx == NULL) {
     151                 :       2916 :                 detach_ctx = calloc(1, sizeof(*detach_ctx));
     152         [ +  + ]:       2916 :                 if (detach_ctx == NULL) {
     153                 :          0 :                         return -ENOMEM;
     154                 :            :                 }
     155   [ +  -  +  -  :       2916 :                 TAILQ_INIT(&detach_ctx->head);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     156                 :        871 :         }
     157                 :            : 
     158                 :       2963 :         rc = nvme_ctrlr_detach_async(ctrlr, &ctx);
     159   [ +  -  +  + ]:       2963 :         if (rc != 0 || ctx == NULL) {
     160                 :            :                 /* If this detach failed and the context header is empty, it means we just
     161                 :            :                  * allocated the header and need to free it before returning.
     162                 :            :                  */
     163   [ +  -  #  #  :        225 :                 if (TAILQ_EMPTY(&detach_ctx->head)) {
             #  #  #  # ]
     164                 :        225 :                         free(detach_ctx);
     165                 :          0 :                 }
     166                 :        225 :                 return rc;
     167                 :            :         }
     168                 :            : 
     169                 :            :         /* Append a context for this detachment to the context header. */
     170   [ +  -  +  -  :       2738 :         TAILQ_INSERT_TAIL(&detach_ctx->head, ctx, link);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     171                 :            : 
     172         [ +  - ]:       2738 :         *_detach_ctx = detach_ctx;
     173                 :            : 
     174                 :       2738 :         return 0;
     175                 :        874 : }
     176                 :            : 
     177                 :            : int
     178                 :   18145586 : spdk_nvme_detach_poll_async(struct spdk_nvme_detach_ctx *detach_ctx)
     179                 :            : {
     180                 :            :         struct nvme_ctrlr_detach_ctx *ctx, *tmp_ctx;
     181                 :            :         int rc;
     182                 :            : 
     183         [ +  + ]:   18145586 :         if (detach_ctx == NULL) {
     184                 :          0 :                 return -EINVAL;
     185                 :            :         }
     186                 :            : 
     187   [ +  +  +  +  :   36291287 :         TAILQ_FOREACH_SAFE(ctx, &detach_ctx->head, link, tmp_ctx) {
          +  -  +  +  +  
          -  +  -  +  -  
                   +  + ]
     188   [ +  +  +  -  :   18145701 :                 TAILQ_REMOVE(&detach_ctx->head, ctx, link);
          +  -  -  +  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     189                 :            : 
     190                 :   18145701 :                 rc = nvme_ctrlr_detach_poll_async(ctx);
     191         [ +  + ]:   18145701 :                 if (rc == -EAGAIN) {
     192                 :            :                         /* If not -EAGAIN, ctx was freed by nvme_ctrlr_detach_poll_async(). */
     193   [ +  +  +  -  :   18142963 :                         TAILQ_INSERT_HEAD(&detach_ctx->head, ctx, link);
          +  -  +  -  +  
          -  +  -  -  +  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     194                 :    1187118 :                 }
     195                 :    1187992 :         }
     196                 :            : 
     197   [ +  +  +  -  :   18145586 :         if (!TAILQ_EMPTY(&detach_ctx->head)) {
             +  -  +  + ]
     198                 :   18142895 :                 return -EAGAIN;
     199                 :            :         }
     200                 :            : 
     201                 :       2691 :         free(detach_ctx);
     202                 :       2691 :         return 0;
     203                 :    1187989 : }
     204                 :            : 
     205                 :            : void
     206                 :       1098 : spdk_nvme_detach_poll(struct spdk_nvme_detach_ctx *detach_ctx)
     207                 :            : {
     208   [ +  +  +  + ]:   17944216 :         while (detach_ctx && spdk_nvme_detach_poll_async(detach_ctx) == -EAGAIN) {
     209                 :            :                 ;
     210                 :            :         }
     211                 :       1098 : }
     212                 :            : 
     213                 :            : void
     214                 :      18117 : nvme_completion_poll_cb(void *arg, const struct spdk_nvme_cpl *cpl)
     215                 :            : {
     216                 :      18117 :         struct nvme_completion_poll_status      *status = arg;
     217                 :            : 
     218   [ +  +  +  +  :      18117 :         if (status->timed_out) {
             +  -  -  + ]
     219                 :            :                 /* There is no routine waiting for the completion of this request, free allocated memory */
     220   [ #  #  #  # ]:          0 :                 spdk_free(status->dma_data);
     221                 :          0 :                 free(status);
     222                 :          0 :                 return;
     223                 :            :         }
     224                 :            : 
     225                 :            :         /*
     226                 :            :          * Copy status into the argument passed by the caller, so that
     227                 :            :          *  the caller can check the status to determine if the
     228                 :            :          *  the request passed or failed.
     229                 :            :          */
     230   [ +  -  +  -  :      18117 :         memcpy(&status->cpl, cpl, sizeof(*cpl));
                   +  - ]
     231   [ +  -  +  - ]:      18117 :         status->done = true;
     232                 :       1773 : }
     233                 :            : 
     234                 :            : static void
     235                 :          0 : dummy_disconnected_qpair_cb(struct spdk_nvme_qpair *qpair, void *poll_group_ctx)
     236                 :            : {
     237                 :          0 : }
     238                 :            : 
     239                 :            : int
     240                 :    3205452 : nvme_wait_for_completion_robust_lock_timeout_poll(struct spdk_nvme_qpair *qpair,
     241                 :            :                 struct nvme_completion_poll_status *status,
     242                 :            :                 pthread_mutex_t *robust_mutex)
     243                 :            : {
     244                 :            :         int rc;
     245                 :            : 
     246         [ +  + ]:    3205452 :         if (robust_mutex) {
     247                 :     568331 :                 nvme_robust_mutex_lock(robust_mutex);
     248                 :          5 :         }
     249                 :            : 
     250   [ +  +  +  -  :    3205452 :         if (qpair->poll_group) {
                   +  - ]
     251   [ #  #  #  #  :    1249765 :                 rc = (int)spdk_nvme_poll_group_process_completions(qpair->poll_group->group, 0,
             #  #  #  # ]
     252                 :            :                                 dummy_disconnected_qpair_cb);
     253                 :          0 :         } else {
     254                 :    1955687 :                 rc = spdk_nvme_qpair_process_completions(qpair, 0);
     255                 :            :         }
     256                 :            : 
     257         [ +  + ]:    3205452 :         if (robust_mutex) {
     258                 :     568331 :                 nvme_robust_mutex_unlock(robust_mutex);
     259                 :          5 :         }
     260                 :            : 
     261         [ +  + ]:    3205452 :         if (rc < 0) {
     262   [ #  #  #  #  :         16 :                 status->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
             #  #  #  # ]
     263   [ #  #  #  #  :         16 :                 status->cpl.status.sc = SPDK_NVME_SC_ABORTED_SQ_DELETION;
             #  #  #  # ]
     264                 :         16 :                 goto error;
     265                 :            :         }
     266                 :            : 
     267   [ +  +  +  +  :    3205436 :         if (!status->done && status->timeout_tsc && spdk_get_ticks() > status->timeout_tsc) {
          +  +  +  +  +  
          -  +  -  -  +  
          #  #  #  #  #  
                      # ]
     268                 :          8 :                 goto error;
     269                 :            :         }
     270                 :            : 
     271   [ +  +  +  -  :    3205428 :         if (qpair->ctrlr->trid.trtype == SPDK_NVME_TRANSPORT_PCIE) {
          +  -  +  -  +  
                -  +  + ]
     272   [ +  -  +  - ]:      17666 :                 union spdk_nvme_csts_register csts = spdk_nvme_ctrlr_get_regs_csts(qpair->ctrlr);
     273         [ +  + ]:      17666 :                 if (csts.raw == SPDK_NVME_INVALID_REGISTER_VALUE) {
     274   [ #  #  #  #  :          0 :                         status->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
             #  #  #  # ]
     275   [ #  #  #  #  :          0 :                         status->cpl.status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
             #  #  #  # ]
     276                 :          0 :                         goto error;
     277                 :            :                 }
     278                 :        239 :         }
     279                 :            : 
     280   [ +  +  +  +  :    3205428 :         if (!status->done) {
             +  -  +  + ]
     281                 :    3187299 :                 return -EAGAIN;
     282   [ +  +  +  +  :      18129 :         } else if (spdk_nvme_cpl_is_error(&status->cpl)) {
          +  -  +  -  +  
          -  -  +  -  +  
          -  +  -  +  -  
                      + ]
     283                 :        779 :                 return -EIO;
     284                 :            :         } else {
     285                 :      17350 :                 return 0;
     286                 :            :         }
     287                 :         18 : error:
     288                 :            :         /* Either transport error occurred or we've timed out.  Either way, if the response hasn't
     289                 :            :          * been received yet, mark the command as timed out, so the status gets freed when the
     290                 :            :          * command is completed or aborted.
     291                 :            :          */
     292   [ +  +  +  -  :         24 :         if (!status->done) {
             #  #  #  # ]
     293   [ #  #  #  # ]:         24 :                 status->timed_out = true;
     294                 :          6 :         }
     295                 :            : 
     296                 :         24 :         return -ECANCELED;
     297                 :      48035 : }
     298                 :            : 
     299                 :            : /**
     300                 :            :  * Poll qpair for completions until a command completes.
     301                 :            :  *
     302                 :            :  * \param qpair queue to poll
     303                 :            :  * \param status completion status. The user must fill this structure with zeroes before calling
     304                 :            :  * this function
     305                 :            :  * \param robust_mutex optional robust mutex to lock while polling qpair
     306                 :            :  * \param timeout_in_usecs optional timeout
     307                 :            :  *
     308                 :            :  * \return 0 if command completed without error,
     309                 :            :  * -EIO if command completed with error,
     310                 :            :  * -ECANCELED if command is not completed due to transport/device error or time expired
     311                 :            :  *
     312                 :            :  *  The command to wait upon must be submitted with nvme_completion_poll_cb as the callback
     313                 :            :  *  and status as the callback argument.
     314                 :            :  */
     315                 :            : int
     316                 :       5962 : nvme_wait_for_completion_robust_lock_timeout(
     317                 :            :         struct spdk_nvme_qpair *qpair,
     318                 :            :         struct nvme_completion_poll_status *status,
     319                 :            :         pthread_mutex_t *robust_mutex,
     320                 :            :         uint64_t timeout_in_usecs)
     321                 :            : {
     322                 :            :         int rc;
     323                 :            : 
     324         [ +  + ]:       5962 :         if (timeout_in_usecs) {
     325   [ #  #  #  # ]:        430 :                 status->timeout_tsc = spdk_get_ticks() + timeout_in_usecs *
     326   [ #  #  #  # ]:        221 :                                       spdk_get_ticks_hz() / SPDK_SEC_TO_USEC;
     327                 :          6 :         } else {
     328   [ +  -  +  - ]:       5747 :                 status->timeout_tsc = 0;
     329                 :            :         }
     330                 :            : 
     331   [ +  -  +  -  :       5962 :         status->cpl.status_raw = 0;
             +  -  +  - ]
     332                 :        104 :         do {
     333                 :    1494899 :                 rc = nvme_wait_for_completion_robust_lock_timeout_poll(qpair, status, robust_mutex);
     334         [ +  + ]:    1494899 :         } while (rc == -EAGAIN);
     335                 :            : 
     336                 :       5962 :         return rc;
     337                 :            : }
     338                 :            : 
     339                 :            : /**
     340                 :            :  * Poll qpair for completions until a command completes.
     341                 :            :  *
     342                 :            :  * \param qpair queue to poll
     343                 :            :  * \param status completion status. The user must fill this structure with zeroes before calling
     344                 :            :  * this function
     345                 :            :  * \param robust_mutex optional robust mutex to lock while polling qpair
     346                 :            :  *
     347                 :            :  * \return 0 if command completed without error,
     348                 :            :  * -EIO if command completed with error,
     349                 :            :  * -ECANCELED if command is not completed due to transport/device error
     350                 :            :  *
     351                 :            :  * The command to wait upon must be submitted with nvme_completion_poll_cb as the callback
     352                 :            :  * and status as the callback argument.
     353                 :            :  */
     354                 :            : int
     355                 :       2266 : nvme_wait_for_completion_robust_lock(
     356                 :            :         struct spdk_nvme_qpair *qpair,
     357                 :            :         struct nvme_completion_poll_status *status,
     358                 :            :         pthread_mutex_t *robust_mutex)
     359                 :            : {
     360                 :       2266 :         return nvme_wait_for_completion_robust_lock_timeout(qpair, status, robust_mutex, 0);
     361                 :            : }
     362                 :            : 
     363                 :            : int
     364                 :       3481 : nvme_wait_for_completion(struct spdk_nvme_qpair *qpair,
     365                 :            :                          struct nvme_completion_poll_status *status)
     366                 :            : {
     367                 :       3481 :         return nvme_wait_for_completion_robust_lock_timeout(qpair, status, NULL, 0);
     368                 :            : }
     369                 :            : 
     370                 :            : /**
     371                 :            :  * Poll qpair for completions until a command completes.
     372                 :            :  *
     373                 :            :  * \param qpair queue to poll
     374                 :            :  * \param status completion status. The user must fill this structure with zeroes before calling
     375                 :            :  * this function
     376                 :            :  * \param timeout_in_usecs optional timeout
     377                 :            :  *
     378                 :            :  * \return 0 if command completed without error,
     379                 :            :  * -EIO if command completed with error,
     380                 :            :  * -ECANCELED if command is not completed due to transport/device error or time expired
     381                 :            :  *
     382                 :            :  * The command to wait upon must be submitted with nvme_completion_poll_cb as the callback
     383                 :            :  * and status as the callback argument.
     384                 :            :  */
     385                 :            : int
     386                 :        190 : nvme_wait_for_completion_timeout(struct spdk_nvme_qpair *qpair,
     387                 :            :                                  struct nvme_completion_poll_status *status,
     388                 :            :                                  uint64_t timeout_in_usecs)
     389                 :            : {
     390                 :        190 :         return nvme_wait_for_completion_robust_lock_timeout(qpair, status, NULL, timeout_in_usecs);
     391                 :            : }
     392                 :            : 
     393                 :            : static void
     394                 :     101263 : nvme_user_copy_cmd_complete(void *arg, const struct spdk_nvme_cpl *cpl)
     395                 :            : {
     396                 :     101263 :         struct nvme_request *req = arg;
     397                 :            :         spdk_nvme_cmd_cb user_cb_fn;
     398                 :            :         void *user_cb_arg;
     399                 :            :         enum spdk_nvme_data_transfer xfer;
     400                 :            : 
     401   [ +  +  +  +  :     101263 :         if (req->user_buffer && req->payload_size) {
          +  +  +  -  +  
                -  -  + ]
     402                 :            :                 /* Copy back to the user buffer */
     403   [ +  +  +  -  :      92206 :                 assert(nvme_payload_type(&req->payload) == NVME_PAYLOAD_TYPE_CONTIG);
                   #  # ]
     404   [ +  -  +  - ]:      92206 :                 xfer = spdk_nvme_opc_get_data_transfer(req->cmd.opc);
     405   [ +  +  -  + ]:      92206 :                 if (xfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST ||
     406                 :         35 :                     xfer == SPDK_NVME_DATA_BIDIRECTIONAL) {
     407   [ +  +  +  -  :      17332 :                         assert(req->pid == getpid());
             +  -  #  # ]
     408   [ +  +  +  +  :      17332 :                         memcpy(req->user_buffer, req->payload.contig_or_cb_arg, req->payload_size);
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  - ]
     409                 :       3630 :                 }
     410                 :       3665 :         }
     411                 :            : 
     412   [ +  -  +  - ]:     101263 :         user_cb_fn = req->user_cb_fn;
     413   [ +  -  +  - ]:     101263 :         user_cb_arg = req->user_cb_arg;
     414                 :     101263 :         nvme_cleanup_user_req(req);
     415                 :            : 
     416                 :            :         /* Call the user's original callback now that the buffer has been copied */
     417   [ -  +  +  - ]:     101263 :         user_cb_fn(user_cb_arg, cpl);
     418                 :            : 
     419                 :     101263 : }
     420                 :            : 
     421                 :            : /**
     422                 :            :  * Allocate a request as well as a DMA-capable buffer to copy to/from the user's buffer.
     423                 :            :  *
     424                 :            :  * This is intended for use in non-fast-path functions (admin commands, reservations, etc.)
     425                 :            :  * where the overhead of a copy is not a problem.
     426                 :            :  */
     427                 :            : struct nvme_request *
     428                 :     101307 : nvme_allocate_request_user_copy(struct spdk_nvme_qpair *qpair,
     429                 :            :                                 void *buffer, uint32_t payload_size, spdk_nvme_cmd_cb cb_fn,
     430                 :            :                                 void *cb_arg, bool host_to_controller)
     431                 :            : {
     432                 :            :         struct nvme_request *req;
     433                 :     101307 :         void *dma_buffer = NULL;
     434                 :            : 
     435   [ +  +  +  + ]:     101307 :         if (buffer && payload_size) {
     436                 :      92250 :                 dma_buffer = spdk_zmalloc(payload_size, 4096, NULL,
     437                 :            :                                           SPDK_ENV_NUMA_ID_ANY, SPDK_MALLOC_DMA);
     438         [ +  + ]:      92250 :                 if (!dma_buffer) {
     439                 :          4 :                         return NULL;
     440                 :            :                 }
     441                 :            : 
     442   [ +  +  +  - ]:      92246 :                 if (host_to_controller) {
     443   [ -  +  -  + ]:      74901 :                         memcpy(dma_buffer, buffer, payload_size);
     444                 :         42 :                 }
     445                 :       3675 :         }
     446                 :            : 
     447                 :     101303 :         req = nvme_allocate_request_contig(qpair, dma_buffer, payload_size, nvme_user_copy_cmd_complete,
     448                 :            :                                            NULL);
     449         [ +  + ]:     101303 :         if (!req) {
     450                 :          4 :                 spdk_free(dma_buffer);
     451                 :          4 :                 return NULL;
     452                 :            :         }
     453                 :            : 
     454   [ +  -  +  - ]:     101299 :         req->user_cb_fn = cb_fn;
     455   [ +  -  +  - ]:     101299 :         req->user_cb_arg = cb_arg;
     456   [ +  -  +  - ]:     101299 :         req->user_buffer = buffer;
     457   [ +  -  +  - ]:     101299 :         req->cb_arg = req;
     458                 :            : 
     459                 :     101299 :         return req;
     460                 :       6281 : }
     461                 :            : 
     462                 :            : /**
     463                 :            :  * Check if a request has exceeded the controller timeout.
     464                 :            :  *
     465                 :            :  * \param req request to check for timeout.
     466                 :            :  * \param cid command ID for command submitted by req (will be passed to timeout_cb_fn)
     467                 :            :  * \param active_proc per-process data for the controller associated with req
     468                 :            :  * \param now_tick current time from spdk_get_ticks()
     469                 :            :  * \return 0 if requests submitted more recently than req should still be checked for timeouts, or
     470                 :            :  * 1 if requests newer than req need not be checked.
     471                 :            :  *
     472                 :            :  * The request's timeout callback will be called if needed; the caller is only responsible for
     473                 :            :  * calling this function on each outstanding request.
     474                 :            :  */
     475                 :            : int
     476                 :     127201 : nvme_request_check_timeout(struct nvme_request *req, uint16_t cid,
     477                 :            :                            struct spdk_nvme_ctrlr_process *active_proc,
     478                 :            :                            uint64_t now_tick)
     479                 :            : {
     480   [ #  #  #  # ]:     127201 :         struct spdk_nvme_qpair *qpair = req->qpair;
     481   [ #  #  #  # ]:     127201 :         struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
     482         [ +  + ]:     127201 :         uint64_t timeout_ticks = nvme_qpair_is_admin_queue(qpair) ?
     483   [ +  +  #  #  :     127201 :                                  active_proc->timeout_admin_ticks : active_proc->timeout_io_ticks;
             #  #  #  # ]
     484                 :            : 
     485   [ +  +  #  #  :     127201 :         assert(active_proc->timeout_cb_fn != NULL);
             #  #  #  # ]
     486                 :            : 
     487   [ +  +  +  +  :     127201 :         if (req->timed_out || req->submit_tick == 0) {
          #  #  #  #  #  
                      # ]
     488                 :       2536 :                 return 0;
     489                 :            :         }
     490                 :            : 
     491   [ +  +  #  #  :     124665 :         if (req->pid != g_spdk_nvme_pid) {
                   #  # ]
     492                 :          4 :                 return 0;
     493                 :            :         }
     494                 :            : 
     495   [ +  +  -  + ]:     124661 :         if (nvme_qpair_is_admin_queue(qpair) &&
     496   [ +  +  #  # ]:        580 :             req->cmd.opc == SPDK_NVME_OPC_ASYNC_EVENT_REQUEST) {
     497                 :          4 :                 return 0;
     498                 :            :         }
     499                 :            : 
     500   [ +  +  #  #  :     124657 :         if (req->submit_tick + timeout_ticks > now_tick) {
                   #  # ]
     501                 :     124653 :                 return 1;
     502                 :            :         }
     503                 :            : 
     504         [ #  # ]:          4 :         req->timed_out = true;
     505                 :            : 
     506                 :            :         /*
     507                 :            :          * We don't want to expose the admin queue to the user,
     508                 :            :          * so when we're timing out admin commands set the
     509                 :            :          * qpair to NULL.
     510                 :            :          */
     511   [ +  -  #  #  :          7 :         active_proc->timeout_cb_fn(active_proc->timeout_cb_arg, ctrlr,
          #  #  #  #  #  
                #  #  # ]
     512         [ -  + ]:          4 :                                    nvme_qpair_is_admin_queue(qpair) ? NULL : qpair,
     513                 :          1 :                                    cid);
     514                 :          4 :         return 0;
     515                 :          6 : }
     516                 :            : 
     517                 :            : int
     518                 :        957 : nvme_robust_mutex_init_shared(pthread_mutex_t *mtx)
     519                 :            : {
     520                 :        957 :         int rc = 0;
     521                 :            : 
     522                 :            : #ifdef __FreeBSD__
     523                 :         35 :         pthread_mutex_init(mtx, NULL);
     524                 :            : #else
     525                 :        267 :         pthread_mutexattr_t attr;
     526                 :            : 
     527   [ +  +  +  + ]:        922 :         if (pthread_mutexattr_init(&attr)) {
     528                 :          6 :                 return -1;
     529                 :            :         }
     530   [ +  +  +  -  :       1832 :         if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED) ||
                   +  + ]
     531   [ +  +  +  + ]:       1798 :             pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST) ||
     532         [ +  + ]:        916 :             pthread_mutex_init(mtx, &attr)) {
     533                 :          3 :                 rc = -1;
     534                 :          0 :         }
     535         [ +  + ]:        916 :         pthread_mutexattr_destroy(&attr);
     536                 :            : #endif
     537                 :            : 
     538                 :        951 :         return rc;
     539                 :         34 : }
     540                 :            : 
     541                 :            : int
     542                 :     143829 : nvme_driver_init(void)
     543                 :            : {
     544                 :            :         static pthread_mutex_t g_init_mutex = PTHREAD_MUTEX_INITIALIZER;
     545                 :     143829 :         int ret = 0;
     546                 :            : 
     547                 :            :         /* Use a special process-private mutex to ensure the global
     548                 :            :          * nvme driver object (g_spdk_nvme_driver) gets initialized by
     549                 :            :          * only one thread.  Once that object is established and its
     550                 :            :          * mutex is initialized, we can unlock this mutex and use that
     551                 :            :          * one instead.
     552                 :            :          */
     553         [ +  + ]:     143829 :         pthread_mutex_lock(&g_init_mutex);
     554                 :            : 
     555                 :            :         /* Each process needs its own pid. */
     556                 :     143829 :         g_spdk_nvme_pid = getpid();
     557                 :            : 
     558                 :            :         /*
     559                 :            :          * Only one thread from one process will do this driver init work.
     560                 :            :          * The primary process will reserve the shared memory and do the
     561                 :            :          *  initialization.
     562                 :            :          * The secondary process will lookup the existing reserved memory.
     563                 :            :          */
     564         [ +  + ]:     143829 :         if (spdk_process_is_primary()) {
     565                 :            :                 /* The unique named memzone already reserved. */
     566         [ +  + ]:     143567 :                 if (g_spdk_nvme_driver != NULL) {
     567         [ +  + ]:     142618 :                         pthread_mutex_unlock(&g_init_mutex);
     568                 :     142618 :                         return 0;
     569                 :            :                 } else {
     570                 :        949 :                         g_spdk_nvme_driver = spdk_memzone_reserve(SPDK_NVME_DRIVER_NAME,
     571                 :            :                                              sizeof(struct nvme_driver), SPDK_ENV_NUMA_ID_ANY,
     572                 :            :                                              SPDK_MEMZONE_NO_IOVA_CONTIG);
     573                 :            :                 }
     574                 :            : 
     575         [ +  + ]:        949 :                 if (g_spdk_nvme_driver == NULL) {
     576                 :          4 :                         SPDK_ERRLOG("primary process failed to reserve memory\n");
     577         [ -  + ]:          4 :                         pthread_mutex_unlock(&g_init_mutex);
     578                 :          4 :                         return -1;
     579                 :            :                 }
     580                 :         66 :         } else {
     581                 :        262 :                 g_spdk_nvme_driver = spdk_memzone_lookup(SPDK_NVME_DRIVER_NAME);
     582                 :            : 
     583                 :            :                 /* The unique named memzone already reserved by the primary process. */
     584         [ +  + ]:        262 :                 if (g_spdk_nvme_driver != NULL) {
     585                 :        250 :                         int ms_waited = 0;
     586                 :            : 
     587                 :            :                         /* Wait the nvme driver to get initialized. */
     588   [ +  +  +  +  :        665 :                         while ((g_spdk_nvme_driver->initialized == false) &&
          #  #  #  #  #  
                      # ]
     589         [ +  + ]:        404 :                                (ms_waited < g_nvme_driver_timeout_ms)) {
     590         [ #  # ]:        400 :                                 ms_waited++;
     591                 :        400 :                                 nvme_delay(1000); /* delay 1ms */
     592                 :            :                         }
     593   [ +  +  +  +  :        250 :                         if (g_spdk_nvme_driver->initialized == false) {
             #  #  #  # ]
     594                 :          4 :                                 SPDK_ERRLOG("timeout waiting for primary process to init\n");
     595         [ -  + ]:          4 :                                 pthread_mutex_unlock(&g_init_mutex);
     596                 :          4 :                                 return -1;
     597                 :            :                         }
     598                 :         14 :                 } else {
     599                 :         12 :                         SPDK_ERRLOG("primary process is not started yet\n");
     600         [ -  + ]:         12 :                         pthread_mutex_unlock(&g_init_mutex);
     601                 :         12 :                         return -1;
     602                 :            :                 }
     603                 :            : 
     604         [ -  + ]:        246 :                 pthread_mutex_unlock(&g_init_mutex);
     605                 :        246 :                 return 0;
     606                 :            :         }
     607                 :            : 
     608                 :            :         /*
     609                 :            :          * At this moment, only one thread from the primary process will do
     610                 :            :          * the g_spdk_nvme_driver initialization
     611                 :            :          */
     612   [ +  +  #  # ]:        945 :         assert(spdk_process_is_primary());
     613                 :            : 
     614         [ +  - ]:        945 :         ret = nvme_robust_mutex_init_shared(&g_spdk_nvme_driver->lock);
     615         [ +  + ]:        945 :         if (ret != 0) {
     616                 :          3 :                 SPDK_ERRLOG("failed to initialize mutex\n");
     617                 :          3 :                 spdk_memzone_free(SPDK_NVME_DRIVER_NAME);
     618         [ -  + ]:          3 :                 pthread_mutex_unlock(&g_init_mutex);
     619                 :          3 :                 return ret;
     620                 :            :         }
     621                 :            : 
     622                 :            :         /* The lock in the shared g_spdk_nvme_driver object is now ready to
     623                 :            :          * be used - so we can unlock the g_init_mutex here.
     624                 :            :          */
     625         [ +  + ]:        942 :         pthread_mutex_unlock(&g_init_mutex);
     626         [ +  - ]:        942 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     627                 :            : 
     628   [ +  -  +  - ]:        942 :         g_spdk_nvme_driver->initialized = false;
     629   [ +  -  +  - ]:        942 :         g_spdk_nvme_driver->hotplug_fd = spdk_pci_event_listen();
     630   [ +  +  +  -  :        942 :         if (g_spdk_nvme_driver->hotplug_fd < 0) {
                   +  - ]
     631   [ +  -  #  #  :         28 :                 SPDK_DEBUGLOG(nvme, "Failed to open uevent netlink socket\n");
                   #  # ]
     632                 :         28 :         }
     633                 :            : 
     634   [ +  -  +  -  :        942 :         TAILQ_INIT(&g_spdk_nvme_driver->shared_attached_ctrlrs);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     635                 :            : 
     636         [ +  - ]:        942 :         spdk_uuid_generate(&g_spdk_nvme_driver->default_extended_host_id);
     637                 :            : 
     638         [ +  - ]:        942 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     639                 :            : 
     640                 :        942 :         return ret;
     641                 :       2866 : }
     642                 :            : 
     643                 :            : /* This function must only be called while holding g_spdk_nvme_driver->lock */
     644                 :            : int
     645                 :       3178 : nvme_ctrlr_probe(const struct spdk_nvme_transport_id *trid,
     646                 :            :                  struct spdk_nvme_probe_ctx *probe_ctx, void *devhandle)
     647                 :            : {
     648                 :            :         struct spdk_nvme_ctrlr *ctrlr;
     649                 :        396 :         struct spdk_nvme_ctrlr_opts opts;
     650                 :            : 
     651   [ +  +  #  # ]:       3178 :         assert(trid != NULL);
     652                 :            : 
     653                 :       3178 :         spdk_nvme_ctrlr_get_default_ctrlr_opts(&opts, sizeof(opts));
     654                 :            : 
     655   [ +  +  +  +  :       3178 :         if (!probe_ctx->probe_cb || probe_ctx->probe_cb(probe_ctx->cb_ctx, trid, &opts)) {
          +  +  +  -  +  
          -  -  +  +  -  
          +  -  +  -  +  
                      - ]
     656                 :       3152 :                 ctrlr = nvme_get_ctrlr_by_trid_unsafe(trid, opts.hostnqn);
     657         [ +  + ]:       3152 :                 if (ctrlr) {
     658                 :            :                         /* This ctrlr already exists. */
     659                 :            : 
     660   [ +  +  +  -  :          4 :                         if (ctrlr->is_destructed) {
             #  #  #  # ]
     661                 :            :                                 /* This ctrlr is being destructed asynchronously. */
     662         [ #  # ]:          4 :                                 SPDK_ERRLOG("NVMe controller for SSD: %s is being destructed\n",
     663                 :            :                                             trid->traddr);
     664   [ #  #  #  #  :          4 :                                 probe_ctx->attach_fail_cb(probe_ctx->cb_ctx, trid, -EBUSY);
          #  #  #  #  #  
                #  #  # ]
     665                 :          4 :                                 return -EBUSY;
     666                 :            :                         }
     667                 :            : 
     668                 :            :                         /* Increase the ref count before calling attach_cb() as the user may
     669                 :            :                         * call nvme_detach() immediately. */
     670                 :          0 :                         nvme_ctrlr_proc_get_ref(ctrlr);
     671                 :            : 
     672   [ #  #  #  #  :          0 :                         if (probe_ctx->attach_cb) {
                   #  # ]
     673         [ #  # ]:          0 :                                 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     674   [ #  #  #  #  :          0 :                                 probe_ctx->attach_cb(probe_ctx->cb_ctx, &ctrlr->trid, ctrlr, &ctrlr->opts);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     675         [ #  # ]:          0 :                                 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     676                 :          0 :                         }
     677                 :          0 :                         return 0;
     678                 :            :                 }
     679                 :            : 
     680                 :       3148 :                 ctrlr = nvme_transport_ctrlr_construct(trid, &opts, devhandle);
     681         [ +  + ]:       3148 :                 if (ctrlr == NULL) {
     682         [ #  # ]:         11 :                         SPDK_ERRLOG("Failed to construct NVMe controller for SSD: %s\n", trid->traddr);
     683   [ #  #  #  #  :         11 :                         probe_ctx->attach_fail_cb(probe_ctx->cb_ctx, trid, -ENODEV);
          #  #  #  #  #  
                #  #  # ]
     684                 :         11 :                         return -1;
     685                 :            :                 }
     686   [ +  -  +  -  :       3137 :                 ctrlr->remove_cb = probe_ctx->remove_cb;
             +  -  +  - ]
     687   [ +  -  +  -  :       3137 :                 ctrlr->cb_ctx = probe_ctx->cb_ctx;
             +  -  +  - ]
     688                 :            : 
     689   [ +  -  +  - ]:       3137 :                 nvme_qpair_set_state(ctrlr->adminq, NVME_QPAIR_ENABLED);
     690   [ +  -  +  -  :       3137 :                 TAILQ_INSERT_TAIL(&probe_ctx->init_ctrlrs, ctrlr, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     691                 :       3137 :                 return 0;
     692                 :            :         }
     693                 :            : 
     694                 :         26 :         return 1;
     695                 :        882 : }
     696                 :            : 
     697                 :            : static void
     698                 :  153306998 : nvme_ctrlr_poll_internal(struct spdk_nvme_ctrlr *ctrlr,
     699                 :            :                          struct spdk_nvme_probe_ctx *probe_ctx)
     700                 :            : {
     701                 :  153306998 :         int rc = 0;
     702                 :            : 
     703                 :  153306998 :         rc = nvme_ctrlr_process_init(ctrlr);
     704                 :            : 
     705         [ +  + ]:  153306998 :         if (rc) {
     706                 :            :                 /* Controller failed to initialize. */
     707   [ -  +  #  #  :         59 :                 TAILQ_REMOVE(&probe_ctx->init_ctrlrs, ctrlr, tailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     708   [ #  #  #  # ]:         59 :                 SPDK_ERRLOG("Failed to initialize SSD: %s\n", ctrlr->trid.traddr);
     709   [ #  #  #  #  :         59 :                 probe_ctx->attach_fail_cb(probe_ctx->cb_ctx, &ctrlr->trid, rc);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     710                 :         59 :                 nvme_ctrlr_lock(ctrlr);
     711                 :         59 :                 nvme_ctrlr_fail(ctrlr, false);
     712                 :         59 :                 nvme_ctrlr_unlock(ctrlr);
     713                 :         59 :                 nvme_ctrlr_destruct(ctrlr);
     714                 :         59 :                 return;
     715                 :            :         }
     716                 :            : 
     717   [ +  +  +  -  :  153306939 :         if (ctrlr->state != NVME_CTRLR_STATE_READY) {
                   +  + ]
     718                 :  153303816 :                 return;
     719                 :            :         }
     720                 :            : 
     721   [ +  -  +  -  :       3123 :         STAILQ_INIT(&ctrlr->io_producers);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     722                 :            : 
     723                 :            :         /*
     724                 :            :          * Controller has been initialized.
     725                 :            :          *  Move it to the attached_ctrlrs list.
     726                 :            :          */
     727   [ +  +  +  -  :       3123 :         TAILQ_REMOVE(&probe_ctx->init_ctrlrs, ctrlr, tailq);
          +  -  -  +  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  +  - ]
     728                 :            : 
     729         [ +  - ]:       3123 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     730         [ +  + ]:       3123 :         if (nvme_ctrlr_shared(ctrlr)) {
     731   [ +  -  +  -  :        716 :                 TAILQ_INSERT_TAIL(&g_spdk_nvme_driver->shared_attached_ctrlrs, ctrlr, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     732                 :         31 :         } else {
     733   [ +  -  +  -  :       2407 :                 TAILQ_INSERT_TAIL(&g_nvme_attached_ctrlrs, ctrlr, tailq);
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     734                 :            :         }
     735                 :            : 
     736                 :            :         /*
     737                 :            :          * Increase the ref count before calling attach_cb() as the user may
     738                 :            :          * call nvme_detach() immediately.
     739                 :            :          */
     740                 :       3123 :         nvme_ctrlr_proc_get_ref(ctrlr);
     741         [ +  - ]:       3123 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     742                 :            : 
     743   [ +  +  +  -  :       3123 :         if (probe_ctx->attach_cb) {
                   +  + ]
     744   [ +  -  +  -  :       1840 :                 probe_ctx->attach_cb(probe_ctx->cb_ctx, &ctrlr->trid, ctrlr, &ctrlr->opts);
          -  +  +  -  +  
          -  +  -  +  -  
                   +  - ]
     745                 :         26 :         }
     746                 :   32444299 : }
     747                 :            : 
     748                 :            : static int
     749                 :      95192 : nvme_init_controllers(struct spdk_nvme_probe_ctx *probe_ctx)
     750                 :            : {
     751                 :      95192 :         int rc = 0;
     752                 :            : 
     753                 :   32441775 :         while (true) {
     754                 :  153061430 :                 rc = spdk_nvme_probe_poll_async(probe_ctx);
     755         [ +  + ]:  153061430 :                 if (rc != -EAGAIN) {
     756                 :      95192 :                         return rc;
     757                 :            :                 }
     758                 :            :         }
     759                 :            : 
     760                 :            :         return rc;
     761                 :            : }
     762                 :            : 
     763                 :            : /* This function must not be called while holding g_spdk_nvme_driver->lock */
     764                 :            : static struct spdk_nvme_ctrlr *
     765                 :       1347 : nvme_get_ctrlr_by_trid(const struct spdk_nvme_transport_id *trid, const char *hostnqn)
     766                 :            : {
     767                 :            :         struct spdk_nvme_ctrlr *ctrlr;
     768                 :            : 
     769         [ +  - ]:       1347 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     770                 :       1347 :         ctrlr = nvme_get_ctrlr_by_trid_unsafe(trid, hostnqn);
     771         [ +  - ]:       1347 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     772                 :            : 
     773                 :       1347 :         return ctrlr;
     774                 :            : }
     775                 :            : 
     776                 :            : /* This function must be called while holding g_spdk_nvme_driver->lock */
     777                 :            : struct spdk_nvme_ctrlr *
     778                 :       5530 : nvme_get_ctrlr_by_trid_unsafe(const struct spdk_nvme_transport_id *trid, const char *hostnqn)
     779                 :            : {
     780                 :            :         struct spdk_nvme_ctrlr *ctrlr;
     781                 :            : 
     782                 :            :         /* Search per-process list */
     783   [ +  +  #  #  :       5906 :         TAILQ_FOREACH(ctrlr, &g_nvme_attached_ctrlrs, tailq) {
             #  #  #  # ]
     784   [ +  +  -  + ]:       1622 :                 if (spdk_nvme_transport_id_compare(&ctrlr->trid, trid) != 0) {
     785                 :        373 :                         continue;
     786                 :            :                 }
     787   [ +  -  +  +  :       1249 :                 if (hostnqn && strcmp(ctrlr->opts.hostnqn, hostnqn) != 0) {
          +  +  +  +  +  
                -  +  - ]
     788                 :          3 :                         continue;
     789                 :            :                 }
     790                 :       1246 :                 return ctrlr;
     791                 :            :         }
     792                 :            : 
     793                 :            :         /* Search multi-process shared list */
     794   [ +  +  +  -  :       4800 :         TAILQ_FOREACH(ctrlr, &g_spdk_nvme_driver->shared_attached_ctrlrs, tailq) {
          +  -  -  +  #  
             #  #  #  #  
                      # ]
     795   [ +  +  #  # ]:        914 :                 if (spdk_nvme_transport_id_compare(&ctrlr->trid, trid) != 0) {
     796                 :        516 :                         continue;
     797                 :            :                 }
     798   [ +  +  -  +  :        398 :                 if (hostnqn && strcmp(ctrlr->opts.hostnqn, hostnqn) != 0) {
          -  +  -  +  #  
                #  #  # ]
     799                 :          0 :                         continue;
     800                 :            :                 }
     801                 :        398 :                 return ctrlr;
     802                 :            :         }
     803                 :            : 
     804                 :       3886 :         return NULL;
     805                 :       1774 : }
     806                 :            : 
     807                 :            : /* This function must only be called while holding g_spdk_nvme_driver->lock */
     808                 :            : static int
     809                 :     100668 : nvme_probe_internal(struct spdk_nvme_probe_ctx *probe_ctx,
     810                 :            :                     bool direct_connect)
     811                 :            : {
     812                 :            :         int rc;
     813                 :            :         struct spdk_nvme_ctrlr *ctrlr, *ctrlr_tmp;
     814   [ +  -  +  - ]:     100668 :         const struct spdk_nvme_ctrlr_opts *opts = probe_ctx->opts;
     815                 :            : 
     816   [ +  +  +  -  :     100668 :         if (strlen(probe_ctx->trid.trstring) == 0) {
             +  -  +  + ]
     817                 :            :                 /* If user didn't provide trstring, derive it from trtype */
     818   [ +  -  +  -  :         94 :                 spdk_nvme_trid_populate_transport(&probe_ctx->trid, probe_ctx->trid.trtype);
             +  -  +  - ]
     819                 :         17 :         }
     820                 :            : 
     821   [ +  +  +  -  :     100668 :         if (!spdk_nvme_transport_available_by_name(probe_ctx->trid.trstring)) {
                   +  - ]
     822   [ #  #  #  #  :          4 :                 SPDK_ERRLOG("NVMe trtype %u (%s) not available\n",
          #  #  #  #  #  
                      # ]
     823                 :            :                             probe_ctx->trid.trtype, probe_ctx->trid.trstring);
     824                 :          4 :                 return -1;
     825                 :            :         }
     826                 :            : 
     827         [ +  - ]:     100664 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     828                 :            : 
     829         [ +  - ]:     100664 :         rc = nvme_transport_ctrlr_scan(probe_ctx, direct_connect);
     830         [ +  + ]:     100664 :         if (rc != 0) {
     831                 :         22 :                 SPDK_ERRLOG("NVMe ctrlr scan failed\n");
     832   [ +  +  +  +  :         26 :                 TAILQ_FOREACH_SAFE(ctrlr, &probe_ctx->init_ctrlrs, tailq, ctrlr_tmp) {
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     833   [ -  +  #  #  :          4 :                         TAILQ_REMOVE(&probe_ctx->init_ctrlrs, ctrlr, tailq);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     834   [ #  #  #  #  :          4 :                         probe_ctx->attach_fail_cb(probe_ctx->cb_ctx, &ctrlr->trid, -EFAULT);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     835                 :          4 :                         nvme_transport_ctrlr_destruct(ctrlr);
     836                 :          1 :                 }
     837         [ #  # ]:         22 :                 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     838                 :         22 :                 return -1;
     839                 :            :         }
     840                 :            : 
     841                 :            :         /*
     842                 :            :          * Probe controllers on the shared_attached_ctrlrs list
     843                 :            :          */
     844   [ +  +  +  +  :     100642 :         if (!spdk_process_is_primary() && (probe_ctx->trid.trtype == SPDK_NVME_TRANSPORT_PCIE)) {
          #  #  #  #  #  
                      # ]
     845   [ +  +  #  #  :        466 :                 TAILQ_FOREACH(ctrlr, &g_spdk_nvme_driver->shared_attached_ctrlrs, tailq) {
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     846                 :            :                         /* Do not attach other ctrlrs if user specify a valid trid */
     847   [ +  +  +  +  :        357 :                         if ((strlen(probe_ctx->trid.traddr) != 0) &&
          #  #  #  #  #  
                      # ]
     848   [ #  #  #  # ]:         74 :                             (spdk_nvme_transport_id_compare(&probe_ctx->trid, &ctrlr->trid))) {
     849                 :         30 :                                 continue;
     850                 :            :                         }
     851                 :            : 
     852   [ +  +  -  +  :        258 :                         if (opts && strcmp(opts->hostnqn, ctrlr->opts.hostnqn) != 0) {
          -  +  -  +  #  
             #  #  #  #  
                      # ]
     853                 :          0 :                                 continue;
     854                 :            :                         }
     855                 :            : 
     856                 :            :                         /* Do not attach if we failed to initialize it in this process */
     857         [ +  + ]:        258 :                         if (nvme_ctrlr_get_current_process(ctrlr) == NULL) {
     858                 :          0 :                                 continue;
     859                 :            :                         }
     860                 :            : 
     861                 :        258 :                         nvme_ctrlr_proc_get_ref(ctrlr);
     862                 :            : 
     863                 :            :                         /*
     864                 :            :                          * Unlock while calling attach_cb() so the user can call other functions
     865                 :            :                          *  that may take the driver lock, like nvme_detach().
     866                 :            :                          */
     867   [ +  +  #  #  :        258 :                         if (probe_ctx->attach_cb) {
                   #  # ]
     868         [ #  # ]:        218 :                                 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     869   [ #  #  #  #  :        218 :                                 probe_ctx->attach_cb(probe_ctx->cb_ctx, &ctrlr->trid, ctrlr, &ctrlr->opts);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     870         [ #  # ]:        218 :                                 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
     871                 :          1 :                         }
     872                 :          6 :                 }
     873                 :          7 :         }
     874                 :            : 
     875         [ +  - ]:     100642 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
     876                 :            : 
     877                 :     100642 :         return 0;
     878                 :        889 : }
     879                 :            : 
     880                 :            : static void
     881                 :         58 : nvme_dummy_attach_fail_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
     882                 :            :                           int rc)
     883                 :            : {
     884   [ #  #  #  #  :         58 :         SPDK_ERRLOG("Failed to attach nvme ctrlr: trtype=%s adrfam=%s traddr=%s trsvcid=%s "
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     885                 :            :                     "subnqn=%s, %s\n", spdk_nvme_transport_id_trtype_str(trid->trtype),
     886                 :            :                     spdk_nvme_transport_id_adrfam_str(trid->adrfam), trid->traddr, trid->trsvcid,
     887                 :            :                     trid->subnqn, spdk_strerror(-rc));
     888                 :         58 : }
     889                 :            : 
     890                 :            : static void
     891                 :     137365 : nvme_probe_ctx_init(struct spdk_nvme_probe_ctx *probe_ctx,
     892                 :            :                     const struct spdk_nvme_transport_id *trid,
     893                 :            :                     const struct spdk_nvme_ctrlr_opts *opts,
     894                 :            :                     void *cb_ctx,
     895                 :            :                     spdk_nvme_probe_cb probe_cb,
     896                 :            :                     spdk_nvme_attach_cb attach_cb,
     897                 :            :                     spdk_nvme_attach_fail_cb attach_fail_cb,
     898                 :            :                     spdk_nvme_remove_cb remove_cb)
     899                 :            : {
     900         [ +  - ]:     137365 :         probe_ctx->trid = *trid;
     901   [ +  -  +  - ]:     137365 :         probe_ctx->opts = opts;
     902   [ +  -  +  - ]:     137365 :         probe_ctx->cb_ctx = cb_ctx;
     903   [ +  -  +  - ]:     137365 :         probe_ctx->probe_cb = probe_cb;
     904   [ +  -  +  - ]:     137365 :         probe_ctx->attach_cb = attach_cb;
     905         [ +  + ]:     137365 :         if (attach_fail_cb != NULL) {
     906   [ #  #  #  # ]:         24 :                 probe_ctx->attach_fail_cb = attach_fail_cb;
     907                 :          6 :         } else {
     908   [ +  -  +  - ]:     137341 :                 probe_ctx->attach_fail_cb = nvme_dummy_attach_fail_cb;
     909                 :            :         }
     910   [ +  -  +  - ]:     137365 :         probe_ctx->remove_cb = remove_cb;
     911   [ +  -  +  -  :     137365 :         TAILQ_INIT(&probe_ctx->init_ctrlrs);
          +  -  +  -  +  
          -  +  -  +  -  
                   +  - ]
     912                 :     137365 : }
     913                 :            : 
     914                 :            : int
     915                 :      93843 : spdk_nvme_probe(const struct spdk_nvme_transport_id *trid, void *cb_ctx,
     916                 :            :                 spdk_nvme_probe_cb probe_cb, spdk_nvme_attach_cb attach_cb,
     917                 :            :                 spdk_nvme_remove_cb remove_cb)
     918                 :            : {
     919                 :      93843 :         return spdk_nvme_probe_ext(trid, cb_ctx, probe_cb, attach_cb, NULL, remove_cb);
     920                 :            : }
     921                 :            : 
     922                 :            : int
     923                 :      93859 : spdk_nvme_probe_ext(const struct spdk_nvme_transport_id *trid, void *cb_ctx,
     924                 :            :                     spdk_nvme_probe_cb probe_cb, spdk_nvme_attach_cb attach_cb,
     925                 :            :                     spdk_nvme_attach_fail_cb attach_fail_cb, spdk_nvme_remove_cb remove_cb)
     926                 :            : {
     927                 :      38712 :         struct spdk_nvme_transport_id trid_pcie;
     928                 :            :         struct spdk_nvme_probe_ctx *probe_ctx;
     929                 :            : 
     930         [ +  + ]:      93859 :         if (trid == NULL) {
     931         [ +  + ]:      93610 :                 memset(&trid_pcie, 0, sizeof(trid_pcie));
     932                 :      93610 :                 spdk_nvme_trid_populate_transport(&trid_pcie, SPDK_NVME_TRANSPORT_PCIE);
     933                 :      93610 :                 trid = &trid_pcie;
     934                 :         10 :         }
     935                 :            : 
     936                 :      93878 :         probe_ctx = spdk_nvme_probe_async_ext(trid, cb_ctx, probe_cb,
     937                 :         19 :                                               attach_cb, attach_fail_cb, remove_cb);
     938         [ +  + ]:      93859 :         if (!probe_ctx) {
     939                 :         10 :                 SPDK_ERRLOG("Create probe context failed\n");
     940                 :         10 :                 return -1;
     941                 :            :         }
     942                 :            : 
     943                 :            :         /*
     944                 :            :          * Keep going even if one or more nvme_attach() calls failed,
     945                 :            :          *  but maintain the value of rc to signal errors when we return.
     946                 :            :          */
     947                 :      93849 :         return nvme_init_controllers(probe_ctx);
     948                 :         19 : }
     949                 :            : 
     950                 :            : static bool
     951                 :       1658 : nvme_connect_probe_cb(void *cb_ctx, const struct spdk_nvme_transport_id *trid,
     952                 :            :                       struct spdk_nvme_ctrlr_opts *opts)
     953                 :            : {
     954                 :       1658 :         struct spdk_nvme_ctrlr_opts *requested_opts = cb_ctx;
     955                 :            : 
     956   [ +  +  #  # ]:       1658 :         assert(requested_opts);
     957   [ +  +  +  + ]:       1658 :         memcpy(opts, requested_opts, sizeof(*opts));
     958                 :            : 
     959                 :       1658 :         return true;
     960                 :            : }
     961                 :            : 
     962                 :            : static void
     963                 :         83 : nvme_ctrlr_opts_init(struct spdk_nvme_ctrlr_opts *opts,
     964                 :            :                      const struct spdk_nvme_ctrlr_opts *opts_user,
     965                 :            :                      size_t opts_size_user)
     966                 :            : {
     967   [ +  +  #  # ]:         83 :         assert(opts);
     968   [ -  +  #  # ]:         83 :         assert(opts_user);
     969                 :            : 
     970                 :         83 :         spdk_nvme_ctrlr_get_default_ctrlr_opts(opts, opts_size_user);
     971                 :            : 
     972                 :            : #define FIELD_OK(field) \
     973                 :            :         offsetof(struct spdk_nvme_ctrlr_opts, field) + sizeof(opts->field) <= (opts->opts_size)
     974                 :            : 
     975                 :            : #define SET_FIELD(field) \
     976                 :            :         if (FIELD_OK(field)) { \
     977                 :            :                         opts->field = opts_user->field; \
     978                 :            :         }
     979                 :            : 
     980                 :            : #define SET_FIELD_ARRAY(field) \
     981                 :            :         if (FIELD_OK(field)) { \
     982                 :            :                 memcpy(opts->field, opts_user->field, sizeof(opts_user->field)); \
     983                 :            :         }
     984                 :            : 
     985   [ +  +  #  #  :         83 :         SET_FIELD(num_io_queues);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     986   [ +  +  -  +  :         83 :         SET_FIELD(use_cmb_sqs);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     987   [ +  +  -  +  :         83 :         SET_FIELD(no_shn_notification);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     988   [ +  +  -  +  :         83 :         SET_FIELD(enable_interrupts);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     989   [ +  +  #  #  :         83 :         SET_FIELD(arb_mechanism);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     990   [ +  +  #  #  :         83 :         SET_FIELD(arbitration_burst);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     991   [ +  +  #  #  :         83 :         SET_FIELD(low_priority_weight);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     992   [ +  +  #  #  :         83 :         SET_FIELD(medium_priority_weight);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     993   [ +  +  #  #  :         83 :         SET_FIELD(high_priority_weight);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     994   [ +  +  #  #  :         83 :         SET_FIELD(keep_alive_timeout_ms);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     995   [ +  +  #  #  :         83 :         SET_FIELD(transport_retry_count);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     996   [ +  +  #  #  :         83 :         SET_FIELD(io_queue_size);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     997   [ +  +  -  +  :         83 :         SET_FIELD_ARRAY(hostnqn);
          -  +  #  #  #  
             #  #  #  #  
                      # ]
     998   [ +  +  #  #  :         83 :         SET_FIELD(io_queue_requests);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     999   [ +  +  -  +  :         83 :         SET_FIELD_ARRAY(src_addr);
          -  +  #  #  #  
             #  #  #  #  
                      # ]
    1000   [ +  +  -  +  :         83 :         SET_FIELD_ARRAY(src_svcid);
          -  +  #  #  #  
             #  #  #  #  
                      # ]
    1001   [ +  +  #  #  :         83 :         SET_FIELD_ARRAY(host_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1002   [ +  +  #  #  :         83 :         SET_FIELD_ARRAY(extended_host_id);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1003   [ +  +  #  #  :         83 :         SET_FIELD(command_set);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1004   [ +  +  #  #  :         83 :         SET_FIELD(admin_timeout_ms);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1005   [ +  +  -  +  :         83 :         SET_FIELD(header_digest);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1006   [ +  +  -  +  :         83 :         SET_FIELD(data_digest);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1007   [ +  +  -  +  :         83 :         SET_FIELD(disable_error_logging);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1008   [ +  +  #  #  :         83 :         SET_FIELD(transport_ack_timeout);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1009   [ +  +  #  #  :         83 :         SET_FIELD(admin_queue_size);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1010   [ +  +  #  #  :         83 :         SET_FIELD(fabrics_connect_timeout_us);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1011   [ +  +  -  +  :         83 :         SET_FIELD(disable_read_ana_log_page);
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1012   [ +  +  #  #  :         83 :         SET_FIELD(disable_read_changed_ns_list_log_page);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1013   [ +  +  #  #  :         83 :         SET_FIELD(tls_psk);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1014   [ +  +  #  #  :         83 :         SET_FIELD(dhchap_key);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1015   [ +  +  #  #  :         83 :         SET_FIELD(dhchap_ctrlr_key);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1016   [ +  +  #  #  :         83 :         SET_FIELD(dhchap_digests);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1017   [ +  +  #  #  :         83 :         SET_FIELD(dhchap_dhgroups);
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1018                 :            : 
    1019                 :            : #undef FIELD_OK
    1020                 :            : #undef SET_FIELD
    1021                 :            : #undef SET_FIELD_ARRAY
    1022                 :         83 : }
    1023                 :            : 
    1024                 :            : struct spdk_nvme_ctrlr *
    1025                 :       1339 : spdk_nvme_connect(const struct spdk_nvme_transport_id *trid,
    1026                 :            :                   const struct spdk_nvme_ctrlr_opts *opts, size_t opts_size)
    1027                 :            : {
    1028                 :            :         int rc;
    1029                 :       1339 :         struct spdk_nvme_ctrlr *ctrlr = NULL;
    1030                 :            :         struct spdk_nvme_probe_ctx *probe_ctx;
    1031                 :       1339 :         struct spdk_nvme_ctrlr_opts *opts_local_p = NULL;
    1032                 :         60 :         struct spdk_nvme_ctrlr_opts opts_local;
    1033                 :         60 :         char hostnqn[SPDK_NVMF_NQN_MAX_LEN + 1];
    1034                 :            : 
    1035         [ +  + ]:       1339 :         if (trid == NULL) {
    1036                 :          4 :                 SPDK_ERRLOG("No transport ID specified\n");
    1037                 :          4 :                 return NULL;
    1038                 :            :         }
    1039                 :            : 
    1040                 :       1335 :         rc = nvme_driver_init();
    1041         [ +  + ]:       1335 :         if (rc != 0) {
    1042                 :          4 :                 return NULL;
    1043                 :            :         }
    1044                 :            : 
    1045                 :       1331 :         nvme_get_default_hostnqn(hostnqn, sizeof(hostnqn));
    1046         [ +  + ]:       1331 :         if (opts) {
    1047                 :         83 :                 opts_local_p = &opts_local;
    1048                 :         83 :                 nvme_ctrlr_opts_init(opts_local_p, opts, opts_size);
    1049   [ #  #  #  # ]:         83 :                 memcpy(hostnqn, opts_local.hostnqn, sizeof(hostnqn));
    1050                 :          7 :         }
    1051                 :            : 
    1052                 :       1331 :         probe_ctx = spdk_nvme_connect_async(trid, opts_local_p, NULL);
    1053         [ +  + ]:       1331 :         if (!probe_ctx) {
    1054                 :          0 :                 SPDK_ERRLOG("Create probe context failed\n");
    1055                 :          0 :                 return NULL;
    1056                 :            :         }
    1057                 :            : 
    1058                 :       1331 :         rc = nvme_init_controllers(probe_ctx);
    1059         [ +  + ]:       1331 :         if (rc != 0) {
    1060                 :          0 :                 return NULL;
    1061                 :            :         }
    1062                 :            : 
    1063                 :       1331 :         ctrlr = nvme_get_ctrlr_by_trid(trid, hostnqn);
    1064                 :            : 
    1065                 :       1331 :         return ctrlr;
    1066                 :        861 : }
    1067                 :            : 
    1068                 :            : void
    1069                 :     148978 : spdk_nvme_trid_populate_transport(struct spdk_nvme_transport_id *trid,
    1070                 :            :                                   enum spdk_nvme_transport_type trtype)
    1071                 :            : {
    1072                 :            :         const char *trstring;
    1073                 :            : 
    1074   [ +  -  +  - ]:     148978 :         trid->trtype = trtype;
    1075   [ -  +  +  +  :     148978 :         switch (trtype) {
                +  -  - ]
    1076                 :          0 :         case SPDK_NVME_TRANSPORT_FC:
    1077                 :          0 :                 trstring = SPDK_NVME_TRANSPORT_NAME_FC;
    1078                 :          0 :                 break;
    1079                 :     135114 :         case SPDK_NVME_TRANSPORT_PCIE:
    1080                 :     135388 :                 trstring = SPDK_NVME_TRANSPORT_NAME_PCIE;
    1081                 :     135388 :                 break;
    1082                 :       2083 :         case SPDK_NVME_TRANSPORT_RDMA:
    1083                 :       2083 :                 trstring = SPDK_NVME_TRANSPORT_NAME_RDMA;
    1084                 :       2083 :                 break;
    1085                 :       8958 :         case SPDK_NVME_TRANSPORT_TCP:
    1086                 :      11500 :                 trstring = SPDK_NVME_TRANSPORT_NAME_TCP;
    1087                 :      11500 :                 break;
    1088                 :          0 :         case SPDK_NVME_TRANSPORT_VFIOUSER:
    1089                 :          7 :                 trstring = SPDK_NVME_TRANSPORT_NAME_VFIOUSER;
    1090                 :          7 :                 break;
    1091                 :          0 :         case SPDK_NVME_TRANSPORT_CUSTOM:
    1092                 :          0 :                 trstring = SPDK_NVME_TRANSPORT_NAME_CUSTOM;
    1093                 :          0 :                 break;
    1094                 :          0 :         default:
    1095                 :          0 :                 SPDK_ERRLOG("no available transports\n");
    1096         [ #  # ]:          0 :                 assert(0);
    1097                 :            :                 return;
    1098                 :            :         }
    1099         [ +  + ]:     148978 :         snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", trstring);
    1100                 :       2823 : }
    1101                 :            : 
    1102                 :            : int
    1103                 :       2894 : spdk_nvme_transport_id_populate_trstring(struct spdk_nvme_transport_id *trid, const char *trstring)
    1104                 :            : {
    1105                 :       2894 :         int i = 0;
    1106                 :            : 
    1107   [ +  -  -  + ]:       2894 :         if (trid == NULL || trstring == NULL) {
    1108                 :          0 :                 return -EINVAL;
    1109                 :            :         }
    1110                 :            : 
    1111                 :            :         /* Note: gcc-11 has some false positive -Wstringop-overread warnings with LTO builds if we
    1112                 :            :          * use strnlen here.  So do the trstring copy manually instead.  See GitHub issue #2391.
    1113                 :            :          */
    1114                 :            : 
    1115                 :            :         /* cast official trstring to uppercase version of input. */
    1116   [ +  +  +  +  :      13047 :         while (i < SPDK_NVMF_TRSTRING_MAX_LEN && trstring[i] != 0) {
             +  -  +  + ]
    1117   [ +  -  +  -  :      10153 :                 trid->trstring[i] = toupper(trstring[i]);
          +  -  +  -  +  
                -  +  - ]
    1118         [ +  - ]:      10153 :                 i++;
    1119                 :            :         }
    1120                 :            : 
    1121   [ +  +  +  -  :       2894 :         if (trstring[i] != 0) {
                   +  - ]
    1122                 :          0 :                 return -EINVAL;
    1123                 :            :         } else {
    1124   [ +  -  +  -  :       2894 :                 trid->trstring[i] = 0;
             +  -  +  - ]
    1125                 :       2894 :                 return 0;
    1126                 :            :         }
    1127                 :         93 : }
    1128                 :            : 
    1129                 :            : int
    1130                 :       2790 : spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
    1131                 :            : {
    1132   [ +  +  +  + ]:       2790 :         if (trtype == NULL || str == NULL) {
    1133                 :          8 :                 return -EINVAL;
    1134                 :            :         }
    1135                 :            : 
    1136   [ +  +  +  +  :       2782 :         if (strcasecmp(str, "PCIe") == 0) {
                   +  + ]
    1137         [ +  - ]:        661 :                 *trtype = SPDK_NVME_TRANSPORT_PCIE;
    1138   [ +  +  +  +  :       2150 :         } else if (strcasecmp(str, "RDMA") == 0) {
                   +  - ]
    1139         [ #  # ]:        427 :                 *trtype = SPDK_NVME_TRANSPORT_RDMA;
    1140   [ +  +  +  +  :       1697 :         } else if (strcasecmp(str, "FC") == 0) {
                   +  - ]
    1141         [ #  # ]:          8 :                 *trtype = SPDK_NVME_TRANSPORT_FC;
    1142   [ +  +  +  +  :       1688 :         } else if (strcasecmp(str, "TCP") == 0) {
                   +  + ]
    1143         [ +  - ]:       1612 :                 *trtype = SPDK_NVME_TRANSPORT_TCP;
    1144   [ +  +  +  +  :        127 :         } else if (strcasecmp(str, "VFIOUSER") == 0) {
                   -  + ]
    1145         [ -  + ]:         70 :                 *trtype = SPDK_NVME_TRANSPORT_VFIOUSER;
    1146                 :         14 :         } else {
    1147         [ #  # ]:          4 :                 *trtype = SPDK_NVME_TRANSPORT_CUSTOM;
    1148                 :            :         }
    1149                 :       2782 :         return 0;
    1150                 :        104 : }
    1151                 :            : 
    1152                 :            : const char *
    1153                 :       3231 : spdk_nvme_transport_id_trtype_str(enum spdk_nvme_transport_type trtype)
    1154                 :            : {
    1155   [ +  +  +  +  :       3231 :         switch (trtype) {
                -  -  + ]
    1156                 :       1042 :         case SPDK_NVME_TRANSPORT_PCIE:
    1157                 :       1051 :                 return "PCIe";
    1158                 :        487 :         case SPDK_NVME_TRANSPORT_RDMA:
    1159                 :        488 :                 return "RDMA";
    1160                 :          3 :         case SPDK_NVME_TRANSPORT_FC:
    1161                 :          4 :                 return "FC";
    1162                 :       1683 :         case SPDK_NVME_TRANSPORT_TCP:
    1163                 :       1684 :                 return "TCP";
    1164                 :          0 :         case SPDK_NVME_TRANSPORT_VFIOUSER:
    1165                 :          0 :                 return "VFIOUSER";
    1166                 :          0 :         case SPDK_NVME_TRANSPORT_CUSTOM:
    1167                 :          0 :                 return "CUSTOM";
    1168                 :          3 :         default:
    1169                 :          4 :                 return NULL;
    1170                 :            :         }
    1171                 :         13 : }
    1172                 :            : 
    1173                 :            : int
    1174                 :       1362 : spdk_nvme_transport_id_parse_adrfam(enum spdk_nvmf_adrfam *adrfam, const char *str)
    1175                 :            : {
    1176   [ +  +  +  + ]:       1362 :         if (adrfam == NULL || str == NULL) {
    1177                 :          8 :                 return -EINVAL;
    1178                 :            :         }
    1179                 :            : 
    1180   [ +  +  +  +  :       1354 :         if (strcasecmp(str, "IPv4") == 0) {
                   -  + ]
    1181         [ +  - ]:       1326 :                 *adrfam = SPDK_NVMF_ADRFAM_IPV4;
    1182   [ +  +  +  +  :         82 :         } else if (strcasecmp(str, "IPv6") == 0) {
                   #  # ]
    1183         [ #  # ]:          8 :                 *adrfam = SPDK_NVMF_ADRFAM_IPV6;
    1184   [ +  +  +  +  :         22 :         } else if (strcasecmp(str, "IB") == 0) {
                   #  # ]
    1185         [ #  # ]:          8 :                 *adrfam = SPDK_NVMF_ADRFAM_IB;
    1186   [ +  +  +  +  :         14 :         } else if (strcasecmp(str, "FC") == 0) {
                   #  # ]
    1187         [ #  # ]:          8 :                 *adrfam = SPDK_NVMF_ADRFAM_FC;
    1188                 :          2 :         } else {
    1189                 :          4 :                 return -ENOENT;
    1190                 :            :         }
    1191                 :       1350 :         return 0;
    1192                 :         63 : }
    1193                 :            : 
    1194                 :            : const char *
    1195                 :       5081 : spdk_nvme_transport_id_adrfam_str(enum spdk_nvmf_adrfam adrfam)
    1196                 :            : {
    1197   [ +  +  +  +  :       5081 :         switch (adrfam) {
                      + ]
    1198                 :       4039 :         case SPDK_NVMF_ADRFAM_IPV4:
    1199                 :       4040 :                 return "IPv4";
    1200                 :          3 :         case SPDK_NVMF_ADRFAM_IPV6:
    1201                 :          4 :                 return "IPv6";
    1202                 :          3 :         case SPDK_NVMF_ADRFAM_IB:
    1203                 :          4 :                 return "IB";
    1204                 :          3 :         case SPDK_NVMF_ADRFAM_FC:
    1205                 :          4 :                 return "FC";
    1206                 :       1020 :         default:
    1207                 :       1029 :                 return NULL;
    1208                 :            :         }
    1209                 :         13 : }
    1210                 :            : 
    1211                 :            : static size_t
    1212                 :       1190 : parse_next_key(const char **str, char *key, char *val, size_t key_buf_size, size_t val_buf_size)
    1213                 :            : {
    1214                 :            : 
    1215                 :            :         const char *sep, *sep1;
    1216                 :       1190 :         const char *whitespace = " \t\n";
    1217                 :            :         size_t key_len, val_len;
    1218                 :            : 
    1219   [ +  +  +  +  :       1190 :         *str += strspn(*str, whitespace);
          +  -  +  -  +  
                      - ]
    1220                 :            : 
    1221   [ +  +  +  - ]:       1190 :         sep = strchr(*str, ':');
    1222         [ +  + ]:       1190 :         if (!sep) {
    1223   [ -  +  #  # ]:         58 :                 sep = strchr(*str, '=');
    1224         [ +  + ]:         58 :                 if (!sep) {
    1225                 :          4 :                         SPDK_ERRLOG("Key without ':' or '=' separator\n");
    1226                 :          4 :                         return 0;
    1227                 :            :                 }
    1228                 :          2 :         } else {
    1229   [ +  +  +  - ]:       1132 :                 sep1 = strchr(*str, '=');
    1230   [ +  +  +  + ]:       1132 :                 if ((sep1 != NULL) && (sep1 < sep)) {
    1231                 :         16 :                         sep = sep1;
    1232                 :          4 :                 }
    1233                 :            :         }
    1234                 :            : 
    1235         [ +  - ]:       1186 :         key_len = sep - *str;
    1236         [ +  + ]:       1186 :         if (key_len >= key_buf_size) {
    1237                 :          4 :                 SPDK_ERRLOG("Key length %zu greater than maximum allowed %zu\n",
    1238                 :            :                             key_len, key_buf_size - 1);
    1239                 :          4 :                 return 0;
    1240                 :            :         }
    1241                 :            : 
    1242   [ +  +  +  +  :       1182 :         memcpy(key, *str, key_len);
                   +  - ]
    1243   [ +  -  +  - ]:       1182 :         key[key_len] = '\0';
    1244                 :            : 
    1245   [ +  -  +  - ]:       1182 :         *str += key_len + 1; /* Skip key: */
    1246   [ +  +  +  +  :       1182 :         val_len = strcspn(*str, whitespace);
                   +  - ]
    1247         [ +  + ]:       1182 :         if (val_len == 0) {
    1248                 :          4 :                 SPDK_ERRLOG("Key without value\n");
    1249                 :          4 :                 return 0;
    1250                 :            :         }
    1251                 :            : 
    1252         [ -  + ]:       1178 :         if (val_len >= val_buf_size) {
    1253                 :          0 :                 SPDK_ERRLOG("Value length %zu greater than maximum allowed %zu\n",
    1254                 :            :                             val_len, val_buf_size - 1);
    1255                 :          0 :                 return 0;
    1256                 :            :         }
    1257                 :            : 
    1258   [ -  +  -  +  :       1178 :         memcpy(val, *str, val_len);
                   -  + ]
    1259   [ -  +  -  + ]:       1178 :         val[val_len] = '\0';
    1260                 :            : 
    1261   [ -  +  -  + ]:       1178 :         *str += val_len;
    1262                 :            : 
    1263                 :       1178 :         return val_len;
    1264                 :        175 : }
    1265                 :            : 
    1266                 :            : int
    1267                 :        388 : spdk_nvme_transport_id_parse(struct spdk_nvme_transport_id *trid, const char *str)
    1268                 :            : {
    1269                 :            :         size_t val_len;
    1270                 :        112 :         char key[32];
    1271                 :        112 :         char val[1024];
    1272                 :            : 
    1273   [ +  +  +  + ]:        388 :         if (trid == NULL || str == NULL) {
    1274                 :         12 :                 return -EINVAL;
    1275                 :            :         }
    1276                 :            : 
    1277   [ +  +  +  + ]:       1530 :         while (*str != '\0') {
    1278                 :            : 
    1279                 :       1166 :                 val_len = parse_next_key(&str, key, val, sizeof(key), sizeof(val));
    1280                 :            : 
    1281         [ +  + ]:       1166 :                 if (val_len == 0) {
    1282                 :         12 :                         SPDK_ERRLOG("Failed to parse transport ID\n");
    1283                 :         12 :                         return -EINVAL;
    1284                 :            :                 }
    1285                 :            : 
    1286   [ +  +  +  -  :       1154 :                 if (strcasecmp(key, "trtype") == 0) {
                   +  + ]
    1287         [ +  + ]:        364 :                         if (spdk_nvme_transport_id_populate_trstring(trid, val) != 0) {
    1288                 :          0 :                                 SPDK_ERRLOG("invalid transport '%s'\n", val);
    1289                 :          0 :                                 return -EINVAL;
    1290                 :            :                         }
    1291   [ +  +  +  - ]:        364 :                         if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, val) != 0) {
    1292                 :          0 :                                 SPDK_ERRLOG("Unknown trtype '%s'\n", val);
    1293                 :          0 :                                 return -EINVAL;
    1294                 :            :                         }
    1295   [ +  +  +  -  :        833 :                 } else if (strcasecmp(key, "adrfam") == 0) {
                   +  + ]
    1296   [ +  +  +  - ]:        169 :                         if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, val) != 0) {
    1297                 :          0 :                                 SPDK_ERRLOG("Unknown adrfam '%s'\n", val);
    1298                 :          0 :                                 return -EINVAL;
    1299                 :            :                         }
    1300   [ +  +  +  -  :        648 :                 } else if (strcasecmp(key, "traddr") == 0) {
                   +  + ]
    1301         [ +  + ]:        314 :                         if (val_len > SPDK_NVMF_TRADDR_MAX_LEN) {
    1302                 :          0 :                                 SPDK_ERRLOG("traddr length %zu greater than maximum allowed %u\n",
    1303                 :            :                                             val_len, SPDK_NVMF_TRADDR_MAX_LEN);
    1304                 :          0 :                                 return -EINVAL;
    1305                 :            :                         }
    1306   [ +  +  +  -  :        314 :                         memcpy(trid->traddr, val, val_len + 1);
                   +  - ]
    1307   [ +  +  +  -  :        348 :                 } else if (strcasecmp(key, "trsvcid") == 0) {
                   +  + ]
    1308         [ +  + ]:        169 :                         if (val_len > SPDK_NVMF_TRSVCID_MAX_LEN) {
    1309                 :          0 :                                 SPDK_ERRLOG("trsvcid length %zu greater than maximum allowed %u\n",
    1310                 :            :                                             val_len, SPDK_NVMF_TRSVCID_MAX_LEN);
    1311                 :          0 :                                 return -EINVAL;
    1312                 :            :                         }
    1313   [ +  +  +  -  :        169 :                         memcpy(trid->trsvcid, val, val_len + 1);
                   +  - ]
    1314   [ +  +  +  -  :        165 :                 } else if (strcasecmp(key, "priority") == 0) {
                   +  - ]
    1315         [ +  + ]:          4 :                         if (val_len > SPDK_NVMF_PRIORITY_MAX_LEN) {
    1316                 :          0 :                                 SPDK_ERRLOG("priority length %zu greater than maximum allowed %u\n",
    1317                 :            :                                             val_len, SPDK_NVMF_PRIORITY_MAX_LEN);
    1318                 :          0 :                                 return -EINVAL;
    1319                 :            :                         }
    1320   [ #  #  #  # ]:          4 :                         trid->priority = spdk_strtol(val, 10);
    1321   [ +  +  +  -  :        135 :                 } else if (strcasecmp(key, "subnqn") == 0) {
                   -  + ]
    1322         [ +  + ]:        125 :                         if (val_len > SPDK_NVMF_NQN_MAX_LEN) {
    1323                 :          0 :                                 SPDK_ERRLOG("subnqn length %zu greater than maximum allowed %u\n",
    1324                 :            :                                             val_len, SPDK_NVMF_NQN_MAX_LEN);
    1325                 :          0 :                                 return -EINVAL;
    1326                 :            :                         }
    1327   [ +  +  +  -  :        125 :                         memcpy(trid->subnqn, val, val_len + 1);
                   +  - ]
    1328   [ -  +  #  #  :         36 :                 } else if (strcasecmp(key, "hostaddr") == 0) {
                   #  # ]
    1329                 :          0 :                         continue;
    1330   [ -  +  #  #  :          9 :                 } else if (strcasecmp(key, "hostsvcid") == 0) {
                   #  # ]
    1331                 :          0 :                         continue;
    1332   [ +  +  #  #  :          9 :                 } else if (strcasecmp(key, "hostnqn") == 0) {
                   #  # ]
    1333                 :          3 :                         continue;
    1334   [ +  +  #  #  :          6 :                 } else if (strcasecmp(key, "ns") == 0) {
                   #  # ]
    1335                 :            :                         /*
    1336                 :            :                          * Special case.  The namespace id parameter may
    1337                 :            :                          * optionally be passed in the transport id string
    1338                 :            :                          * for an SPDK application (e.g. spdk_nvme_perf)
    1339                 :            :                          * and additionally parsed therein to limit
    1340                 :            :                          * targeting a specific namespace.  For this
    1341                 :            :                          * scenario, just silently ignore this key
    1342                 :            :                          * rather than letting it default to logging
    1343                 :            :                          * it as an invalid key.
    1344                 :            :                          */
    1345                 :          5 :                         continue;
    1346   [ +  -  #  #  :          1 :                 } else if (strcasecmp(key, "alt_traddr") == 0) {
                   #  # ]
    1347                 :            :                         /*
    1348                 :            :                          * Used by applications for enabling transport ID failover.
    1349                 :            :                          * Please see the case above for more information on custom parameters.
    1350                 :            :                          */
    1351                 :          1 :                         continue;
    1352                 :            :                 } else {
    1353                 :          0 :                         SPDK_ERRLOG("Unknown transport ID key '%s'\n", key);
    1354                 :            :                 }
    1355                 :            :         }
    1356                 :            : 
    1357                 :        364 :         return 0;
    1358                 :         49 : }
    1359                 :            : 
    1360                 :            : int
    1361                 :         12 : spdk_nvme_host_id_parse(struct spdk_nvme_host_id *hostid, const char *str)
    1362                 :          9 : {
    1363                 :            : 
    1364                 :         12 :         size_t key_size = 32;
    1365                 :         12 :         size_t val_size = 1024;
    1366                 :            :         size_t val_len;
    1367         [ -  + ]:         12 :         char key[key_size];
    1368         [ -  + ]:         12 :         char val[val_size];
    1369                 :            : 
    1370   [ +  -  -  + ]:         12 :         if (hostid == NULL || str == NULL) {
    1371                 :          0 :                 return -EINVAL;
    1372                 :            :         }
    1373                 :            : 
    1374   [ +  +  #  # ]:         24 :         while (*str != '\0') {
    1375                 :            : 
    1376                 :         12 :                 val_len = parse_next_key(&str, key, val, key_size, val_size);
    1377                 :            : 
    1378         [ +  + ]:         12 :                 if (val_len == 0) {
    1379                 :          0 :                         SPDK_ERRLOG("Failed to parse host ID\n");
    1380                 :          0 :                         return val_len;
    1381                 :            :                 }
    1382                 :            : 
    1383                 :            :                 /* Ignore the rest of the options from the transport ID. */
    1384   [ +  +  +  +  :         12 :                 if (strcasecmp(key, "trtype") == 0) {
                   #  # ]
    1385                 :          4 :                         continue;
    1386   [ +  +  -  +  :          8 :                 } else if (strcasecmp(key, "adrfam") == 0) {
                   #  # ]
    1387                 :          0 :                         continue;
    1388   [ +  +  -  +  :          8 :                 } else if (strcasecmp(key, "traddr") == 0) {
                   #  # ]
    1389                 :          0 :                         continue;
    1390   [ +  +  -  +  :          8 :                 } else if (strcasecmp(key, "trsvcid") == 0) {
                   #  # ]
    1391                 :          0 :                         continue;
    1392   [ +  +  -  +  :          8 :                 } else if (strcasecmp(key, "subnqn") == 0) {
                   #  # ]
    1393                 :          0 :                         continue;
    1394   [ +  +  -  +  :          8 :                 } else if (strcasecmp(key, "priority") == 0) {
                   #  # ]
    1395                 :          0 :                         continue;
    1396   [ +  +  -  +  :          8 :                 } else if (strcasecmp(key, "ns") == 0) {
                   #  # ]
    1397                 :          0 :                         continue;
    1398   [ +  +  +  +  :          8 :                 } else if (strcasecmp(key, "hostaddr") == 0) {
                   #  # ]
    1399         [ +  + ]:          4 :                         if (val_len > SPDK_NVMF_TRADDR_MAX_LEN) {
    1400                 :          0 :                                 SPDK_ERRLOG("hostaddr length %zu greater than maximum allowed %u\n",
    1401                 :            :                                             val_len, SPDK_NVMF_TRADDR_MAX_LEN);
    1402                 :          0 :                                 return -EINVAL;
    1403                 :            :                         }
    1404   [ -  +  -  +  :          4 :                         memcpy(hostid->hostaddr, val, val_len + 1);
                   #  # ]
    1405                 :            : 
    1406   [ +  +  +  -  :          5 :                 } else if (strcasecmp(key, "hostsvcid") == 0) {
                   #  # ]
    1407         [ -  + ]:          4 :                         if (val_len > SPDK_NVMF_TRSVCID_MAX_LEN) {
    1408                 :          0 :                                 SPDK_ERRLOG("trsvcid length %zu greater than maximum allowed %u\n",
    1409                 :            :                                             val_len, SPDK_NVMF_TRSVCID_MAX_LEN);
    1410                 :          0 :                                 return -EINVAL;
    1411                 :            :                         }
    1412   [ -  +  -  +  :          4 :                         memcpy(hostid->hostsvcid, val, val_len + 1);
                   #  # ]
    1413                 :          1 :                 } else {
    1414                 :          0 :                         SPDK_ERRLOG("Unknown transport ID key '%s'\n", key);
    1415                 :            :                 }
    1416                 :            :         }
    1417                 :            : 
    1418                 :         12 :         return 0;
    1419                 :          3 : }
    1420                 :            : 
    1421                 :            : static int
    1422                 :      37011 : cmp_int(int a, int b)
    1423                 :            : {
    1424         [ +  - ]:      37011 :         return a - b;
    1425                 :            : }
    1426                 :            : 
    1427                 :            : int
    1428                 :      19285 : spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
    1429                 :            :                                const struct spdk_nvme_transport_id *trid2)
    1430                 :            : {
    1431                 :            :         int cmp;
    1432                 :            : 
    1433   [ +  +  +  -  :      19285 :         if (trid1->trtype == SPDK_NVME_TRANSPORT_CUSTOM) {
                   -  + ]
    1434   [ #  #  #  #  :          0 :                 cmp = strcasecmp(trid1->trstring, trid2->trstring);
             #  #  #  # ]
    1435                 :          0 :         } else {
    1436   [ +  -  +  -  :      19285 :                 cmp = cmp_int(trid1->trtype, trid2->trtype);
             +  -  +  - ]
    1437                 :            :         }
    1438                 :            : 
    1439         [ +  + ]:      19285 :         if (cmp) {
    1440                 :          4 :                 return cmp;
    1441                 :            :         }
    1442                 :            : 
    1443   [ +  +  +  -  :      19281 :         if (trid1->trtype == SPDK_NVME_TRANSPORT_PCIE) {
                   -  + ]
    1444                 :       1213 :                 struct spdk_pci_addr pci_addr1 = {};
    1445                 :       1213 :                 struct spdk_pci_addr pci_addr2 = {};
    1446                 :            : 
    1447                 :            :                 /* Normalize PCI addresses before comparing */
    1448   [ +  -  +  +  :       2401 :                 if (spdk_pci_addr_parse(&pci_addr1, trid1->traddr) < 0 ||
                   #  # ]
    1449         [ #  # ]:       1213 :                     spdk_pci_addr_parse(&pci_addr2, trid2->traddr) < 0) {
    1450                 :          0 :                         return -1;
    1451                 :            :                 }
    1452                 :            : 
    1453                 :            :                 /* PCIe transport ID only uses trtype and traddr */
    1454                 :       1213 :                 return spdk_pci_addr_compare(&pci_addr1, &pci_addr2);
    1455                 :            :         }
    1456                 :            : 
    1457   [ +  +  +  +  :      18068 :         cmp = strcasecmp(trid1->traddr, trid2->traddr);
             +  -  +  - ]
    1458         [ +  + ]:      18068 :         if (cmp) {
    1459                 :        342 :                 return cmp;
    1460                 :            :         }
    1461                 :            : 
    1462   [ +  -  +  -  :      17726 :         cmp = cmp_int(trid1->adrfam, trid2->adrfam);
             +  -  +  - ]
    1463         [ +  + ]:      17726 :         if (cmp) {
    1464                 :          4 :                 return cmp;
    1465                 :            :         }
    1466                 :            : 
    1467   [ +  +  +  +  :      17722 :         cmp = strcasecmp(trid1->trsvcid, trid2->trsvcid);
             +  -  +  - ]
    1468         [ +  + ]:      17722 :         if (cmp) {
    1469                 :       1244 :                 return cmp;
    1470                 :            :         }
    1471                 :            : 
    1472   [ +  +  +  +  :      16478 :         cmp = strcmp(trid1->subnqn, trid2->subnqn);
             +  -  +  - ]
    1473         [ +  + ]:      16478 :         if (cmp) {
    1474                 :        596 :                 return cmp;
    1475                 :            :         }
    1476                 :            : 
    1477                 :      15882 :         return 0;
    1478                 :       3689 : }
    1479                 :            : 
    1480                 :            : int
    1481                 :         16 : spdk_nvme_prchk_flags_parse(uint32_t *prchk_flags, const char *str)
    1482                 :            : {
    1483                 :            :         size_t val_len;
    1484                 :         12 :         char key[32];
    1485                 :         12 :         char val[1024];
    1486                 :            : 
    1487   [ +  +  -  + ]:         16 :         if (prchk_flags == NULL || str == NULL) {
    1488                 :          4 :                 return -EINVAL;
    1489                 :            :         }
    1490                 :            : 
    1491   [ +  +  #  # ]:         27 :         while (*str != '\0') {
    1492                 :         12 :                 val_len = parse_next_key(&str, key, val, sizeof(key), sizeof(val));
    1493                 :            : 
    1494         [ +  + ]:         12 :                 if (val_len == 0) {
    1495                 :          0 :                         SPDK_ERRLOG("Failed to parse prchk\n");
    1496                 :          0 :                         return -EINVAL;
    1497                 :            :                 }
    1498                 :            : 
    1499   [ +  +  #  #  :         12 :                 if (strcasecmp(key, "prchk") == 0) {
                   #  # ]
    1500   [ +  +  #  #  :         12 :                         if (strcasestr(val, "reftag") != NULL) {
                   #  # ]
    1501   [ #  #  #  # ]:          8 :                                 *prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_REFTAG;
    1502                 :          2 :                         }
    1503   [ +  +  #  #  :         12 :                         if (strcasestr(val, "guard") != NULL) {
                   #  # ]
    1504   [ #  #  #  # ]:          8 :                                 *prchk_flags |= SPDK_NVME_IO_FLAGS_PRCHK_GUARD;
    1505                 :          2 :                         }
    1506                 :          3 :                 } else {
    1507                 :          0 :                         SPDK_ERRLOG("Unknown key '%s'\n", key);
    1508                 :          0 :                         return -EINVAL;
    1509                 :            :                 }
    1510                 :            :         }
    1511                 :            : 
    1512                 :         12 :         return 0;
    1513                 :          4 : }
    1514                 :            : 
    1515                 :            : const char *
    1516                 :         12 : spdk_nvme_prchk_flags_str(uint32_t prchk_flags)
    1517                 :            : {
    1518   [ +  +  #  # ]:         12 :         if (prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_REFTAG) {
    1519   [ +  +  #  # ]:          8 :                 if (prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_GUARD) {
    1520                 :          4 :                         return "prchk:reftag|guard";
    1521                 :            :                 } else {
    1522                 :          4 :                         return "prchk:reftag";
    1523                 :            :                 }
    1524                 :            :         } else {
    1525   [ +  -  #  # ]:          4 :                 if (prchk_flags & SPDK_NVME_IO_FLAGS_PRCHK_GUARD) {
    1526                 :          4 :                         return "prchk:guard";
    1527                 :            :                 } else {
    1528                 :          0 :                         return NULL;
    1529                 :            :                 }
    1530                 :            :         }
    1531                 :          3 : }
    1532                 :            : 
    1533                 :            : int
    1534                 :      36681 : spdk_nvme_scan_attached(const struct spdk_nvme_transport_id *trid)
    1535                 :            : {
    1536                 :            :         int rc;
    1537                 :            :         struct spdk_nvme_probe_ctx *probe_ctx;
    1538                 :            : 
    1539                 :      36681 :         rc = nvme_driver_init();
    1540         [ -  + ]:      36681 :         if (rc != 0) {
    1541                 :          0 :                 return rc;
    1542                 :            :         }
    1543                 :            : 
    1544                 :      36681 :         probe_ctx = calloc(1, sizeof(*probe_ctx));
    1545         [ +  + ]:      36681 :         if (!probe_ctx) {
    1546                 :          0 :                 return -ENOMEM;
    1547                 :            :         }
    1548                 :            : 
    1549                 :      36681 :         nvme_probe_ctx_init(probe_ctx, trid, NULL, NULL, NULL, NULL, NULL, NULL);
    1550                 :            : 
    1551         [ -  + ]:      36681 :         nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
    1552                 :      36681 :         rc = nvme_transport_ctrlr_scan_attached(probe_ctx);
    1553         [ -  + ]:      36681 :         nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
    1554                 :      36681 :         free(probe_ctx);
    1555                 :            : 
    1556         [ +  + ]:      36681 :         return rc < 0 ? rc : 0;
    1557                 :        215 : }
    1558                 :            : 
    1559                 :            : struct spdk_nvme_probe_ctx *
    1560                 :       3893 : spdk_nvme_probe_async(const struct spdk_nvme_transport_id *trid,
    1561                 :            :                       void *cb_ctx,
    1562                 :            :                       spdk_nvme_probe_cb probe_cb,
    1563                 :            :                       spdk_nvme_attach_cb attach_cb,
    1564                 :            :                       spdk_nvme_remove_cb remove_cb)
    1565                 :            : {
    1566                 :       3893 :         return spdk_nvme_probe_async_ext(trid, cb_ctx, probe_cb, attach_cb, NULL, remove_cb);
    1567                 :            : }
    1568                 :            : 
    1569                 :            : struct spdk_nvme_probe_ctx *
    1570                 :      97752 : spdk_nvme_probe_async_ext(const struct spdk_nvme_transport_id *trid,
    1571                 :            :                           void *cb_ctx,
    1572                 :            :                           spdk_nvme_probe_cb probe_cb,
    1573                 :            :                           spdk_nvme_attach_cb attach_cb,
    1574                 :            :                           spdk_nvme_attach_fail_cb attach_fail_cb,
    1575                 :            :                           spdk_nvme_remove_cb remove_cb)
    1576                 :            : {
    1577                 :            :         int rc;
    1578                 :            :         struct spdk_nvme_probe_ctx *probe_ctx;
    1579                 :            : 
    1580                 :      97752 :         rc = nvme_driver_init();
    1581         [ +  + ]:      97752 :         if (rc != 0) {
    1582                 :          4 :                 return NULL;
    1583                 :            :         }
    1584                 :            : 
    1585                 :      97748 :         probe_ctx = calloc(1, sizeof(*probe_ctx));
    1586         [ +  + ]:      97748 :         if (!probe_ctx) {
    1587                 :          0 :                 return NULL;
    1588                 :            :         }
    1589                 :            : 
    1590                 :      97766 :         nvme_probe_ctx_init(probe_ctx, trid, NULL, cb_ctx, probe_cb, attach_cb, attach_fail_cb,
    1591                 :         18 :                             remove_cb);
    1592                 :      97748 :         rc = nvme_probe_internal(probe_ctx, false);
    1593         [ +  + ]:      97748 :         if (rc != 0) {
    1594                 :          6 :                 free(probe_ctx);
    1595                 :          6 :                 return NULL;
    1596                 :            :         }
    1597                 :            : 
    1598                 :      97742 :         return probe_ctx;
    1599                 :         19 : }
    1600                 :            : 
    1601                 :            : int
    1602                 :  153377205 : spdk_nvme_probe_poll_async(struct spdk_nvme_probe_ctx *probe_ctx)
    1603                 :            : {
    1604                 :            :         struct spdk_nvme_ctrlr *ctrlr, *ctrlr_tmp;
    1605                 :            : 
    1606   [ +  +  +  +  :  153377205 :         if (!spdk_process_is_primary() && probe_ctx->trid.trtype == SPDK_NVME_TRANSPORT_PCIE) {
          #  #  #  #  #  
                      # ]
    1607                 :        178 :                 free(probe_ctx);
    1608                 :        178 :                 return 0;
    1609                 :            :         }
    1610                 :            : 
    1611   [ +  +  +  +  :  306684025 :         TAILQ_FOREACH_SAFE(ctrlr, &probe_ctx->init_ctrlrs, tailq, ctrlr_tmp) {
          +  -  +  +  +  
          -  +  -  +  -  
                   +  + ]
    1612                 :  153306998 :                 nvme_ctrlr_poll_internal(ctrlr, probe_ctx);
    1613                 :   32444299 :         }
    1614                 :            : 
    1615   [ +  +  +  -  :  153377027 :         if (TAILQ_EMPTY(&probe_ctx->init_ctrlrs)) {
             +  -  +  + ]
    1616         [ -  + ]:     100476 :                 nvme_robust_mutex_lock(&g_spdk_nvme_driver->lock);
    1617   [ -  +  -  + ]:     100476 :                 g_spdk_nvme_driver->initialized = true;
    1618         [ -  + ]:     100476 :                 nvme_robust_mutex_unlock(&g_spdk_nvme_driver->lock);
    1619                 :     100476 :                 free(probe_ctx);
    1620                 :     100476 :                 return 0;
    1621                 :            :         }
    1622                 :            : 
    1623                 :  153276551 :         return -EAGAIN;
    1624                 :   32444310 : }
    1625                 :            : 
    1626                 :            : struct spdk_nvme_probe_ctx *
    1627                 :       2916 : spdk_nvme_connect_async(const struct spdk_nvme_transport_id *trid,
    1628                 :            :                         const struct spdk_nvme_ctrlr_opts *opts,
    1629                 :            :                         spdk_nvme_attach_cb attach_cb)
    1630                 :            : {
    1631                 :            :         int rc;
    1632                 :       2916 :         spdk_nvme_probe_cb probe_cb = NULL;
    1633                 :            :         struct spdk_nvme_probe_ctx *probe_ctx;
    1634                 :            : 
    1635                 :       2916 :         rc = nvme_driver_init();
    1636         [ -  + ]:       2916 :         if (rc != 0) {
    1637                 :          0 :                 return NULL;
    1638                 :            :         }
    1639                 :            : 
    1640                 :       2916 :         probe_ctx = calloc(1, sizeof(*probe_ctx));
    1641         [ +  + ]:       2916 :         if (!probe_ctx) {
    1642                 :          0 :                 return NULL;
    1643                 :            :         }
    1644                 :            : 
    1645         [ +  + ]:       2916 :         if (opts) {
    1646                 :       1668 :                 probe_cb = nvme_connect_probe_cb;
    1647                 :         18 :         }
    1648                 :            : 
    1649                 :       2916 :         nvme_probe_ctx_init(probe_ctx, trid, opts, (void *)opts, probe_cb, attach_cb, NULL, NULL);
    1650                 :       2916 :         rc = nvme_probe_internal(probe_ctx, true);
    1651         [ +  + ]:       2916 :         if (rc != 0) {
    1652                 :         16 :                 free(probe_ctx);
    1653                 :         16 :                 return NULL;
    1654                 :            :         }
    1655                 :            : 
    1656                 :       2900 :         return probe_ctx;
    1657                 :        870 : }
    1658                 :            : 
    1659                 :            : int
    1660                 :      19863 : nvme_parse_addr(struct sockaddr_storage *sa, int family, const char *addr, const char *service,
    1661                 :            :                 long int *port)
    1662                 :            : {
    1663                 :        102 :         struct addrinfo *res;
    1664                 :        102 :         struct addrinfo hints;
    1665                 :            :         int ret;
    1666                 :            : 
    1667         [ +  + ]:      19863 :         memset(&hints, 0, sizeof(hints));
    1668         [ +  - ]:      19863 :         hints.ai_family = family;
    1669         [ +  - ]:      19863 :         hints.ai_socktype = SOCK_STREAM;
    1670         [ +  - ]:      19863 :         hints.ai_protocol = 0;
    1671                 :            : 
    1672         [ +  + ]:      19863 :         if (service != NULL) {
    1673         [ +  - ]:      19847 :                 *port = spdk_strtol(service, 10);
    1674   [ +  -  +  +  :      19847 :                 if (*port <= 0 || *port >= 65536) {
             +  -  -  + ]
    1675                 :          0 :                         SPDK_ERRLOG("Invalid port: %s\n", service);
    1676                 :          0 :                         return -EINVAL;
    1677                 :            :                 }
    1678                 :       1679 :         }
    1679                 :            : 
    1680                 :      19863 :         ret = getaddrinfo(addr, service, &hints, &res);
    1681         [ +  + ]:      19863 :         if (ret) {
    1682                 :          4 :                 SPDK_ERRLOG("getaddrinfo failed: %s (%d)\n", gai_strerror(ret), ret);
    1683         [ #  # ]:          4 :                 return -(abs(ret));
    1684                 :            :         }
    1685                 :            : 
    1686   [ +  +  +  -  :      19859 :         if (res->ai_addrlen > sizeof(*sa)) {
                   -  + ]
    1687   [ #  #  #  # ]:          0 :                 SPDK_ERRLOG("getaddrinfo() ai_addrlen %zu too large\n", (size_t)res->ai_addrlen);
    1688                 :          0 :                 ret = -EINVAL;
    1689                 :          0 :         } else {
    1690   [ +  +  +  +  :      19859 :                 memcpy(sa, res->ai_addr, res->ai_addrlen);
          +  -  +  -  +  
                -  +  - ]
    1691                 :            :         }
    1692                 :            : 
    1693                 :      19859 :         freeaddrinfo(res);
    1694                 :      19859 :         return ret;
    1695                 :       1680 : }
    1696                 :            : 
    1697                 :            : int
    1698                 :       6496 : nvme_get_default_hostnqn(char *buf, int len)
    1699                 :            : {
    1700                 :        885 :         char uuid[SPDK_UUID_STRING_LEN];
    1701                 :            :         int rc;
    1702                 :            : 
    1703         [ +  - ]:       6496 :         spdk_uuid_fmt_lower(uuid, sizeof(uuid), &g_spdk_nvme_driver->default_extended_host_id);
    1704         [ -  + ]:       6496 :         rc = snprintf(buf, len, "nqn.2014-08.org.nvmexpress:uuid:%s", uuid);
    1705   [ +  -  -  + ]:       6496 :         if (rc < 0 || rc >= len) {
    1706                 :          0 :                 return -EINVAL;
    1707                 :            :         }
    1708                 :            : 
    1709                 :       6496 :         return 0;
    1710                 :       1766 : }
    1711                 :            : 
    1712                 :       2575 : SPDK_LOG_REGISTER_COMPONENT(nvme)

Generated by: LCOV version 1.15